File size: 2,877 Bytes
7dc685b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 'use strict';
// PHP file parsers for controllers, Eloquent models, migrations, middleware,
// and Blade views. Split out of parser.js for size.
const fs = require('fs');
const path = require('path');
function tryRead(p) {
try { return fs.readFileSync(p, 'utf8'); } catch { return null; }
}
function listPhp(dir) {
if (!fs.existsSync(dir)) return [];
return fs.readdirSync(dir)
.filter(f => f.endsWith('.php'))
.map(f => path.join(dir, f));
}
// Parse a controller PHP file: class name + public methods.
function parseController(file) {
const src = tryRead(file) || '';
const cls = (src.match(/class\s+([A-Za-z0-9_]+)/) || [])[1] || path.basename(file, '.php');
const methods = [];
const re = /public\s+function\s+([A-Za-z0-9_]+)\s*\(/g;
let m;
while ((m = re.exec(src))) methods.push(m[1]);
return { file, class: cls, methods };
}
// Parse an Eloquent model: class name + table + fillable.
function parseModel(file) {
const src = tryRead(file) || '';
const cls = (src.match(/class\s+([A-Za-z0-9_]+)/) || [])[1] || path.basename(file, '.php');
const table = (src.match(/protected\s+\\\$table\s*=\s*['"]([^'"]+)['"]/) || [])[1];
const fillableMatch = src.match(/protected\s+\\\$fillable\s*=\s*\[([^\]]*)\]/);
let fillable = [];
if (fillableMatch) {
fillable = fillableMatch[1].match(/['"]([A-Za-z0-9_]+)['"]/g) || [];
fillable = fillable.map(s => s.replace(/^['"]|['"]$/g, ''));
}
return { file, class: cls, table: table || cls.toLowerCase() + 's', fillable };
}
// Parse a migration: table name from Schema::create('x', ...) + columns.
function parseMigration(file) {
const src = tryRead(file) || '';
const m = src.match(/Schema::create\s*\(\s*['"]([A-Za-z0-9_]+)['"]/);
if (!m) return null;
const table = m[1];
const cols = [];
const colRe = /\\\$table->([a-zA-Z]+)\s*\(\s*['"]([A-Za-z0-9_]+)['"]/g;
let cm;
while ((cm = colRe.exec(src))) {
cols.push({ type: cm[1], name: cm[2] });
}
return { file, table, cols };
}
// Parse a middleware class: class name.
function parseMiddleware(file) {
const src = tryRead(file) || '';
const cls = (src.match(/class\s+([A-Za-z0-9_]+)/) || [])[1] || path.basename(file, '.php');
return { file, class: cls };
}
// List Blade views (recursive).
function listBlade(dir, base) {
base = base || dir;
const out = [];
if (!fs.existsSync(dir)) return out;
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, e.name);
if (e.isDirectory()) out.push(...listBlade(full, base));
else if (e.name.endsWith('.blade.php')) {
const rel = path.relative(base, full).replace(/\.blade\.php$/, '').replace(/\//g, '.');
out.push({ file: full, name: rel });
}
}
return out;
}
module.exports = {
tryRead, listPhp, parseController, parseModel, parseMigration,
parseMiddleware, listBlade,
};
|