Skip to content

Commit

Permalink
Merge pull request #3 from JBDevLabs/master
Browse files Browse the repository at this point in the history
Improve YAML convert
  • Loading branch information
mamazu authored Jan 3, 2024
2 parents d73396f + c100af0 commit bbbc2e6
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 67 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Converts a yaml configuration file from the [SyliusGridBundle](https://github.co
## How to use:
* Clone the repository
* `composer install`
* `bin/config-converter <path> [namespace] [--functional]`
* `bin/config-converter <path> [namespace] [--functional] [--output-directory <path>] [-q]`

This will print the generated code out to the screen and produce a file that contains the new configuration.

Expand Down
30 changes: 25 additions & 5 deletions bin/config-converter
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@

use Mamazu\ConfigConverter\ClassConfigConverter;

require_once __DIR__."/../vendor/autoload.php";
require_once __DIR__."/../src/ClassConfigConverter.php";
require_once __DIR__."/../src/GridBuilderCalls.php";
require_once __DIR__ . "/../vendor/autoload.php";
require_once __DIR__ . "/../src/ClassConfigConverter.php";
require_once __DIR__ . "/../src/GridBuilderCalls.php";

if (count($argv) < 2) {
echo "Usage: bin/config-transformer <file to convert> [grid namespace]\n";
echo "\t<file to convert>: must be in the yaml / yml format\n";
echo "\t[grid namespace]: (optional) Namespace of the grid class that is generated";
echo "\t[--function]: (optional) Generating the functional version of it";
echo "\t[--output-directory <path>]: (optional) Save the file in directory";
echo "\t[--functional]: (optional) Generating the functional version of it";
echo "\t[-q]: (optional) Quiet";
echo "\n\n";
echo "Example: bin/config-transformer order.yaml \"App\\Env\"\n";
die(1);
Expand All @@ -35,4 +37,22 @@ if (in_array('--functional', $argv, true)) {
$configConverter->setFunctional();
}

$configConverter->convert($argv[1]);
$outputDirectory = getcwd();
if (in_array('--output-directory', $argv, true)) {
$key = array_search('--output-directory', $argv, true);
if (array_key_exists($key + 1, $argv) === false) {
echo 'Please add the output directory after the --output-directory argument';
die(1);
}
$outputDirectory = $argv[$key + 1];
if (
is_dir($outputDirectory) === false
&& mkdir($outputDirectory, 0777, true)
&& is_dir($outputDirectory) === false
) {
echo 'Unable to create the directory defined by "--output-directory" argument: "'.$outputDirectory.'"';
die(1);
}
}

$configConverter->convert($argv[1], $outputDirectory);
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"require": {
"php": ">=7.4",
"symplify/php-config-printer": "^9.4.70",
"symfony/yaml": "^v5.4.14",
"sylius/grid-bundle": "dev-master",
"sylius/grid-bundle": "1.12.x-dev",
"phpunit/phpunit": "^9.5.26"
},
"autoload": {
Expand Down
102 changes: 69 additions & 33 deletions src/ClassConfigConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,44 @@
namespace Mamazu\ConfigConverter;

use InvalidArgumentException;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
use PhpParser\PrettyPrinter\Standard;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\SubItemActionGroup;
use PhpParser\Node\Stmt\Throw_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use Sylius\Bundle\GridBundle\Builder\Action\Action;
use Sylius\Bundle\GridBundle\Builder\Action\CreateAction;
use Sylius\Bundle\GridBundle\Builder\Action\DeleteAction;
use Sylius\Bundle\GridBundle\Builder\Action\ShowAction;
use Sylius\Bundle\GridBundle\Builder\Action\UpdateAction;
use Sylius\Bundle\GridBundle\Builder\Action\CreateAction;
use Sylius\Bundle\GridBundle\Builder\Field\Field;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\MainActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\ItemActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\BulkActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\ItemActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\MainActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\SubItemActionGroup;
use Sylius\Bundle\GridBundle\Builder\Field\DateTimeField;
use Sylius\Bundle\GridBundle\Builder\Field\Field;
use Sylius\Bundle\GridBundle\Builder\Field\StringField;
use Sylius\Bundle\GridBundle\Builder\Field\TwigField;
use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Config\GridConfig;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Bundle\GridBundle\Grid\ResourceAwareGridInterface;
use Symfony\Component\Yaml\Yaml;

class ClassConfigConverter
{
const NO_CLASS = 'To be replaced with the correct class.';
private ?string $namespace = null;
private bool $functional = false;
private bool $verbose = true;
Expand Down Expand Up @@ -66,7 +68,7 @@ public function makeQuiet(): void
$this->verbose = false;
}

public function convert(string $fileName): void
public function convert(string $fileName, string $outputDirectory): void
{
$allGrids = Yaml::parse(file_get_contents($fileName))['sylius_grid']['grids'] ?? [];

Expand All @@ -84,23 +86,34 @@ public function convert(string $fileName): void
* Functional mode: filename = name of the grid
*/
foreach ($allGrids as $gridName => $gridConfiguration) {
[$className, $phpCode] = $this->handleGrid($gridName, $gridConfiguration);
echo "************* PROCESS GRID $gridName *************" . PHP_EOL;
try {
[$className, $phpCode] = $this->handleGrid($gridName, $gridConfiguration);
} catch (\Throwable $e) {
printf('EXCEPTION "%s" on grid "%s": %s', get_class($e), $gridName, $e->getMessage());
continue;
}
$new_content = $this->codeOutputter->printCode($phpCode);

$newFileName = $className.'.php';
if($this->verbose) {
echo "==============================$newFileName================".PHP_EOL;
$newFileName = $className . '.php';
$newFilePath = realpath($outputDirectory . DIRECTORY_SEPARATOR . $newFileName);
if ($this->verbose) {
echo "==============================$newFilePath================" . PHP_EOL;
echo $new_content;
} else {
echo "Writing the content to ".realpath($newFileName);
echo "Writing the content to " . $newFilePath . PHP_EOL;
}
file_put_contents($newFileName, $new_content);
file_put_contents($newFilePath, $new_content);
}
}

public function handleGrid(string $gridName, array $gridConfiguration): array
{

$phpNodes = [];
$phpNodes[] = new Node\Stmt\Declare_([
new Node\Stmt\DeclareDeclare(new Identifier('strict_types'), new Node\Scalar\LNumber(1))
]);
if ($this->namespace) {
$phpNodes[] = new Node\Stmt\Namespace_(new Name($this->namespace));
}
Expand All @@ -123,27 +136,35 @@ public function handleGrid(string $gridName, array $gridConfiguration): array
DateTimeField::class,
StringField::class,
TwigField::class,
ResourceAwareGridInterface::class,
]));

$resourceClass = $gridConfiguration['driver']['options']['class'] ?? 'To be replaced with the correct class.';

$resourceClass = $gridConfiguration['driver']['options']['class'] ?? self::NO_CLASS;
$isClassName = false;
if (strpos($resourceClass, '%') !== false || strpos($resourceClass, 'expr:param') !== false) {
trigger_error('You are using the parameter based syntax which does not work. Either provide a class directly in the getResourceClass or pass it by the constructor.', E_USER_WARNING);
trigger_error('You are using the parameter based syntax which does not work. Either provide a class directly in the getResourceClass or pass it by the constructor.',
E_USER_WARNING);
} elseif ($resourceClass !== self::NO_CLASS) {
$phpNodes[] = new Use_([new UseUse(new Name($resourceClass))]);
$isClassName = true;
$part = explode('\\', $resourceClass);
$resourceClass = end($part);
}

if (!$this->functional) {
$className = ucfirst(preg_replace_callback('#_\w#', static fn($a) => strtoupper($a[0][1]), $gridName));

$phpNodes[] = new Class_(
new Identifier($className),
[
'extends' => new Identifier('AbstractGrid'),
'implements' => [new Identifier('ResourceAwareGridInterface')],
'stmts' => [
$this->createStaticFunction('getName', $gridName),
$this->createGridBuildFunction($gridConfiguration),
$this->createStaticFunction('getResourceClass', $resourceClass),
$this->createResourceFunction($resourceClass, $isClassName),
],
],
[
]
);
} else {
$className = $gridName;
Expand All @@ -170,7 +191,6 @@ private function createStaticFunction(string $functionName, string $returnValue)
public function createGridBuildFunction(array $configuration): Node
{
$gridBuilder = new Variable('gridBuilder');

return new ClassMethod(
new Identifier('buildGrid'),
[
Expand Down Expand Up @@ -219,4 +239,20 @@ private function generateUseStatements(array $useStatement): array
);
}

private function createResourceFunction(string $returnValue, bool $isClassName): Node
{
$expr = $isClassName ? new Expr\ConstFetch(new Name($returnValue . '::class')) : new String_($returnValue);
return new ClassMethod(
new Identifier('getResourceClass'),
[
'flags' => Class_::MODIFIER_PUBLIC,
'returnType' => 'string',
'stmts' => [
$returnValue === self::NO_CLASS ? new Throw_(new Expr\New_(new Name('\InvalidArgumentException'),
['arguments' => $expr])) : new Return_($expr),
],
]
);
}

}
7 changes: 4 additions & 3 deletions src/FieldConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function convertField(Expr $gridBuilder, string $fieldName, array $fieldC
// Only add the options if the value is not empty. This can happen for the twig field for example. The template is now
// part of the create call and not an option anymore
if (isset($fieldConfig['options'])) {
unset($fieldConfig['options']['template']);
if (count($fieldConfig['options']) > 0) {
$field = new MethodCall($field, 'setOptions', [$this->convertValue($fieldConfig['options'])]);
}
Expand All @@ -60,7 +61,7 @@ public function convertField(Expr $gridBuilder, string $fieldName, array $fieldC

private function createField(array $fieldConfig, string $fieldName): Expr
{
switch ($fieldConfig['type']) {
switch ($fieldConfig['type']??'string') {
case 'datetime':
$field = new StaticCall(new Name('DateTimeField'), 'create', [
$this->convertValue($fieldName),
Expand All @@ -80,9 +81,9 @@ private function createField(array $fieldConfig, string $fieldName): Expr
default:
$field = new StaticCall(new Name('Field'), 'create', [
$this->convertValue($fieldName),
$this->convertValue($fieldConfig['type']),
$this->convertValue($fieldConfig['type']??'string'),
]);
}
return $field;
}
}
}
20 changes: 18 additions & 2 deletions src/FilterConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;

class FilterConverter
{
Expand All @@ -25,9 +26,24 @@ public function convertFilter(Expr $gridBuilder, string $filterName, array $conf
$this->convertToFunctionCall($filter, $configuration, 'label');
$this->convertToFunctionCall($filter, $configuration, 'options');
$this->convertToFunctionCall($filter, $configuration, 'form_options');

if (\array_key_exists('default_value', $configuration)) {
if (method_exists(Filter::class, 'setDefaultValue') === false) {
trigger_error(sprintf(
'The "%s" class dont have the "%s" method. Please use GridBundle 1.13+. This option is lost in convertion.',
Filter::class,
'setDefaultValue'
));
} else {
$filter = new MethodCall(
$filter,
'setDefaultValue',
[$this->convertValue($configuration['default_value'])]
);
}
unset($configuration['default_value']);
}
$this->checkUnconsumedConfiguration('filter', $configuration);

return new MethodCall($gridBuilder, 'addFilter', [new Arg($filter)]);
}
}
}
Loading

0 comments on commit bbbc2e6

Please sign in to comment.