Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/core/actions/config/create-model.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@

$namespace = implode("\\", $parts);

$nest = str_replace("\\","/",$namespace);


if(strlen($name) <= 0){
throw new Exception('empty_model_name', QN_ERROR_INVALID_PARAM);
}
Expand All @@ -62,7 +65,7 @@
}

// Verification de la non existence du model
$file = QN_BASEDIR."/packages/{$package}/classes/{$model_path}.class.php";
$file = QN_BASEDIR."/packages/{$package}/classes/{$nest}/{$name}.class.php";

if(file_exists($file)) {
throw new Exception('model_already_exists', QN_ERROR_INVALID_PARAM);
Expand All @@ -88,7 +91,7 @@
}

// create folder if missing
$dir = QN_BASEDIR."/packages/{$package}/classes/".str_replace("\\","/",$namespace);
$dir = QN_BASEDIR."/packages/{$package}/classes/".$nest;
$d = mkdir($dir, 0777, true);

$f = fopen($file,"w");
Expand Down
11 changes: 11 additions & 0 deletions packages/core/actions/config/create-view.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@
throw new Exception('view_already_exists', QN_ERROR_INVALID_PARAM);
}

$nest = explode("/",$entity);
array_pop($nest);
$path = implode("/",$nest);

if(!is_dir(QN_BASEDIR."/packages/{$package}/views/{$path}")){
mkdir(QN_BASEDIR."/packages/{$package}/views/{$path}",0777,true);
if(!is_dir(QN_BASEDIR."/packages/{$package}/views/{$path}")) {
throw new Exception('file_access_denied', QN_ERROR_UNKNOWN);
}
}

$f = fopen($file,"w");

if(!$f) {
Expand Down
5 changes: 4 additions & 1 deletion packages/core/actions/config/delete-model.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@

$namespace = implode("\\", $parts);


$nest = str_replace("\\","/",$namespace);

if(strlen($name) <= 0){
throw new Exception('empty_model_name', QN_ERROR_INVALID_PARAM);
}
Expand All @@ -57,7 +60,7 @@
}

// Verification de la non existence du model
$file = QN_BASEDIR."/packages/{$package}/classes/{$model_path}.class.php";
$file = QN_BASEDIR."/packages/{$package}/classes/{$nest}/{$name}.class.php";

if(!file_exists($file)) {
throw new Exception('model_does_not_exists', QN_ERROR_INVALID_PARAM);
Expand Down
184 changes: 184 additions & 0 deletions packages/core/actions/config/update-controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php
/*
This file is part of the eQual framework <http://www.github.com/cedricfrancoys/equal>
Some Rights Reserved, Cedric Francoys, 2010-2021
Licensed under GNU LGPL 3 license <http://www.gnu.org/licenses/>
*/
use PhpParser\{Node, NodeTraverser, NodeVisitorAbstract, ParserFactory, NodeFinder, NodeDumper, PrettyPrinter, BuilderFactory, Comment};
use PhpParser\Node\Expr\CallLike;
use equal\orm\Model;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;

list($params, $providers) = eQual::announce([
'description' => "Translate an entity definition to a PHP file and store it in related package dir.",
'help' => "This controller rely on the PHP binary. In order to make them work, sure the PHP binary is present in the PATH.",
'response' => [
'content-type' => 'text/plain',
'charset' => 'UTF-8',
'accept-origin' => '*'
],
'params' => [
'controller' => [
'description' => 'Name of the controller.',
'type' => 'string',
// 'required' => true
],
'operation' => [
'description' => 'Operation the controller relates to.',
'type' => 'string',
'selection' => [
'do',
'get',
'show'
]
],
'payload' => [
'description' => 'Controller `announce` descriptor.',
'type' => 'array',
// 'required' => true
]
],
'providers' => ['context', 'orm']
]);

/**
* @var \equal\php\Context $context
* @var \equal\orm\ObjectManager $orm
*/
list($context, $orm) = [$providers['context'], $providers['orm']];

// Create all the object to use for using PhpParser
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$nodeFinder = new NodeFinder;
$traverser = new NodeTraverser;
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;

// Get the parts of the entity string, separated by backslashes
$params['entity'] = str_replace('_', '\\', $params['entity']);
$parts = explode('\\', $params['entity']);

// Get the package name from the first part of the string
$package = array_shift($parts);
// Get the file name from the last part of the string
$filename = array_pop($parts);
// Get the class path from the remaining part
$class_path = implode('/', $parts);


// Get a string representation from the code_php variable, with backslashes escaped
$code_string = str_replace("\\\\", "\\", var_export($params['payload'], true));

// #test #toremove
// $code_string = "[
// 'description' => \"save a representation of a view to a json file\",
// 'response' => [
// 'content-type' => 'text/plain',
// 'charset' => 'UTF-8',
// 'accept-origin' => '*',
// 'schema' => [
// 'type' => 'entity',
// 'qty' => 'one',
// 'entity' => 'core\User',
// 'values' => []
// ]
// ],
// 'params' => [
// 'entity' => [
// 'description' => 'name of the entity',
// 'type' => 'string',
// 'required' => true
// ],
// 'view_id' => [
// 'description' => 'id of the view',
// 'type' => 'string',
// 'required' => true
// ],
// ],
// 'access' => [
// 'visibility' => 'protected',
// 'groups' => ['admins']
// ],
// 'providers' => ['context']
// ]";

// Create a virtual file holding the default structure, and generate a minimal AST
$ast_temp = $parser->parse("<?php \nlist(\$params, \$providers) = eQual::announce($code_string);");


/** @var Node $node */
$node = $nodeFinder->findFirst($ast_temp, function(Node $node) {
// support for `announce`
if(get_class($node) == 'PhpParser\Node\Expr\FuncCall' && property_exists($node, 'name') && get_class($node->name) == 'PhpParser\Node\Name' && $node->name->getFirst() == 'announce') {
return true;
}
// support for `eQual::announce`
if(get_class($node) == 'PhpParser\Node\Expr\StaticCall' && property_exists($node, 'class') && get_class($node->class) == 'PhpParser\Node\Name' && $node->class->getFirst() == 'eQual') {
return property_exists($node, 'name') && get_class($node->name) == 'PhpParser\Node\Identifier' && $node->name->name == 'announce';
}
return false;
});

// Add a visitor to the traverse in order to consider the getColumns method and update its content with new schema
$traverser->addVisitor(
new class($node) extends NodeVisitorAbstract {
private $node;

public function __construct($node) {
$this->node = $node;
}

public function leaveNode(Node $node) {
if ($node->name->name === 'announce') {
return $this->node;
}
}
}
);

// Get the full path of the file
$dir = ['do' => 'actions', 'get' => 'date', 'show' => 'apps'][$params['operation']];
$file = QN_BASEDIR."/packages/{$package}/{$dir}/{$class_path}/{$filename}.php";

// Get the code from the original file ...
$code = file_get_contents($file);
// ... and parse it to create an AST
$stmtOriginal = $parser->parse($code);


// #test #toremove fake original file
// $stmtOriginal = $parser->parse("<?php \nlist(\$params, \$providers) = eQual::announce([]);
// /**
// * @var \\equal\\php\\Context \$context
// */
// list(\$context) = [\$providers['context']];

// \$parts = explode(\"\\\\\",\$params['entity']);
// \$parts_v = explode(\".\",\$params['view_id']);
// ");

// Update the AST by using visitors attached to the traverser
$stmtModified = $traverser->traverse($stmtOriginal);
// Pretty print the modified AST ...
$result = $prettyPrinter->prettyPrintFile($stmtModified);

// ... and write back the code to the file
file_put_contents($file, $result);

try {
// apply coding standards (ecs.php is expected in QN_BASEDIR)
$command = 'php ./vendor/bin/ecs check "' . str_replace('\\', '/', $file) . '" --fix';

if(exec($command) === false) {
throw new Exception('command_failed', QN_ERROR_UNKNOWN);
}
}
catch(Exception $e) {
trigger_error("PHP::unable to beautify rendered file ($file): ".$e->getMessage(), QN_REPORT_INFO);
}

$result = file_get_contents($file);

$context->httpResponse()
->body($result)
->send();
Loading