├── _config.yml ├── behat.yml ├── src ├── Module │ ├── Frontend │ │ ├── Layout │ │ │ ├── Widgets │ │ │ │ └── Base │ │ │ │ │ ├── Base.html.twig │ │ │ │ │ └── Base.php │ │ │ └── Templates │ │ │ │ ├── Detail │ │ │ │ ├── Detail.html.twig │ │ │ │ └── Detail.php │ │ │ │ └── Index │ │ │ │ ├── Index.html.twig │ │ │ │ └── Index.php │ │ ├── Config │ │ │ ├── Config.php71.php.twig │ │ │ └── Config.php │ │ ├── Widgets │ │ │ ├── Base │ │ │ │ ├── Base.php71.php.twig │ │ │ │ └── Base.php │ │ │ ├── FrontendWidgetDataTransferObject.php │ │ │ └── FrontendWidgetType.php │ │ └── Actions │ │ │ ├── FrontendActionDataTransferObject.php │ │ │ ├── Index │ │ │ ├── Index.php71.php.twig │ │ │ └── Index.php │ │ │ ├── FrontendActionType.php │ │ │ └── Detail │ │ │ ├── Detail.php71.php.twig │ │ │ └── Detail.php │ └── Backend │ │ ├── Resources │ │ └── Config │ │ │ ├── Services │ │ │ ├── services.yml.twig │ │ │ └── Services.php │ │ │ ├── Commands │ │ │ ├── commands.yml.twig │ │ │ └── Commands.php │ │ │ ├── Repositories │ │ │ ├── repositories.yml.twig │ │ │ └── Repositories.php │ │ │ └── Doctrine │ │ │ ├── doctrine.yml.twig │ │ │ └── Doctrine.php │ │ ├── Config │ │ ├── Config.php71.php.twig │ │ └── Config.php │ │ ├── Installer │ │ ├── Data │ │ │ └── Locale │ │ │ │ ├── locale.xml.twig │ │ │ │ └── Locale.php │ │ └── Installer │ │ │ └── Installer.php │ │ ├── Info │ │ ├── info.xml.twig │ │ ├── InfoDataTransferObject.php │ │ ├── InfoType.php │ │ └── Info.php │ │ ├── Actions │ │ ├── BackendActionDataTransferObject.php │ │ ├── Index │ │ │ ├── Index.php71.php.twig │ │ │ └── Index.php │ │ ├── BackendSettingsActionDataTransferObject.php │ │ ├── Detail │ │ │ ├── Detail.php71.php.twig │ │ │ └── Detail.php │ │ ├── BackendActionType.php │ │ ├── Add │ │ │ ├── Add.php │ │ │ └── Add.php71.php.twig │ │ ├── Edit │ │ │ └── Edit.php │ │ ├── Delete │ │ │ ├── Delete.php │ │ │ └── Delete.php71.php.twig │ │ ├── BackendSettingsActionType.php │ │ └── Settings │ │ │ ├── Settings.php │ │ │ └── Settings.php71.php.twig │ │ ├── DependencyInjection │ │ └── ModuleExtension │ │ │ ├── ModuleExtension.php │ │ │ └── ModuleExtension.php71.php.twig │ │ └── Layout │ │ └── Templates │ │ ├── Index │ │ ├── Index.html.twig │ │ └── Index.php │ │ ├── Settings │ │ ├── Settings.html.twig │ │ └── Settings.php │ │ ├── Add │ │ ├── Add.html.twig │ │ └── Add.php │ │ ├── Detail │ │ ├── Detail.html.twig │ │ └── Detail.php │ │ └── Edit │ │ └── Edit.php ├── CLI │ ├── Service │ │ └── Generate │ │ │ ├── Appender.php │ │ │ ├── Dumper.php │ │ │ ├── FileDumper.php │ │ │ ├── FileAppender.php │ │ │ ├── GeneratableFile.php │ │ │ ├── GeneratableClass.php │ │ │ ├── ConsoleOutputAppender.php │ │ │ ├── ConsoleOutputDumper.php │ │ │ ├── GeneratableModuleClass.php │ │ │ └── GeneratableModuleFile.php │ ├── Exception │ │ ├── NonComplyingModuleName.php │ │ └── SourceDirectoryNotFound.php │ └── Console │ │ ├── Generate │ │ ├── Domain │ │ │ ├── DataGrid.php │ │ │ ├── File.php │ │ │ ├── Image.php │ │ │ ├── ValueObject.php │ │ │ ├── Repository.php │ │ │ └── Entity.php │ │ ├── Backend │ │ │ └── Action │ │ │ │ ├── CRUDActions.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── AddAction.php │ │ │ │ ├── EditAction.php │ │ │ │ ├── IndexAction.php │ │ │ │ └── DetailAction.php │ │ ├── Frontend │ │ │ ├── Widget │ │ │ │ └── BaseWidget.php │ │ │ └── Action │ │ │ │ ├── IndexAction.php │ │ │ │ └── DetailAction.php │ │ └── Module │ │ │ └── Bootstrap.php │ │ └── GenerateCommand.php ├── SumoCoders │ ├── ProjectDataTransferObject.php │ ├── Migration │ │ └── BlogToNews │ │ │ └── BlogToNewsMigration.php │ └── ProjectType.php ├── Domain │ ├── ServiceConfiguration │ │ ├── CommandHandlerServiceConfiguration.php71.yaml.twig │ │ └── CommandHandlerServiceConfigurationDataTransferObject.php │ ├── File │ │ ├── FileDataTransferObject.php │ │ ├── FileDBALType.php71.php.twig │ │ ├── File.php71.php.twig │ │ ├── FileType.php │ │ ├── File.php │ │ └── FileDBALType.php │ ├── Command │ │ ├── Create │ │ │ ├── CreateCommand.php71.php.twig │ │ │ ├── CreateCommandHandler.php71.php.twig │ │ │ ├── CreateCommand.php │ │ │ └── CreateCommandHandler.php │ │ ├── Update │ │ │ ├── UpdateCommandHandler.php71.php.twig │ │ │ ├── UpdateCommand.php71.php.twig │ │ │ ├── UpdateCommandHandler.php │ │ │ └── UpdateCommand.php │ │ ├── CRUDCommandDataTransferObject.php │ │ ├── Delete │ │ │ ├── DeleteCommand.php71.php.twig │ │ │ ├── DeleteCommandHandler.php71.php.twig │ │ │ ├── DeleteCommand.php │ │ │ └── DeleteCommandHandler.php │ │ ├── Settings │ │ │ ├── SettingsCommandHandler.php71.php.twig │ │ │ ├── SettingsCommand.php71.php.twig │ │ │ └── SettingsCommand.php │ │ └── CRUDCommandsType.php │ ├── Entity │ │ ├── EntityDataTransferObject.php │ │ ├── Entity.php │ │ └── EntityType.php │ ├── Image │ │ ├── ImageDataTransferObject.php │ │ ├── ImageDBALType.php71.php.twig │ │ ├── Image.php71.php.twig │ │ ├── ImageType.php │ │ └── ImageDBALType.php │ ├── ValueObject │ │ ├── ValueObjectDataTransferObject.php │ │ ├── ValueObjectDBALType.php71.php.twig │ │ ├── ValueObject.php │ │ ├── ValueObjectType.php │ │ ├── ValueObject.php71.php.twig │ │ └── ValueObjectDBALType.php │ ├── DataGrid │ │ ├── DataGridDataTransferObject.php │ │ ├── DataGrid.php71.php.twig │ │ ├── DataGrid.php │ │ └── DataGridType.php │ ├── Repository │ │ ├── RepositoryType.php │ │ └── Repository.php │ ├── FormType │ │ ├── SettingsType.php71.php.twig │ │ └── FormType.php71.php.twig │ └── DataTransferObject │ │ └── DataTransferObject.php ├── ModuleGeneratorBundle.php ├── PhpGenerator │ ├── Parameter │ │ ├── ParameterDataTransferObject.php │ │ └── Parameter.php │ ├── ActionName │ │ ├── ActionNameDataTransferObject.php │ │ ├── ActionName.php │ │ └── ActionNameType.php │ ├── ModuleName │ │ ├── ModuleNameDataTransferObject.php │ │ ├── ModuleName.php │ │ └── ModuleNameType.php │ ├── WidgetName │ │ ├── WidgetNameDataTransferObject.php │ │ ├── WidgetName.php │ │ └── WidgetNameType.php │ ├── PhpNamespace │ │ ├── PhpNamespaceDataTransferObject.php │ │ ├── PhpNamespace.php │ │ └── PhpNamespaceType.php │ ├── Constant │ │ ├── ConstantDataTransferObject.php │ │ └── ConstantType.php │ ├── ClassName │ │ ├── ClassNameDataTransferObject.php │ │ └── ClassName.php │ └── SemVer │ │ └── SemVerType.php └── DependencyInjection │ └── ModuleGeneratorExtension.php ├── app ├── config_test.yml ├── services.yml ├── config.yml ├── Application.php └── Kernel.php ├── .editorconfig ├── .github └── FUNDING.yml ├── README.md ├── LICENSE └── composer.json /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /behat.yml: -------------------------------------------------------------------------------- 1 | default: 2 | formatters: 3 | progress: true 4 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Widgets/Base/Base.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {{ hello }} 3 | {%- endverbatim %} 4 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Services/services.yml.twig: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: commands.yml } 3 | - { resource: repositories.yml } 4 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Commands/commands.yml.twig: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | autowire: true 4 | autoconfigure: true 5 | public: true 6 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/Appender.php: -------------------------------------------------------------------------------- 1 | 0 %} 4 | tags: 5 | {% for tag in service.tags %} 6 | - { {% for key, value in tag -%}{{ key }}: {{ value }}{% if not loop.last %}, {% endif %}{% endfor %} } 7 | {% endfor %} 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /src/Module/Backend/Installer/Data/Locale/locale.xml.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Domain/File/FileDataTransferObject.php: -------------------------------------------------------------------------------- 1 | loadTemplate(); 14 | 15 | $this->template->assign('hello', 'hello world'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Module/Backend/Info/info.xml.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ file.moduleName }} 4 | {{ file.moduleVersion }} 5 | 6 | {{ file.minimumForkVersion }} 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Domain/Command/Create/CreateCommand.php71.php.twig: -------------------------------------------------------------------------------- 1 | locale = $locale; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/CLI/Exception/NonComplyingModuleName.php: -------------------------------------------------------------------------------- 1 | getModuleName())); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Domain/DataGrid/DataGridDataTransferObject.php: -------------------------------------------------------------------------------- 1 | getModuleName())); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/FileDumper.php: -------------------------------------------------------------------------------- 1 | fileSystem = new Filesystem(); 15 | } 16 | 17 | public function dump(string $filename, string $content): void 18 | { 19 | $this->fileSystem->dumpFile($filename, $content); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Domain/File/FileDBALType.php71.php.twig: -------------------------------------------------------------------------------- 1 | filesystem = new Filesystem(); 15 | } 16 | 17 | public function append(string $filename, string $content): void 18 | { 19 | $this->filesystem->appendToFile($filename, $content); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Domain/Image/ImageDBALType.php71.php.twig: -------------------------------------------------------------------------------- 1 | append = $append; 13 | } 14 | 15 | public function isAppend(): bool 16 | { 17 | return $this->append; 18 | } 19 | 20 | abstract public function getFilePath(float $targetPhpVersion): string; 21 | abstract public function getTemplatePath(float $targetPhpVersion): string; 22 | } 23 | -------------------------------------------------------------------------------- /src/Module/Backend/Installer/Data/Locale/Locale.php: -------------------------------------------------------------------------------- 1 | getModuleName() . '/Installer/Data/locale.xml'; 12 | } 13 | 14 | public function getTemplatePath(float $targetPhpVersion): string 15 | { 16 | return __DIR__ . '/locale.xml.twig'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Commands/Commands.php: -------------------------------------------------------------------------------- 1 | getModuleName() . '/Resources/config/commands.yml'; 12 | } 13 | 14 | public function getTemplatePath(float $targetPhpVersion): string 15 | { 16 | return __DIR__ . '/commands.yml.twig'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Services/Services.php: -------------------------------------------------------------------------------- 1 | getModuleName() . '/Resources/config/services.yml'; 12 | } 13 | 14 | public function getTemplatePath(float $targetPhpVersion): string 15 | { 16 | return __DIR__ . '/services.yml.twig'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Domain/Command/Update/UpdateCommand.php71.php.twig: -------------------------------------------------------------------------------- 1 | template->assign('dataGrid', {{ class.entityClassName }}DataGrid::getHtml(Locale::workingLocale())); 16 | 17 | $this->parse(); 18 | $this->display(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Module/Backend/Installer/Installer/Installer.php: -------------------------------------------------------------------------------- 1 | getModuleName() . '\\Installer') 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # 2 | # @see http://editorconfig.org/ 3 | # 4 | 5 | root = true 6 | 7 | [*.{js,php,py,yml}] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 4 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.{html,rb,tpl,twig,xml}] 16 | charset = utf-8 17 | end_of_line = lf 18 | indent_size = 2 19 | indent_style = space 20 | insert_final_newline = true 21 | trim_trailing_whitespace = true 22 | 23 | # 24 | # Following languages aren't used at the moment in Fork CMS, but just in case. 25 | # (for instance: Capistrano is used in a lot of projects for deployment) 26 | # 27 | # [*.{py,rb}] 28 | -------------------------------------------------------------------------------- /src/Domain/File/File.php71.php.twig: -------------------------------------------------------------------------------- 1 | loadTemplate(); 16 | 17 | $this->template->assign( 18 | '{{ class.entityClassName.forParameter }}Collection', 19 | $this->get({{ class.entityClassName }}Repository::class)->findByLocale(Locale::frontendLanguage()) 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Module/Backend/DependencyInjection/ModuleExtension/ModuleExtension.php: -------------------------------------------------------------------------------- 1 | getModuleName() . 'Extension', 15 | new PhpNamespace('Backend\\Modules\\' . $this->getModuleName() . '\\DependencyInjection') 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Index/Index.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {% extends 'Layout/Templates/base.html.twig' %} 3 | {% import 'Layout/Templates/macros.html.twig' as macro %} 4 | 5 | {% block actionbar %} 6 | {% if show{%- endverbatim %}{{ file.moduleName }}{{ file.entityClassName }}{%- verbatim -%}Add %} 7 |
8 |
9 | {{ macro.buttonIcon(geturl('{%- endverbatim %}{{ file.entityClassName }}{%- verbatim -%}Add'), 'plus-square', 'lbl.Add'|trans|ucfirst) }} 10 |
11 |
12 | {% endif %} 13 | {% endblock %} 14 | 15 | {% block content %} 16 | {{ macro.dataGrid(dataGrid) }} 17 | {% endblock %} 18 | {%- endverbatim %} 19 | -------------------------------------------------------------------------------- /src/Domain/Repository/RepositoryType.php: -------------------------------------------------------------------------------- 1 | setDefaults( 15 | [ 16 | 'label' => 'Entity class name', 17 | 'name_label' => 'Entity class name', 18 | 'namespace_label' => 'Entity namespace (i.e.: Backend\Modules\MyModule\Domain\MyEntity)', 19 | ] 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Domain/Command/Delete/DeleteCommand.php71.php.twig: -------------------------------------------------------------------------------- 1 | {{ class.entityClassName.forParameter }} = ${{ class.entityClassName.forParameter }}; 15 | } 16 | 17 | public function get{{ class.entityClassName.name }}(): {{ class.entityClassName.name }} 18 | { 19 | return $this->{{ class.entityClassName.forParameter }}; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Settings/Settings.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {% extends 'Layout/Templates/base.html.twig' %} 3 | {% import 'Layout/Templates/macros.html.twig' as macro %} 4 | 5 | {% block content %} 6 | {{ form_start(form) }} 7 |
8 | {{ form_rest(form) }} 9 |
10 |
11 |
12 |
13 |
14 | {{ macro.buttonIcon('', 'floppy-o', 'lbl.Save'|trans|ucfirst, 'btn-primary', { "type":"submit", "id":"save", "name":"save"} ) }} 15 |
16 |
17 |
18 |
19 | {{ form_end(form) }} 20 | {% endblock %} 21 | {%- endverbatim %} 22 | -------------------------------------------------------------------------------- /src/Domain/Image/Image.php71.php.twig: -------------------------------------------------------------------------------- 1 | load('services.yml'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Module/Backend/Info/InfoDataTransferObject.php: -------------------------------------------------------------------------------- 1 | infoClass instanceof Info; 28 | } 29 | 30 | public function getInfoClass(): Info 31 | { 32 | return $this->infoClass; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/PhpGenerator/ActionName/ActionNameDataTransferObject.php: -------------------------------------------------------------------------------- 1 | actionNameClass = $actionName; 16 | 17 | if (!$this->actionNameClass instanceof ActionName) { 18 | return; 19 | } 20 | 21 | $this->name = $this->actionNameClass->getName(); 22 | } 23 | 24 | public function hasExistingActionName(): bool 25 | { 26 | return $this->actionNameClass instanceof ActionName; 27 | } 28 | 29 | public function getActionNameClass(): ActionName 30 | { 31 | return $this->actionNameClass; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/PhpGenerator/ModuleName/ModuleNameDataTransferObject.php: -------------------------------------------------------------------------------- 1 | moduleNameClass = $moduleName; 16 | 17 | if (!$this->moduleNameClass instanceof ModuleName) { 18 | return; 19 | } 20 | 21 | $this->name = $this->moduleNameClass->getName(); 22 | } 23 | 24 | public function hasExistingModuleName(): bool 25 | { 26 | return $this->moduleNameClass instanceof ModuleName; 27 | } 28 | 29 | public function getModuleNameClass(): ModuleName 30 | { 31 | return $this->moduleNameClass; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/PhpGenerator/WidgetName/WidgetNameDataTransferObject.php: -------------------------------------------------------------------------------- 1 | widgetNameClass = $widgetName; 16 | 17 | if (!$this->widgetNameClass instanceof WidgetName) { 18 | return; 19 | } 20 | 21 | $this->name = $this->widgetNameClass->getName(); 22 | } 23 | 24 | public function hasExistingWidgetName(): bool 25 | { 26 | return $this->widgetNameClass instanceof WidgetName; 27 | } 28 | 29 | public function getWidgetNameClass(): WidgetName 30 | { 31 | return $this->widgetNameClass; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Domain/Command/Settings/SettingsCommandHandler.php71.php.twig: -------------------------------------------------------------------------------- 1 | modulesSettings = $modulesSettings; 17 | } 18 | 19 | public function handle({{ class.commandClassName.name }} ${{ class.commandClassName.forParameter }}): void 20 | { 21 | {% if class.settings is not empty %} 22 | {% for setting in class.settings %} 23 | $this->modulesSettings->set(self::MODULE_NAME, '{{ setting.name }}', ${{ class.commandClassName.forParameter }}->{{ setting.name }}); 24 | {% endfor -%} 25 | {% endif %} 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Domain/Command/Delete/DeleteCommandHandler.php71.php.twig: -------------------------------------------------------------------------------- 1 | {{ class.repositoryClassName.forParameter }} = ${{ class.repositoryClassName.forParameter }}; 15 | } 16 | 17 | public function handle({{ class.commandClassName.name }} ${{ class.commandClassName.forParameter }}): void 18 | { 19 | $this->{{ class.repositoryClassName.forParameter }}->remove(${{ class.commandClassName.forParameter }}->get{{ class.entityClassName.realName }}()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Application.php: -------------------------------------------------------------------------------- 1 | extractNamespace($command->getName()), 19 | [ 20 | 'assets', 21 | 'cache', 22 | 'config', 23 | 'debug', 24 | 'lint', 25 | 'server', 26 | 'translation', 27 | 'cache:pool', 28 | ] 29 | )) { 30 | return; 31 | } 32 | 33 | parent::add($command); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Templates/Detail/Detail.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {# 3 | variables that are available: 4 | - {{ item }}: contains data about the question 5 | - {{ related }}: the related items 6 | #} 7 | {% import 'Core/Layout/Templates/Alerts.html.twig' as alerts %} 8 | {% import "Core/Layout/Templates/Macros.html.twig" as macro %} 9 | 10 |
11 | {% block block_heading %} 12 | 15 | {% endblock %} 16 | 17 | {% block block_item %} 18 | 19 | {% endblock %} 20 | 21 | {% block block_footer %} 22 | {% endblock %} 23 |
24 | {%- endverbatim %} 25 | -------------------------------------------------------------------------------- /src/PhpGenerator/PhpNamespace/PhpNamespaceDataTransferObject.php: -------------------------------------------------------------------------------- 1 | phpNamespaceClass = $phpNamespace; 16 | 17 | if (!$this->phpNamespaceClass instanceof PhpNamespace) { 18 | return; 19 | } 20 | 21 | $this->name = $this->phpNamespaceClass->getName(); 22 | } 23 | 24 | public function hasExistingPhpNamespace(): bool 25 | { 26 | return $this->phpNamespaceClass instanceof PhpNamespace; 27 | } 28 | 29 | public function getPhpNamespaceClass(): PhpNamespace 30 | { 31 | return $this->phpNamespaceClass; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/SumoCoders/ProjectType.php: -------------------------------------------------------------------------------- 1 | add( 16 | 'project', 17 | TextType::class, 18 | [ 19 | 'label' => 'Name of the project', 20 | ] 21 | ); 22 | } 23 | 24 | public function configureOptions(OptionsResolver $resolver) 25 | { 26 | $resolver->setDefaults( 27 | [ 28 | 'data_class' => ProjectDataTransferObject::class, 29 | ] 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Domain/ValueObject/ValueObjectDBALType.php71.php.twig: -------------------------------------------------------------------------------- 1 | getValue(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/ConsoleOutputAppender.php: -------------------------------------------------------------------------------- 1 | writeln('########## START FILE ##########'); 14 | $output->writeln('########## START FILENAME ##########'); 15 | $output->writeln('# ' . $filename . ' #'); 16 | $output->writeln('########## END FILENAME ##########'); 17 | $output->writeln('########## START CONTENT ##########'); 18 | $output->writeln($content); 19 | $output->writeln('########## END CONTENT ##########'); 20 | $output->writeln('########## END FILE ##########'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Domain/Command/Settings/SettingsCommand.php71.php.twig: -------------------------------------------------------------------------------- 1 | getForModule('{{ class.moduleName }}'); 26 | {% if class.settings is not empty %} 27 | 28 | {% for setting in class.settings %} 29 | $this->{{ setting.name }} = $settings['{{ setting.name }}'] ?? null; 30 | {% endfor -%} 31 | {% endif %} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Domain/Command/Create/CreateCommandHandler.php71.php.twig: -------------------------------------------------------------------------------- 1 | {{ class.repositoryClassName.forParameter }} = ${{ class.repositoryClassName.forParameter }}; 16 | } 17 | 18 | public function handle({{ class.commandClassName.name }} ${{ class.commandClassName.forParameter }}): void 19 | { 20 | $this->{{ class.repositoryClassName.forParameter }}->add( 21 | {{ class.entityClassName.name }}::fromDataTransferObject(${{ class.commandClassName.forParameter }}) 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Add/Add.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {% extends 'Layout/Templates/base.html.twig' %} 3 | {% import 'Layout/Templates/macros.html.twig' as macro %} 4 | 5 | {% block actionbar %}{% endblock %} 6 | 7 | {% block content %} 8 | {{ form_start(form) }} 9 |
10 | {{ form_rest(form) }} 11 |
12 |
13 |
14 |
15 |
16 | {{ macro.buttonIcon(geturl('{%- endverbatim %}{{ file.entityClassName }}{%- verbatim -%}Index'), 'times', 'lbl.Cancel'|trans|ucfirst, 'btn-default') }} 17 |
18 |
19 | {{ macro.buttonIcon('', 'plus-square', 'lbl.Add'|trans|ucfirst, 'btn-primary', {"id":"addButton", "type":"submit", "name":"add"}) }} 20 |
21 |
22 |
23 |
24 | {{ form_end(form) }} 25 | {% endblock %} 26 | {%- endverbatim %} 27 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/ConsoleOutputDumper.php: -------------------------------------------------------------------------------- 1 | writeln('########## START FILE ##########'); 15 | $output->writeln('########## START FILENAME ##########'); 16 | $output->writeln('# ' . $filename . ' #'); 17 | $output->writeln('########## END FILENAME ##########'); 18 | $output->writeln('########## START CONTENT ##########'); 19 | $output->writeln($content); 20 | $output->writeln('########## END CONTENT ##########'); 21 | $output->writeln('########## END FILE ##########'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Module/Frontend/Widgets/FrontendWidgetType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'moduleName', 18 | ModuleNameType::class 19 | ) 20 | ->add( 21 | 'widgetName', 22 | WidgetNameType::class 23 | ); 24 | } 25 | 26 | public function configureOptions(OptionsResolver $resolver) 27 | { 28 | $resolver->setDefaults( 29 | [ 30 | 'data_class' => FrontendWidgetDataTransferObject::class, 31 | ] 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Detail/Detail.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {% extends 'Layout/Templates/base.html.twig' %} 3 | {% import 'Layout/Templates/macros.html.twig' as macro %} 4 | 5 | {% block actionbar %}{% endblock %} 6 | 7 | {% block content %} 8 |

{{ {% endverbatim %}{{ file.entityClassName.forParameter }}{%- verbatim -%}.title }}

9 |
10 |
11 |
12 |
13 | {% if show{%- endverbatim %}{{ file.moduleName }}{{ file.entityClassName }}{%- verbatim -%}Delete %} 14 | {{ macro.buttonIcon('', 'plus-square', 'lbl.Delete'|trans|ucfirst, 'btn-danger', {"type":"button", "data-toggle":"modal", "data-target":"#confirmDelete"}) }} 15 | {% endif %} 16 | {{ macro.buttonIcon(geturl('{%- endverbatim %}{{ file.entityClassName }}{%- verbatim -%}Index'), 'times', 'lbl.Cancel'|trans|ucfirst, 'btn-default') }} 17 |
18 |
19 |
20 |
21 | {% endblock %} 22 | {%- endverbatim %} 23 | -------------------------------------------------------------------------------- /src/PhpGenerator/Constant/ConstantDataTransferObject.php: -------------------------------------------------------------------------------- 1 | constantClass = $constant; 19 | 20 | if (!$this->constantClass instanceof Constant) { 21 | return; 22 | } 23 | 24 | $this->name = $this->constantClass->getName(); 25 | $this->value = $this->constantClass->getValue(); 26 | 27 | if (is_bool($this->value)) { 28 | $this->value = $this->value ? 'true' : 'false'; 29 | } 30 | } 31 | 32 | public function hasExistingConstant(): bool 33 | { 34 | return $this->constantClass instanceof Constant; 35 | } 36 | 37 | public function getConstantClass(): Constant 38 | { 39 | return $this->constantClass; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Repositories/Repositories.php: -------------------------------------------------------------------------------- 1 | repositories = $repositories; 18 | } 19 | 20 | public function getFilePath(float $targetPhpVersion): string 21 | { 22 | return 'Backend/Modules/' . $this->getModuleName() . '/Resources/config/repositories.yml'; 23 | } 24 | 25 | public function getTemplatePath(float $targetPhpVersion): string 26 | { 27 | return __DIR__ . '/repositories.yml.twig'; 28 | } 29 | 30 | public function getRepositories(): array 31 | { 32 | return $this->repositories; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fork-cms module generator 2 | [![Build Status](https://travis-ci.org/sumocoders/fork-cms-module-generator.svg?branch=master)](https://travis-ci.org/sumocoders/fork-cms-module-generator) 3 | 4 | ## Installation 5 | 6 | Use composer to install the package to your dev dependencies. 7 | 8 | `composer require --dev pageon/fork-cms-module-generator` 9 | 10 | Register the following bundles in your Fork `app/AppKernel.php`, but only load them in dev or test mode. 11 | 12 | ``` 13 | class AppKernel extends Kernel 14 | { 15 | /** 16 | * Load all the bundles we'll be using in our application. 17 | */ 18 | public function registerBundles(): array 19 | { 20 | ... 21 | 22 | if (in_array($this->getEnvironment(), ['dev', 'test'])) { 23 | ... 24 | 25 | $bundles[] = new \Matthias\SymfonyConsoleForm\Bundle\SymfonyConsoleFormBundle(); 26 | $bundles[] = new \ModuleGenerator\ModuleGeneratorBundle(); 27 | } 28 | 29 | return $bundles; 30 | } 31 | 32 | ... 33 | } 34 | ``` 35 | 36 | ## Tests 37 | 38 | You can run the tests with `composer test` 39 | -------------------------------------------------------------------------------- /src/Module/Backend/Resources/Config/Doctrine/Doctrine.php: -------------------------------------------------------------------------------- 1 | entities = $entities; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Backend/Modules/' . $this->getModuleName() . '/Resources/config/doctrine.yml'; 24 | } 25 | 26 | public function getTemplatePath(float $targetPhpVersion): string 27 | { 28 | return __DIR__ . '/doctrine.yml.twig'; 29 | } 30 | 31 | public function getEntities(): array 32 | { 33 | return $this->entities; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jelmer Prins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Domain/File/FileType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'className', 18 | ClassNameType::class 19 | )->add( 20 | 'maxFileSize', 21 | TextType::class, 22 | [ 23 | 'label' => 'Max file size (optional)', 24 | 'required' => false, 25 | ] 26 | ); 27 | } 28 | 29 | public function configureOptions(OptionsResolver $resolver) 30 | { 31 | $resolver->setDefaults( 32 | [ 33 | 'data_class' => FileDataTransferObject::class, 34 | ] 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Domain/Repository/Repository.php: -------------------------------------------------------------------------------- 1 | className = $className; 19 | $this->entityClassName = $entityClassName; 20 | } 21 | 22 | public function getClassName(): ClassName 23 | { 24 | return $this->className; 25 | } 26 | 27 | public function getEntityClassName(): ClassName 28 | { 29 | return $this->entityClassName; 30 | } 31 | 32 | public static function fromEntityClassName(ClassName $entityClassName): self 33 | { 34 | return new self( 35 | new ClassName($entityClassName->getRealName() . 'Repository', $entityClassName->getNamespace()), 36 | $entityClassName 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Detail/Detail.php71.php.twig: -------------------------------------------------------------------------------- 1 | get{{ class.entityClassName }}(); 16 | 17 | if (!${{ class.entityClassName.forParameter }} instanceof {{ class.entityClassName }}) { 18 | $this->redirect($this->getBackLink(['error' => 'non-existing'])); 19 | } 20 | 21 | $this->template->assign('{{ class.entityClassName.forParameter }}', ${{ class.entityClassName.forParameter }}); 22 | $this->parse(); 23 | $this->display(); 24 | } 25 | 26 | private function get{{ class.entityClassName }}(): ?{{ class.entityClassName }} 27 | { 28 | return $this->get({{ class.entityClassName }}Repository::class)->find($this->getRequest()->query->getInt('id')); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/GeneratableModuleClass.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 15 | } 16 | 17 | final public function getModuleName(): ModuleName 18 | { 19 | return $this->moduleName; 20 | } 21 | 22 | final protected function getFrontendModulePath(string $filePath = null): string 23 | { 24 | if ($filePath === null) { 25 | return 'Frontend/Modules/' . $this->getModuleName(); 26 | } 27 | 28 | return $this->getFrontendModulePath() . '/' . $filePath; 29 | } 30 | 31 | final protected function getBackendModulePath(string $filePath = null): string 32 | { 33 | if ($filePath === null) { 34 | return 'Backend/Modules/' . $this->getModuleName(); 35 | } 36 | 37 | return $this->getBackendModulePath() . '/' . $filePath; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Domain/FormType/SettingsType.php71.php.twig: -------------------------------------------------------------------------------- 1 | add( 19 | '{{ setting.setting.name }}', 20 | {{ setting.formType }}::class, 21 | [ 22 | 'label' => 'lbl.{{ setting.setting.forFunction }}',{% if setting.setting.isNullable %} 23 | 24 | 'required' => false,{% endif %} 25 | 26 | ] 27 | ); 28 | {% endfor %} 29 | } 30 | 31 | public function configureOptions(OptionsResolver $resolver): void 32 | { 33 | $resolver->setDefaults(['data_class' => {{ class.dataClass.name }}::class]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Domain/DataTransferObject/DataTransferObject.php: -------------------------------------------------------------------------------- 1 | entity = $entity; 17 | } 18 | 19 | public function getEntity(): Entity 20 | { 21 | return $this->entity; 22 | } 23 | 24 | public function getClassName(): ClassName 25 | { 26 | return new ClassName( 27 | $this->entity->getClassName()->getName() . 'DataTransferObject', 28 | $this->entity->getClassName()->getNamespace() 29 | ); 30 | } 31 | 32 | public function hasRequiredParameters(): bool 33 | { 34 | foreach ($this->entity->getParameters() as $parameter) { 35 | if (!$parameter->isNullable()) { 36 | return true; 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/CLI/Service/Generate/GeneratableModuleFile.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 17 | } 18 | 19 | final public function getModuleName(): ModuleName 20 | { 21 | return $this->moduleName; 22 | } 23 | 24 | final protected function getFrontendModulePath(string $filePath = null): string 25 | { 26 | if ($filePath === null) { 27 | return 'Frontend/Modules/' . $this->getModuleName(); 28 | } 29 | 30 | return $this->getFrontendModulePath() . '/' . $filePath; 31 | } 32 | 33 | final protected function getBackendModulePath(string $filePath = null): string 34 | { 35 | if ($filePath === null) { 36 | return 'Backend/Modules/' . $this->getModuleName(); 37 | } 38 | 39 | return $this->getBackendModulePath() . '/' . $filePath; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/PhpGenerator/ActionName/ActionName.php: -------------------------------------------------------------------------------- 1 | name = ucfirst($name); 13 | } 14 | 15 | public function getName(): string 16 | { 17 | return $this->name; 18 | } 19 | 20 | public function __toString(): string 21 | { 22 | return $this->getName(); 23 | } 24 | 25 | public function getForCssClassName(): string 26 | { 27 | return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $this->name)), '-'); 28 | } 29 | 30 | public static function fromDataTransferObject( 31 | ActionNameDataTransferObject $actionNameDataTransferObject 32 | ): self { 33 | if ($actionNameDataTransferObject->hasExistingActionName()) { 34 | $actionNameDataTransferObject->getActionNameClass()->name = ucfirst($actionNameDataTransferObject->name); 35 | 36 | return $actionNameDataTransferObject->getActionNameClass(); 37 | } 38 | 39 | return new self( 40 | $actionNameDataTransferObject->name 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/PhpGenerator/WidgetName/WidgetName.php: -------------------------------------------------------------------------------- 1 | name = ucfirst($name); 13 | } 14 | 15 | public function getName(): string 16 | { 17 | return $this->name; 18 | } 19 | 20 | public function getForCssClassName(): string 21 | { 22 | return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $this->name)), '-'); 23 | } 24 | 25 | public function __toString(): string 26 | { 27 | return $this->getName(); 28 | } 29 | 30 | public static function fromDataTransferObject( 31 | WidgetNameDataTransferObject $widgetNameDataTransferObject 32 | ): self { 33 | if ($widgetNameDataTransferObject->hasExistingWidgetName()) { 34 | $widgetNameDataTransferObject->getWidgetNameClass()->name = ucfirst($widgetNameDataTransferObject->name); 35 | 36 | return $widgetNameDataTransferObject->getWidgetNameClass(); 37 | } 38 | 39 | return new self( 40 | $widgetNameDataTransferObject->name 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/PhpGenerator/ModuleName/ModuleName.php: -------------------------------------------------------------------------------- 1 | name = ucfirst($name); 13 | } 14 | 15 | public function getName(): string 16 | { 17 | return $this->name; 18 | } 19 | 20 | public function getForCssClassName(): string 21 | { 22 | return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $this->getName())), '-'); 23 | } 24 | 25 | public function __toString(): string 26 | { 27 | return $this->getName(); 28 | } 29 | 30 | public static function fromDataTransferObject( 31 | ModuleNameDataTransferObject $moduleNameDataTransferObject 32 | ): self { 33 | if ($moduleNameDataTransferObject->hasExistingModuleName()) { 34 | $moduleNameDataTransferObject->getModuleNameClass()->name = ucfirst($moduleNameDataTransferObject->name); 35 | 36 | return $moduleNameDataTransferObject->getModuleNameClass(); 37 | } 38 | 39 | return new self( 40 | $moduleNameDataTransferObject->name 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/DataGrid.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:data-grid') 19 | ->setDescription('Generates a data grid for an entity'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | parent::execute($input, $output); 25 | 26 | /** @var DataGridDataTransferObject $dataGridDataTransferObject */ 27 | $dataGridDataTransferObject = $this->getFormData(DataGridType::class); 28 | 29 | $this->generateService->generateClass( 30 | DataGridClass::fromDataTransferObject($dataGridDataTransferObject), 31 | $this->getTargetPhpVersion() 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/PhpGenerator/ClassName/ClassNameDataTransferObject.php: -------------------------------------------------------------------------------- 1 | classNameClass = $className; 24 | 25 | if (!$this->classNameClass instanceof ClassName) { 26 | return; 27 | } 28 | 29 | $this->name = $this->classNameClass->getName(); 30 | $this->namespace = new PhpNamespaceDataTransferObject($this->classNameClass->getNamespace()); 31 | $this->alias = $this->classNameClass->getAlias(); 32 | } 33 | 34 | public function hasExistingClassName(): bool 35 | { 36 | return $this->classNameClass instanceof ClassName; 37 | } 38 | 39 | public function getClassNameClass(): ClassName 40 | { 41 | return $this->classNameClass; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Domain/DataGrid/DataGrid.php71.php.twig: -------------------------------------------------------------------------------- 1 | $locale] 20 | ); 21 | 22 | $this->setSortingColumns(['title']); 23 | 24 | if (BackendAuthentication::isAllowedAction('{{ class.entityClassName }}Edit')) { 25 | $editUrl = Model::createUrlForAction('{{ class.entityClassName }}Edit', null, null, ['id' => '[id]'], false); 26 | $this->setColumnURL('title', $editUrl); 27 | $this->addColumn('edit', null, Language::lbl('Edit'), $editUrl, Language::lbl('Edit')); 28 | } 29 | } 30 | 31 | public static function getHtml(Locale $locale): string 32 | { 33 | return (new self($locale))->getContent(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Module/Backend/DependencyInjection/ModuleExtension/ModuleExtension.php71.php.twig: -------------------------------------------------------------------------------- 1 | getLoader($container)->load('services.yml'); 21 | } 22 | 23 | public function prepend(ContainerBuilder $container): void 24 | { 25 | $this->getLoader($container)->load('doctrine.yml'); 26 | } 27 | 28 | private function getLoader(ContainerBuilder $container): YamlFileLoader 29 | { 30 | return new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/BackendActionType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'moduleName', 18 | ModuleNameType::class 19 | ) 20 | ->add( 21 | 'entityClassName', 22 | ClassNameType::class, 23 | [ 24 | 'label' => 'Entity class name', 25 | 'name_label' => 'Entity class name', 26 | 'namespace_label' => 'Entity namespace (i.e.: Backend\\Modules\MyModule\Domain\MyEntity)', 27 | ] 28 | ); 29 | } 30 | 31 | public function configureOptions(OptionsResolver $resolver) 32 | { 33 | $resolver->setDefaults( 34 | [ 35 | 'data_class' => BackendActionDataTransferObject::class, 36 | ] 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/PhpGenerator/PhpNamespace/PhpNamespace.php: -------------------------------------------------------------------------------- 1 | name = preg_replace('/(^\\\\)||(\\\\$)/', '', $name); 14 | } 15 | 16 | public function getName(): string 17 | { 18 | return $this->name; 19 | } 20 | 21 | public function __toString(): string 22 | { 23 | return $this->name; 24 | } 25 | 26 | public static function root(): self 27 | { 28 | return new self(''); 29 | } 30 | 31 | public function isRoot(): bool 32 | { 33 | return $this->name === ''; 34 | } 35 | 36 | public static function fromDataTransferObject( 37 | PhpNamespaceDataTransferObject $phpNamespaceDataTransferObject 38 | ): self { 39 | if ($phpNamespaceDataTransferObject->hasExistingPhpNamespace()) { 40 | $phpNamespaceDataTransferObject->getPhpNamespaceClass()->name = $phpNamespaceDataTransferObject->name; 41 | 42 | return $phpNamespaceDataTransferObject->getPhpNamespaceClass(); 43 | } 44 | 45 | return new self($phpNamespaceDataTransferObject->name); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Templates/Index/Index.html.twig: -------------------------------------------------------------------------------- 1 | {%- verbatim -%} 2 | {% import 'Core/Layout/Templates/Alerts.html.twig' as alerts %} 3 | 4 |
5 | {% if not {% endverbatim -%}{{ file.entityClassName.forParameter }}Collection{%- verbatim %} %} 6 | {% block block_no_items %} 7 | {{ alerts.alert('info', 'msg.{%- endverbatim %}{{ file.entityClassName }}{%- verbatim -%}NoItems'|trans) }} 8 | {% endblock %} 9 | {% else %} 10 | {% block block_heading %}{% endblock %} 11 | 12 | {% block block_items %} 13 | 22 | {% endblock %} 23 | 24 | {% block block_footer %}{% endblock %} 25 | {% endif %} 26 |
27 | {%- endverbatim %} 28 | -------------------------------------------------------------------------------- /src/Domain/Command/CRUDCommandsType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'commandNamespace', 18 | PhpNamespaceType::class, 19 | [ 20 | 'name_label' => 'Command namespace (i.e.: Backend\\Modules\MyModule\Domain\MyEntity\Command)', 21 | ] 22 | )->add( 23 | 'entityClassName', 24 | ClassNameType::class, 25 | [ 26 | 'label' => 'Entity class name', 27 | 'name_label' => 'Entity class name', 28 | 'namespace_label' => 'Entity namespace (i.e.: Backend\\Modules\MyModule\Domain\MyEntity)', 29 | ] 30 | ); 31 | } 32 | 33 | public function configureOptions(OptionsResolver $resolver) 34 | { 35 | $resolver->setDefaults( 36 | [ 37 | 'data_class' => CRUDCommandDataTransferObject::class, 38 | ] 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/CRUDActions.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:crud') 18 | ->setDescription('Generates the index, add, update and delete action for an entity'); 19 | } 20 | 21 | protected function execute(InputInterface $input, OutputInterface $output) 22 | { 23 | parent::execute($input, $output); 24 | 25 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 26 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 27 | 28 | $classes = [ 29 | AddAction::class, 30 | DeleteAction::class, 31 | EditAction::class, 32 | IndexAction::class, 33 | ]; 34 | 35 | foreach ($classes as $class) { 36 | (new $class($this->generateService))->setTargetPhpVersion($this->getTargetPhpVersion())->generateAction( 37 | $crudActionsDataTransferObject 38 | ); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/DeleteAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:action:delete') 19 | ->setDescription('Generate the delete action for an entity'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | parent::execute($input, $output); 25 | 26 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 27 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 28 | 29 | $this->generateAction($crudActionsDataTransferObject); 30 | } 31 | 32 | public function generateAction(BackendActionDataTransferObject $crudActionsDataTransferObject): void 33 | { 34 | $this->generateService->generateClass( 35 | Delete::fromDataTransferObject($crudActionsDataTransferObject), 36 | $this->getTargetPhpVersion() 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Module/Frontend/Actions/FrontendActionType.php: -------------------------------------------------------------------------------- 1 | add( 18 | 'moduleName', 19 | ModuleNameType::class 20 | ) 21 | ->add( 22 | 'entityClassName', 23 | ClassNameType::class, 24 | [ 25 | 'label' => 'Entity class name', 26 | 'name_label' => 'Entity class name', 27 | 'namespace_label' => 'Entity namespace (i.e.: Backend\\Modules\MyModule\Domain\MyEntity)', 28 | ] 29 | ) 30 | ->add( 31 | 'actionName', 32 | ActionNameType::class 33 | ); 34 | } 35 | 36 | public function configureOptions(OptionsResolver $resolver) 37 | { 38 | $resolver->setDefaults( 39 | [ 40 | 'data_class' => FrontendActionDataTransferObject::class, 41 | ] 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/PhpGenerator/ActionName/ActionNameType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'name', 18 | TextType::class, 19 | [ 20 | 'label' => 'Action name (i.e.: Index)', 21 | 'required' => true, 22 | 'constraints' => [ 23 | new NotBlank(), 24 | new Regex( 25 | [ 26 | 'pattern' => '/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', 27 | 'message' => 'Invalid action name', 28 | ] 29 | ), 30 | ], 31 | ] 32 | ); 33 | } 34 | 35 | public function configureOptions(OptionsResolver $resolver) 36 | { 37 | $resolver->setDefaults( 38 | [ 39 | 'data_class' => ActionNameDataTransferObject::class, 40 | 'label' => false, 41 | 'required' => true, 42 | ] 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/PhpGenerator/WidgetName/WidgetNameType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'name', 18 | TextType::class, 19 | [ 20 | 'label' => 'Widget name (i.e.: Spotlight)', 21 | 'required' => true, 22 | 'constraints' => [ 23 | new NotBlank(), 24 | new Regex( 25 | [ 26 | 'pattern' => '/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', 27 | 'message' => 'Invalid widget name', 28 | ] 29 | ), 30 | ], 31 | ] 32 | ); 33 | } 34 | 35 | public function configureOptions(OptionsResolver $resolver) 36 | { 37 | $resolver->setDefaults( 38 | [ 39 | 'data_class' => WidgetNameDataTransferObject::class, 40 | 'label' => false, 41 | 'required' => true, 42 | ] 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/PhpGenerator/ModuleName/ModuleNameType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'name', 18 | TextType::class, 19 | [ 20 | 'label' => 'Module name (i.e.: Testimonies)', 21 | 'required' => true, 22 | 'constraints' => [ 23 | new NotBlank(), 24 | new Regex( 25 | [ 26 | 'pattern' => '/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', 27 | 'message' => 'Invalid module name', 28 | ] 29 | ), 30 | ], 31 | ] 32 | ); 33 | } 34 | 35 | public function configureOptions(OptionsResolver $resolver) 36 | { 37 | $resolver->setDefaults( 38 | [ 39 | 'data_class' => ModuleNameDataTransferObject::class, 40 | 'label' => false, 41 | 'required' => true, 42 | ] 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Widgets/Base/Base.php: -------------------------------------------------------------------------------- 1 | widgetName = $widgetName; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Frontend/Modules/' . $this->getModuleName() . '/Layout/Widgets/' . $this->widgetName . '.html.twig'; 24 | } 25 | 26 | public function getWidgetName(): WidgetName 27 | { 28 | return $this->widgetName; 29 | } 30 | 31 | public function getTemplatePath(float $targetPhpVersion): string 32 | { 33 | return __DIR__ . '/Base.html.twig'; 34 | } 35 | 36 | public static function fromDataTransferObject(FrontendWidgetDataTransferObject $frontendWidgetDataTransferObject): self 37 | { 38 | return new self( 39 | ModuleName::fromDataTransferObject($frontendWidgetDataTransferObject->moduleName), 40 | WidgetName::fromDataTransferObject($frontendWidgetDataTransferObject->widgetName) 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Domain/Command/Delete/DeleteCommand.php: -------------------------------------------------------------------------------- 1 | className = $className; 23 | $this->entityClassName = $entityClassName; 24 | } 25 | 26 | public function getClassName(): ClassName 27 | { 28 | return $this->className; 29 | } 30 | 31 | public function getEntityClassName(): ClassName 32 | { 33 | return $this->entityClassName; 34 | } 35 | 36 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 37 | { 38 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 39 | 40 | return new self( 41 | new ClassName( 42 | 'Delete' . $entityClassName->getRealName(), 43 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 44 | ), 45 | $entityClassName 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Add/Add.php: -------------------------------------------------------------------------------- 1 | entityClassName = $entityClassName; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Backend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . 24 | $this->entityClassName->getName() . 'Add.html.twig'; 25 | } 26 | 27 | public function getEntityClassName(): ClassName 28 | { 29 | return $this->entityClassName; 30 | } 31 | 32 | public function getTemplatePath(float $targetPhpVersion): string 33 | { 34 | return __DIR__ . '/Add.html.twig'; 35 | } 36 | 37 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 38 | { 39 | return new self( 40 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 41 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pageon/fork-cms-module-generator", 3 | "description": "The generator for Fork modules", 4 | "type": "application", 5 | "require": { 6 | "php": "^7.0", 7 | "symfony/framework-bundle": "^3.2", 8 | "symfony/validator": "^3.2", 9 | "symfony/yaml": "^3.2", 10 | "symfony/security": "^3.2", 11 | "symfony/twig-bundle": "^3.2", 12 | "symfony/asset": "^3.2", 13 | "symfony/templating": "^3.2", 14 | "symfony/serializer": "^3.2", 15 | "vierbergenlars/php-semver": "^3.0", 16 | "matthiasnoback/symfony-console-form": "^2.2", 17 | "symfony/finder": "^3.2" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "ModuleGenerator\\": [ 22 | "src/" 23 | ], 24 | "App\\": [ 25 | "app/" 26 | ] 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "ModuleGenerator\\Tests\\": "test/" 32 | } 33 | }, 34 | "license": "MIT", 35 | "authors": [ 36 | { 37 | "name": "Jelmer Prins", 38 | "email": "jelmer@pageon.be" 39 | }, 40 | { 41 | "name": "Bruno Vitorino", 42 | "email": "bruno@vitorino.me" 43 | } 44 | ], 45 | "require-dev": { 46 | "symfony/var-dumper": "^3.2", 47 | "behat/behat": "^3.3", 48 | "beberlei/assert": "^2.7", 49 | "squizlabs/php_codesniffer": "^2.8", 50 | "sebastian/diff": "^1.4" 51 | }, 52 | "scripts": { 53 | "test": "vendor/bin/behat" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/PhpGenerator/Parameter/Parameter.php: -------------------------------------------------------------------------------- 1 | name = $name; 21 | $this->dbalType = $dbalType; 22 | $this->nullable = $nullable; 23 | } 24 | 25 | public function getName(): string 26 | { 27 | return $this->name; 28 | } 29 | 30 | public function getDbalType(): DBALType 31 | { 32 | return $this->dbalType; 33 | } 34 | 35 | public function getDbalTypeName(): string 36 | { 37 | if ($this->dbalType->isImage() || $this->dbalType->isFile()) { 38 | return mb_strtolower($this->name); 39 | } 40 | 41 | return $this->dbalType; 42 | } 43 | 44 | public function isNullable(): bool 45 | { 46 | return $this->nullable; 47 | } 48 | 49 | public function getForFunction(): string 50 | { 51 | return ucfirst($this->getName()); 52 | } 53 | 54 | public static function fromDataTransferObject(ParameterDataTransferObject $parameterDataTransferObject): self 55 | { 56 | return new self( 57 | $parameterDataTransferObject->name, 58 | $parameterDataTransferObject->dbalType, 59 | $parameterDataTransferObject->nullable 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Edit/Edit.php: -------------------------------------------------------------------------------- 1 | entityClassName = $entityClassName; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Backend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . 24 | $this->entityClassName->getName() . 'Edit.html.twig'; 25 | } 26 | 27 | public function getEntityClassName(): ClassName 28 | { 29 | return $this->entityClassName; 30 | } 31 | 32 | public function getTemplatePath(float $targetPhpVersion): string 33 | { 34 | return __DIR__ . '/Edit.html.twig'; 35 | } 36 | 37 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 38 | { 39 | return new self( 40 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 41 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Index/Index.php: -------------------------------------------------------------------------------- 1 | entityClassName = $entityClassName; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Backend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . 24 | $this->entityClassName->getName() . 'Index.html.twig'; 25 | } 26 | 27 | public function getTemplatePath(float $targetPhpVersion): string 28 | { 29 | return __DIR__ . '/Index.html.twig'; 30 | } 31 | 32 | public function getEntityClassName(): ClassName 33 | { 34 | return $this->entityClassName; 35 | } 36 | 37 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 38 | { 39 | return new self( 40 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 41 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Module/Frontend/Widgets/Base/Base.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 25 | $this->className = new ClassName( 26 | $widgetName, 27 | new PhpNamespace('Frontend\\Modules\\' . $this->moduleName->getName() . '\\Widgets') 28 | ); 29 | } 30 | 31 | public function getModuleName(): ModuleName 32 | { 33 | return $this->moduleName; 34 | } 35 | 36 | public function getClassName(): ClassName 37 | { 38 | return $this->className; 39 | } 40 | 41 | public static function fromDataTransferObject(FrontendWidgetDataTransferObject $widgetDataTransferObject): self 42 | { 43 | return new self( 44 | ModuleName::fromDataTransferObject($widgetDataTransferObject->moduleName), 45 | WidgetName::fromDataTransferObject($widgetDataTransferObject->widgetName) 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Detail/Detail.php: -------------------------------------------------------------------------------- 1 | entityClassName = $entityClassName; 19 | } 20 | 21 | public function getFilePath(float $targetPhpVersion): string 22 | { 23 | return 'Backend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . 24 | $this->entityClassName->getName() . 'Detail.html.twig'; 25 | } 26 | 27 | public function getEntityClassName(): ClassName 28 | { 29 | return $this->entityClassName; 30 | } 31 | 32 | public function getTemplatePath(float $targetPhpVersion): string 33 | { 34 | return __DIR__ . '/Detail.html.twig'; 35 | } 36 | 37 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 38 | { 39 | return new self( 40 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 41 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/File.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:file') 21 | ->setDescription('Generates a file'); 22 | } 23 | 24 | protected function execute(InputInterface $input, OutputInterface $output) 25 | { 26 | parent::execute($input, $output); 27 | 28 | $file = FileClass::fromDataTransferObject($this->getFormData(FileType::class)); 29 | $this->generateService->generateClass($file, $this->getTargetPhpVersion()); 30 | 31 | $generateDBALType = $this->getHelper('question')->ask( 32 | $input, 33 | $output, 34 | new ConfirmationQuestion( 35 | Format::forQuestion('Generate a DBAL type for the file?', 'y') 36 | ) 37 | ); 38 | 39 | if ($generateDBALType) { 40 | $this->generateService->generateClass( 41 | FileDBALType::fromFile($file), 42 | $this->getTargetPhpVersion() 43 | ); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Domain/ValueObject/ValueObject.php: -------------------------------------------------------------------------------- 1 | className = $className; 21 | $this->constants = $constants; 22 | } 23 | 24 | public static function fromDataTransferObject(ValueObjectDataTransferObject $valueObjectDataTransferObject): self 25 | { 26 | return new self( 27 | ClassName::fromDataTransferObject($valueObjectDataTransferObject->className), 28 | array_map( 29 | function (ConstantDataTransferObject $constantDataTransferObject) { 30 | return Constant::fromDataTransferObject($constantDataTransferObject); 31 | }, 32 | $valueObjectDataTransferObject->constants 33 | ) 34 | ); 35 | } 36 | 37 | public function getClassName(): ClassName 38 | { 39 | return $this->className; 40 | } 41 | 42 | public function getConstants(): array 43 | { 44 | return $this->constants; 45 | } 46 | 47 | public function getType(): string 48 | { 49 | return reset($this->constants)->getType(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/Image.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:image') 21 | ->setDescription('Generates a image'); 22 | } 23 | 24 | protected function execute(InputInterface $input, OutputInterface $output) 25 | { 26 | parent::execute($input, $output); 27 | 28 | $image = ImageClass::fromDataTransferObject($this->getFormData(ImageType::class)); 29 | $this->generateService->generateClass($image, $this->getTargetPhpVersion()); 30 | 31 | $generateDBALType = $this->getHelper('question')->ask( 32 | $input, 33 | $output, 34 | new ConfirmationQuestion( 35 | Format::forQuestion('Generate a DBAL type for the image?', 'y') 36 | ) 37 | ); 38 | 39 | if ($generateDBALType) { 40 | $this->generateService->generateClass( 41 | ImageDBALType::fromImage($image), 42 | $this->getTargetPhpVersion() 43 | ); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Domain/ValueObject/ValueObjectType.php: -------------------------------------------------------------------------------- 1 | add( 20 | 'className', 21 | ClassNameType::class 22 | )->add( 23 | 'constants', 24 | CollectionType::class, 25 | [ 26 | 'allow_add' => true, 27 | 'allow_delete' => true, 28 | 'entry_type' => ConstantType::class, 29 | 'constraints' => [ 30 | new Valid(), 31 | new Count(['min' => 1, 'minMessage' => 'You need to add at least 1 constant']), 32 | ], 33 | 'error_bubbling' => false, 34 | ] 35 | ); 36 | } 37 | 38 | public function configureOptions(OptionsResolver $resolver) 39 | { 40 | $resolver->setDefaults( 41 | [ 42 | 'data_class' => ValueObjectDataTransferObject::class, 43 | ] 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/PhpGenerator/Constant/ConstantType.php: -------------------------------------------------------------------------------- 1 | add( 16 | 'name', 17 | TextType::class, 18 | [ 19 | 'label' => 'Name', 20 | 'required' => true, 21 | 'constraints' => [ 22 | new NotBlank(), 23 | ], 24 | ] 25 | )->add( 26 | 'value', 27 | $options['value_type_class_name'], 28 | [ 29 | 'label' => $options['value_label'], 30 | 'required' => true, 31 | 'constraints' => $options['value_constraints'], 32 | ] 33 | ); 34 | } 35 | 36 | public function configureOptions(OptionsResolver $resolver) 37 | { 38 | $resolver->setDefaults( 39 | [ 40 | 'data_class' => ConstantDataTransferObject::class, 41 | 'label' => 'Constant', 42 | 'required' => true, 43 | 'value_type_class_name' => TextType::class, 44 | 'value_label' => 'Value', 45 | 'value_constraints' => [ 46 | new NotBlank(), 47 | ], 48 | ] 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Frontend/Widget/BaseWidget.php: -------------------------------------------------------------------------------- 1 | setName('generate:frontend:widget:base') 20 | ->setDescription('Generate a base widget'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | $frontendWidgetDataTransferObject = $this->getFormData(FrontendWidgetType::class); 28 | 29 | $this->generateWidget($frontendWidgetDataTransferObject); 30 | } 31 | 32 | public function generateWidget(FrontendWidgetDataTransferObject $frontendWidgetDataTransferObject): void 33 | { 34 | $this->generateService->generateClass( 35 | Base::fromDataTransferObject($frontendWidgetDataTransferObject), 36 | $this->getTargetPhpVersion() 37 | ); 38 | $this->generateService->generateFile( 39 | BaseTemplate::fromDataTransferObject($frontendWidgetDataTransferObject), 40 | $this->getTargetPhpVersion() 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Frontend/Action/IndexAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:frontend:action:index') 20 | ->setDescription('Generate an index action'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | $frontendActionDataTransferObject = $this->getFormData(FrontendActionType::class); 28 | 29 | $this->generateAction($frontendActionDataTransferObject); 30 | } 31 | 32 | public function generateAction(FrontendActionDataTransferObject $frontendActionDataTransferObject): void 33 | { 34 | $this->generateService->generateClass( 35 | Index::fromDataTransferObject($frontendActionDataTransferObject), 36 | $this->getTargetPhpVersion() 37 | ); 38 | $this->generateService->generateFile( 39 | IndexTemplate::fromDataTransferObject($frontendActionDataTransferObject), 40 | $this->getTargetPhpVersion() 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Module/Frontend/Actions/Detail/Detail.php71.php.twig: -------------------------------------------------------------------------------- 1 | loadTemplate(); 18 | 19 | ${{ class.entityClassName.forParameter }} = $this->get{{ class.entityClassName }}(); 20 | 21 | $this->template->assign('{{ class.entityClassName.forParameter }}', ${{ class.entityClassName.forParameter }}); 22 | $this->header->setPageTitle(${{ class.entityClassName.forParameter }}->getTitle()); 23 | 24 | // @todo remove if you don't have meta 25 | $this->setMeta(${{ class.entityClassName.forParameter }}->getMeta()); 26 | } 27 | 28 | private function get{{ class.entityClassName }}(): {{ class.entityClassName }} 29 | { 30 | if ($this->url->getParameter(0) === null) { 31 | throw new NotFoundHttpException(); 32 | } 33 | 34 | ${{ class.entityClassName.forParameter }} = $this->get({{ class.entityClassName }}Repository::class)->findBySlugAndLocale( 35 | urldecode($this->url->getParameter(0)), 36 | Locale::frontendLanguage() 37 | ); 38 | 39 | if (${{ class.entityClassName.forParameter }} === null) { 40 | throw new NotFoundHttpException(); 41 | } 42 | 43 | return ${{ class.entityClassName.forParameter }}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Domain/FormType/FormType.php71.php.twig: -------------------------------------------------------------------------------- 1 | add( 19 | '{{ parameter.parameter.name }}', 20 | {{ parameter.formType }}::class, 21 | [ 22 | 'label' => 'lbl.{{ parameter.parameter.forFunction }}',{% if parameter.parameter.isNullable %} 23 | 24 | 'required' => false,{% endif %} 25 | 26 | ] 27 | ); 28 | {% endfor %} 29 | 30 | // @TODO remove when entity doesn't use meta 31 | $builder->addEventSubscriber( 32 | new AddMetaSubscriber( 33 | '@TODO module name', 34 | '@TODO action name', 35 | {{ class.entity.className.name }}Repository::class, 36 | 'getUrl', 37 | [ 38 | 'getData.getLocale', 39 | 'getData.getId', 40 | ] 41 | ) 42 | ); 43 | } 44 | 45 | public function configureOptions(OptionsResolver $resolver): void 46 | { 47 | $resolver->setDefaults(['data_class' => {{ class.entity.className.name }}DataTransferObject::class]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Frontend/Action/DetailAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:frontend:action:detail') 20 | ->setDescription('Generate a detail action'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | $frontendActionDataTransferObject = $this->getFormData(FrontendActionType::class); 28 | 29 | $this->generateAction($frontendActionDataTransferObject); 30 | } 31 | 32 | public function generateAction(FrontendActionDataTransferObject $frontendActionDataTransferObject): void 33 | { 34 | $this->generateService->generateClass( 35 | Detail::fromDataTransferObject($frontendActionDataTransferObject), 36 | $this->getTargetPhpVersion() 37 | ); 38 | $this->generateService->generateFile( 39 | DetailTemplate::fromDataTransferObject($frontendActionDataTransferObject), 40 | $this->getTargetPhpVersion() 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Domain/Command/Create/CreateCommand.php: -------------------------------------------------------------------------------- 1 | className = $className; 23 | $this->dataTransferObjectClassName = $dataTransferObjectClassName; 24 | } 25 | 26 | public function getClassName(): ClassName 27 | { 28 | return $this->className; 29 | } 30 | 31 | public function getDataTransferObjectClassName(): ClassName 32 | { 33 | return $this->dataTransferObjectClassName; 34 | } 35 | 36 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 37 | { 38 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 39 | 40 | return new self( 41 | new ClassName( 42 | 'Create' . $entityClassName->getRealName(), 43 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 44 | ), 45 | new ClassName($entityClassName->getRealName() . 'DataTransferObject', $entityClassName->getNamespace()) 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/AddAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:action:add') 20 | ->setDescription('Generate the add action for an entity'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 28 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 29 | 30 | $this->generateAction($crudActionsDataTransferObject); 31 | } 32 | 33 | public function generateAction(BackendActionDataTransferObject $crudActionsDataTransferObject): void 34 | { 35 | $this->generateService->generateClass( 36 | Add::fromDataTransferObject($crudActionsDataTransferObject), 37 | $this->getTargetPhpVersion() 38 | ); 39 | $this->generateService->generateFile( 40 | AddTemplate::fromDataTransferObject($crudActionsDataTransferObject), 41 | $this->getTargetPhpVersion() 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Kernel.php: -------------------------------------------------------------------------------- 1 | vendorDirectory = $vendorDirectory; 21 | } 22 | 23 | public function registerBundles(): array 24 | { 25 | return [ 26 | new FrameworkBundle(), 27 | new TwigBundle(), 28 | new SymfonyConsoleFormBundle(), 29 | ]; 30 | } 31 | 32 | public function registerContainerConfiguration(LoaderInterface $loader) 33 | { 34 | $loader->load(__DIR__ . '/config.yml'); 35 | 36 | if ($this->environment === 'test') { 37 | $loader->load(__DIR__ . '/config_test.yml'); 38 | } 39 | } 40 | 41 | public function getCacheDir(): string 42 | { 43 | return __DIR__ . '/cache/' . $this->environment; 44 | } 45 | 46 | public function getLogDir(): string 47 | { 48 | return __DIR__ . '/logs/' . $this->environment; 49 | } 50 | 51 | protected function buildContainer(): ContainerInterface 52 | { 53 | $container = parent::buildContainer(); 54 | 55 | $container->setParameter('vendor_directory', $this->vendorDirectory); 56 | 57 | return $container; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/EditAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:action:edit') 20 | ->setDescription('Generate the edit action for an entity'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 28 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 29 | 30 | $this->generateAction($crudActionsDataTransferObject); 31 | } 32 | 33 | public function generateAction(BackendActionDataTransferObject $crudActionsDataTransferObject): void 34 | { 35 | $this->generateService->generateClass( 36 | Edit::fromDataTransferObject($crudActionsDataTransferObject), 37 | $this->getTargetPhpVersion() 38 | ); 39 | $this->generateService->generateFile( 40 | EditTemplate::fromDataTransferObject($crudActionsDataTransferObject), 41 | $this->getTargetPhpVersion() 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/ValueObject.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:value-object') 21 | ->setDescription('Generates a value object'); 22 | } 23 | 24 | protected function execute(InputInterface $input, OutputInterface $output) 25 | { 26 | parent::execute($input, $output); 27 | 28 | $valueObject = ValueObjectClass::fromDataTransferObject($this->getFormData(ValueObjectType::class)); 29 | $this->generateService->generateClass($valueObject, $this->getTargetPhpVersion()); 30 | 31 | $generateDBALType = $this->getHelper('question')->ask( 32 | $input, 33 | $output, 34 | new ConfirmationQuestion( 35 | Format::forQuestion('Generate a DBAL type for the value object?', 'y') 36 | ) 37 | ); 38 | 39 | if ($generateDBALType) { 40 | $this->generateService->generateClass( 41 | ValueObjectDBALType::fromValueObject($valueObject), 42 | $this->getTargetPhpVersion() 43 | ); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Module/Backend/Layout/Templates/Settings/Settings.php: -------------------------------------------------------------------------------- 1 | entityClassName = $entityClassName; 20 | } 21 | 22 | public function getFilePath(float $targetPhpVersion): string 23 | { 24 | return 'Backend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . 25 | $this->entityClassName->getName() . '.html.twig'; 26 | } 27 | 28 | public function getEntityClassName(): ClassName 29 | { 30 | return $this->entityClassName; 31 | } 32 | 33 | public function getTemplatePath(float $targetPhpVersion): string 34 | { 35 | return __DIR__ . '/Settings.html.twig'; 36 | } 37 | 38 | public static function fromDataTransferObject( 39 | BackendSettingsActionDataTransferObject $backendSettingsActionDataTransferObject 40 | ): self { 41 | return new self( 42 | ModuleName::fromDataTransferObject($backendSettingsActionDataTransferObject->moduleName), 43 | ClassName::fromDataTransferObject($backendSettingsActionDataTransferObject->settingClassName) 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/IndexAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:action:index') 20 | ->setDescription('Generate the index action for an entity'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 28 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 29 | 30 | $this->generateAction($crudActionsDataTransferObject); 31 | } 32 | 33 | public function generateAction(BackendActionDataTransferObject $crudActionsDataTransferObject): void 34 | { 35 | $this->generateService->generateClass( 36 | Index::fromDataTransferObject($crudActionsDataTransferObject), 37 | $this->getTargetPhpVersion() 38 | ); 39 | $this->generateService->generateFile( 40 | IndexTemplate::fromDataTransferObject($crudActionsDataTransferObject), 41 | $this->getTargetPhpVersion() 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Backend/Action/DetailAction.php: -------------------------------------------------------------------------------- 1 | setName('generate:backend:action:detail') 20 | ->setDescription('Generate the detail action for an entity'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | parent::execute($input, $output); 26 | 27 | /** @var BackendActionDataTransferObject $crudActionsDataTransferObject */ 28 | $crudActionsDataTransferObject = $this->getFormData(BackendActionType::class); 29 | 30 | $this->generateAction($crudActionsDataTransferObject); 31 | } 32 | 33 | public function generateAction(BackendActionDataTransferObject $crudActionsDataTransferObject): void 34 | { 35 | $this->generateService->generateClass( 36 | Detail::fromDataTransferObject($crudActionsDataTransferObject), 37 | $this->getTargetPhpVersion() 38 | ); 39 | $this->generateService->generateFile( 40 | DetailTemplate::fromDataTransferObject($crudActionsDataTransferObject), 41 | $this->getTargetPhpVersion() 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Domain/Entity/Entity.php: -------------------------------------------------------------------------------- 1 | className = $className; 24 | $this->tableName = $tableName; 25 | $this->parameters = $parameters; 26 | } 27 | 28 | public function getClassName(): ClassName 29 | { 30 | return $this->className; 31 | } 32 | 33 | public function getTableName(): string 34 | { 35 | return $this->tableName; 36 | } 37 | 38 | public function getParameters(): array 39 | { 40 | return $this->parameters; 41 | } 42 | 43 | public static function fromDataTransferObject(EntityDataTransferObject $entityDataTransferObject): self 44 | { 45 | return new self( 46 | ClassName::fromDataTransferObject($entityDataTransferObject->className), 47 | $entityDataTransferObject->tableName, 48 | array_map( 49 | function (ParameterDataTransferObject $parameterDataTransferObject): Parameter { 50 | return Parameter::fromDataTransferObject($parameterDataTransferObject); 51 | }, 52 | $entityDataTransferObject->parameters 53 | ) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Domain/Image/ImageType.php: -------------------------------------------------------------------------------- 1 | add( 17 | 'className', 18 | ClassNameType::class 19 | )->add( 20 | 'maxFileSize', 21 | TextType::class, 22 | [ 23 | 'label' => 'Max file size (optional)', 24 | 'required' => false, 25 | ] 26 | )->add( 27 | 'mimeTypes', 28 | TextType::class, 29 | [ 30 | 'label' => 'Allowed mime types', 31 | 'data' => $options['mime_types'], 32 | ] 33 | )->add( 34 | 'mimeTypeErrorMessage', 35 | TextType::class, 36 | [ 37 | 'label' => 'Error message when wrong mime type is passed', 38 | 'data' => $options['mime_type_error_message'], 39 | ] 40 | ); 41 | } 42 | 43 | public function configureOptions(OptionsResolver $resolver) 44 | { 45 | $resolver->setDefaults( 46 | [ 47 | 'data_class' => ImageDataTransferObject::class, 48 | 'mime_types' => '{"image/jpeg", "image/gif", "image/png"}', 49 | 'mime_type_error_message' => 'err.JPGGIFAndPNGOnly', 50 | ] 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/PhpGenerator/PhpNamespace/PhpNamespaceType.php: -------------------------------------------------------------------------------- 1 | add( 18 | 'name', 19 | TextType::class, 20 | [ 21 | 'label' => $options['name_label'], 22 | 'required' => true, 23 | 'constraints' => [ 24 | new NotBlank(), 25 | new Regex( 26 | [ 27 | 'pattern' => '/^(?:\\w+|\\w+\\\\)(?:\\w+\\\\?\\w+)+$/', 28 | 'message' => 'Invalid namespace', 29 | ] 30 | ), 31 | ], 32 | 'error_bubbling' => true, 33 | ] 34 | ); 35 | } 36 | 37 | public function configureOptions(OptionsResolver $resolver) 38 | { 39 | $resolver->setDefaults( 40 | [ 41 | 'data_class' => PhpNamespaceDataTransferObject::class, 42 | 'label' => '', 43 | 'required' => true, 44 | 'constraints' => [ 45 | new Valid(), 46 | ], 47 | 'error_bubbling' => false, 48 | 'name_label' => 'Namespace (i.e.: Console\\ValueObject)', 49 | ] 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Add/Add.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName() . 'Add', 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 50 | { 51 | return new self( 52 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 53 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Edit/Edit.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName() . 'Edit', 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 50 | { 51 | return new self( 52 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 53 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Index/Index.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName() . 'Index', 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 50 | { 51 | return new self( 52 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 53 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Delete/Delete.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName() . 'Delete', 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 50 | { 51 | return new self( 52 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 53 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Detail/Detail.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName() . 'Detail', 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject(BackendActionDataTransferObject $crudActionsDataTransferObject): self 50 | { 51 | return new self( 52 | ModuleName::fromDataTransferObject($crudActionsDataTransferObject->moduleName), 53 | ClassName::fromDataTransferObject($crudActionsDataTransferObject->entityClassName) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Domain/File/File.php: -------------------------------------------------------------------------------- 1 | className = $className; 25 | $this->maxFileSize = $maxFileSize; 26 | $this->uploadDirectory = $uploadDirectory; 27 | } 28 | 29 | public static function fromDataTransferObject(FileDataTransferObject $fileDataTransferObject): self 30 | { 31 | $className = ClassName::fromDataTransferObject($fileDataTransferObject->className); 32 | $matches = 0; 33 | $uploadDirectory = preg_replace( 34 | '|\\\\Backend\\\\Modules\\\\(.+?)\\\\Domain\\\\(.+?)\\\\(.+?)$|', 35 | '$1/$2/$3', 36 | $className->getFullyQualifiedName(), 37 | -1, 38 | $matches 39 | ); 40 | 41 | if ($matches === 0) { 42 | $uploadDirectory = $className->getRealName(); 43 | } 44 | 45 | return new self( 46 | $className, 47 | $fileDataTransferObject->maxFileSize, 48 | $uploadDirectory 49 | ); 50 | } 51 | 52 | public function getClassName(): ClassName 53 | { 54 | return $this->className; 55 | } 56 | 57 | public function getMaxFileSize(): ?string 58 | { 59 | return $this->maxFileSize; 60 | } 61 | 62 | public function getUploadDirectory(): string 63 | { 64 | return $this->uploadDirectory; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/BackendSettingsActionType.php: -------------------------------------------------------------------------------- 1 | add( 20 | 'moduleName', 21 | ModuleNameType::class 22 | ) 23 | ->add( 24 | 'settingClassName', 25 | ClassNameType::class, 26 | [ 27 | 'label' => 'Setting class name', 28 | 'name_label' => 'Setting class name', 29 | 'namespace_label' => 'Setting namespace (i.e.: Backend\\Modules\\MyModule\\Domain\\Settings)', 30 | ] 31 | )->add( 32 | 'settings', 33 | CollectionType::class, 34 | [ 35 | 'entry_type' => ParameterType::class, 36 | 'allow_add' => true, 37 | 'label' => 'Settings', 38 | 'constraints' => [ 39 | new Valid(), 40 | ], 41 | ] 42 | ); 43 | } 44 | 45 | public function configureOptions(OptionsResolver $resolver): void 46 | { 47 | $resolver->setDefaults(['data_class' => BackendSettingsActionDataTransferObject::class]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Settings/Settings.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 27 | $this->entityClassName = $entityClassName; 28 | $this->className = new ClassName( 29 | $this->entityClassName->getName(), 30 | new PhpNamespace('Backend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 31 | ); 32 | } 33 | 34 | public function getModuleName(): ModuleName 35 | { 36 | return $this->moduleName; 37 | } 38 | 39 | public function getEntityClassName(): ClassName 40 | { 41 | return $this->entityClassName; 42 | } 43 | 44 | public function getClassName(): ClassName 45 | { 46 | return $this->className; 47 | } 48 | 49 | public static function fromDataTransferObject( 50 | BackendSettingsActionDataTransferObject $backendSettingsActionDataTransferObject 51 | ): self { 52 | return new self( 53 | ModuleName::fromDataTransferObject($backendSettingsActionDataTransferObject->moduleName), 54 | ClassName::fromDataTransferObject($backendSettingsActionDataTransferObject->settingClassName) 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Settings/Settings.php71.php.twig: -------------------------------------------------------------------------------- 1 | getForm(); 18 | 19 | if (!$form->isSubmitted() || !$form->isValid()) { 20 | $this->template->assign('form', $form->createView()); 21 | 22 | $this->parse(); 23 | $this->display(); 24 | 25 | return; 26 | } 27 | 28 | $this->handleForm($form); 29 | } 30 | 31 | private function handleForm(Form $form): void 32 | { 33 | $save{{ class.entityClassName.name }} = $form->getData(); 34 | 35 | $this->get('command_bus')->handle($save{{ class.entityClassName.name }}); 36 | 37 | $this->redirect( 38 | $this->getBackLink( 39 | [ 40 | 'report' => 'saved', 41 | ] 42 | ) 43 | ); 44 | } 45 | 46 | private function getForm(): Form 47 | { 48 | $form = $this->createForm({{ class.entityClassName.name }}Type::class, new Save{{ class.entityClassName.name }}($this->get('fork.settings'))); 49 | 50 | $form->handleRequest($this->getRequest()); 51 | 52 | return $form; 53 | } 54 | 55 | private function getBackLink(array $parameters = []): string 56 | { 57 | return BackendModel::createUrlForAction( 58 | '{{ class.entityClassName.name }}', 59 | null, 60 | null, 61 | $parameters 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Domain/DataGrid/DataGrid.php: -------------------------------------------------------------------------------- 1 | tableName = $tableName; 29 | $this->moduleName = $moduleName; 30 | $this->entityClassName = $entityClassName; 31 | $this->className = new ClassName( 32 | $this->entityClassName->getName() . 'DataGrid', 33 | $this->entityClassName->getNamespace() 34 | ); 35 | } 36 | 37 | public function getModuleName(): ModuleName 38 | { 39 | return $this->moduleName; 40 | } 41 | 42 | public function getEntityClassName(): ClassName 43 | { 44 | return $this->entityClassName; 45 | } 46 | 47 | public function getClassName(): ClassName 48 | { 49 | return $this->className; 50 | } 51 | 52 | public function getTableName(): string 53 | { 54 | return $this->tableName; 55 | } 56 | 57 | public static function fromDataTransferObject(DataGridDataTransferObject $dataGridDataTransferObject): self 58 | { 59 | return new self( 60 | ModuleName::fromDataTransferObject($dataGridDataTransferObject->moduleName), 61 | ClassName::fromDataTransferObject($dataGridDataTransferObject->entityClassName), 62 | $dataGridDataTransferObject->tableName 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Domain/File/FileDBALType.php: -------------------------------------------------------------------------------- 1 | className = $className; 27 | $this->fileClassName = $fileClassName; 28 | $this->name = $name; 29 | } 30 | 31 | public static function fromFile(File $file): self 32 | { 33 | $matches = 0; 34 | $name = preg_replace( 35 | '|\\\\Backend\\\\Modules\\\\(.+?)\\\\Domain\\\\(.+?)\\\\(.+?)$|', 36 | '$1_$2_$3', 37 | $file->getClassName()->getFullyQualifiedName(), 38 | -1, 39 | $matches 40 | ); 41 | 42 | if ($matches === 0) { 43 | $name = $file->getClassName()->getRealName(); 44 | } 45 | 46 | return new self( 47 | new ClassName( 48 | $file->getClassName()->getRealName() . 'DBALType', 49 | $file->getClassName()->getNamespace() 50 | ), 51 | $file->getClassName(), 52 | mb_strtolower($name) 53 | ); 54 | } 55 | 56 | public function getClassName(): ClassName 57 | { 58 | return $this->className; 59 | } 60 | 61 | public function getFileClassName(): ClassName 62 | { 63 | return $this->fileClassName; 64 | } 65 | 66 | public function getName(): string 67 | { 68 | return $this->name; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Domain/Image/ImageDBALType.php: -------------------------------------------------------------------------------- 1 | className = $className; 27 | $this->imageClassName = $imageClassName; 28 | $this->name = $name; 29 | } 30 | 31 | public static function fromImage(Image $image): self 32 | { 33 | $matches = 0; 34 | $name = preg_replace( 35 | '|\\\\Backend\\\\Modules\\\\(.+?)\\\\Domain\\\\(.+?)\\\\(.+?)$|', 36 | '$1_$2_$3', 37 | $image->getClassName()->getFullyQualifiedName(), 38 | -1, 39 | $matches 40 | ); 41 | 42 | if ($matches === 0) { 43 | $name = $image->getClassName()->getRealName(); 44 | } 45 | 46 | return new self( 47 | new ClassName( 48 | $image->getClassName()->getRealName() . 'DBALType', 49 | $image->getClassName()->getNamespace() 50 | ), 51 | $image->getClassName(), 52 | mb_strtolower($name) 53 | ); 54 | } 55 | 56 | public function getClassName(): ClassName 57 | { 58 | return $this->className; 59 | } 60 | 61 | public function getImageClassName(): ClassName 62 | { 63 | return $this->imageClassName; 64 | } 65 | 66 | public function getName(): string 67 | { 68 | return $this->name; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Domain/ValueObject/ValueObject.php71.php.twig: -------------------------------------------------------------------------------- 1 | {{ class.className.forParameter }} = ${{ class.className.forParameter }}; 27 | } 28 | 29 | public function getValue(): {{ class.type }} 30 | { 31 | return $this->{{ class.className.forParameter }}; 32 | } 33 | 34 | public function __toString(): string 35 | { 36 | return (string) $this->{{ class.className.forParameter }}; 37 | } 38 | 39 | public function equals(self ${{ class.className.forParameter }}): bool 40 | { 41 | if (!(${{ class.className.forParameter }} instanceof $this)) { 42 | return false; 43 | } 44 | 45 | return ${{ class.className.forParameter }}->{{ class.className.forParameter }} === $this->{{ class.className.forParameter }}; 46 | } 47 | {% for constant in class.constants %} 48 | 49 | public static function {{ constant.camelCasedName }}(): self 50 | { 51 | return new self(self::{{ constant.name }}); 52 | } 53 | 54 | public function is{{ constant.camelCasedName(true) }}(): bool 55 | { 56 | return $this->equals(self::{{ constant.camelCasedName }}()); 57 | } 58 | {% endfor -%} 59 | } 60 | -------------------------------------------------------------------------------- /src/Domain/DataGrid/DataGridType.php: -------------------------------------------------------------------------------- 1 | add( 19 | 'moduleName', 20 | ModuleNameType::class 21 | ) 22 | ->add( 23 | 'entityClassName', 24 | ClassNameType::class, 25 | [ 26 | 'label' => 'Entity class name', 27 | 'name_label' => 'Entity class name', 28 | 'namespace_label' => 'Entity namespace (i.e.: Backend\\Modules\MyModule\Domain\MyEntity)', 29 | ] 30 | )->add( 31 | 'tableName', 32 | TextType::class, 33 | [ 34 | 'label' => 'Table name', 35 | 'constraints' => [ 36 | new Regex( 37 | [ 38 | 'pattern' => '/^[\p{L}_][\p{L}\p{N}@$#_]{0,127}$/', 39 | 'message' => 'Invalid database table name', 40 | ] 41 | ), 42 | ], 43 | ] 44 | ); 45 | } 46 | 47 | public function configureOptions(OptionsResolver $resolver) 48 | { 49 | $resolver->setDefaults( 50 | [ 51 | 'data_class' => DataGridDataTransferObject::class, 52 | ] 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Module/Backend/Info/InfoType.php: -------------------------------------------------------------------------------- 1 | add( 19 | 'moduleName', 20 | ModuleNameType::class 21 | )->add( 22 | 'moduleVersion', 23 | SemVerType::class, 24 | [ 25 | 'label' => 'Module version', 26 | ] 27 | )->add( 28 | 'moduleVersion', 29 | SemVerType::class, 30 | [ 31 | 'label' => 'Module version', 32 | ] 33 | )->add( 34 | 'minimumForkVersion', 35 | SemVerType::class, 36 | [ 37 | 'label' => 'Minimum fork version', 38 | 'data' => new version('5.0.0'), 39 | ] 40 | )->add( 41 | 'moduleDescription', 42 | TextType::class, 43 | [ 44 | 'label' => 'Module description', 45 | 'constraints' => [ 46 | new NotBlank(), 47 | ], 48 | ] 49 | ); 50 | } 51 | 52 | public function configureOptions(OptionsResolver $resolver) 53 | { 54 | $resolver->setDefaults( 55 | [ 56 | 'data_class' => InfoDataTransferObject::class, 57 | 'label' => 'Module info', 58 | 'required' => true, 59 | ] 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/PhpGenerator/SemVer/SemVerType.php: -------------------------------------------------------------------------------- 1 | addModelTransformer( 19 | new CallbackTransformer( 20 | function (version $version = null) use ($options) { 21 | return $version; 22 | }, 23 | function (string $version) { 24 | try { 25 | return new version($version); 26 | } catch (SemVerException $semVerException) { 27 | throw new TransformationFailedException( 28 | $semVerException->getMessage(), 29 | $semVerException->getCode(), 30 | $semVerException 31 | ); 32 | } 33 | } 34 | ) 35 | ); 36 | } 37 | 38 | public function getParent(): string 39 | { 40 | return TextType::class; 41 | } 42 | 43 | public function configureOptions(OptionsResolver $resolver) 44 | { 45 | parent::configureOptions($resolver); 46 | 47 | $resolver->setDefaults( 48 | [ 49 | 'label' => false, 50 | 'required' => true, 51 | 'invalid_message' => 'invalid semver version number', 52 | 'data' => new version('1.0.0'), 53 | ] 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/Repository.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:repository') 21 | ->setDescription('Generates the repository class for an entity'); 22 | } 23 | 24 | protected function execute(InputInterface $input, OutputInterface $output) 25 | { 26 | parent::execute($input, $output); 27 | 28 | $this->createRepository(ClassName::fromDataTransferObject($this->getFormData(RepositoryType::class))); 29 | } 30 | 31 | public function createRepository(ClassName $entityClassName): void 32 | { 33 | $repositoryClass = RepositoryClass::fromEntityClassName($entityClassName); 34 | $this->generateService->generateClass( 35 | $repositoryClass, 36 | $this->getTargetPhpVersion() 37 | ); 38 | 39 | $moduleName = $this->extractModuleName($repositoryClass->getClassName()->getNamespace()); 40 | if ($moduleName instanceof ModuleName) { 41 | $this->generateService->generateFile( 42 | new Repositories( 43 | $moduleName, 44 | [$repositoryClass->getClassName()->getForUseStatement()], 45 | true 46 | ), 47 | $this->getTargetPhpVersion() 48 | ); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Domain/Command/Update/UpdateCommandHandler.php: -------------------------------------------------------------------------------- 1 | className = $className; 27 | $this->entityClassName = $entityClassName; 28 | $this->commandClassName = $commandClassName; 29 | } 30 | 31 | public function getClassName(): ClassName 32 | { 33 | return $this->className; 34 | } 35 | 36 | public function getEntityClassName(): ClassName 37 | { 38 | return $this->entityClassName; 39 | } 40 | 41 | public function getCommandClassName(): ClassName 42 | { 43 | return $this->commandClassName; 44 | } 45 | 46 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 47 | { 48 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 49 | 50 | return new self( 51 | new ClassName( 52 | 'Update' . $entityClassName->getRealName() . 'Handler', 53 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 54 | ), 55 | $entityClassName, 56 | new ClassName('Update' . $entityClassName->getRealName(), $entityClassName->getNamespace()) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Templates/Index/Index.php: -------------------------------------------------------------------------------- 1 | actionName = $actionName; 23 | $this->entityClassName = $entityClassName; 24 | } 25 | 26 | public function getFilePath(float $targetPhpVersion): string 27 | { 28 | return 'Frontend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . $this->actionName . '.html.twig'; 29 | } 30 | 31 | public function getActionName(): ActionName 32 | { 33 | return $this->actionName; 34 | } 35 | 36 | public function getEntityClassName(): ClassName 37 | { 38 | return $this->entityClassName; 39 | } 40 | 41 | public function getTemplatePath(float $targetPhpVersion): string 42 | { 43 | return __DIR__ . '/Index.html.twig'; 44 | } 45 | 46 | public static function fromDataTransferObject(FrontendActionDataTransferObject $frontendActionDataTransferObject): self 47 | { 48 | return new self( 49 | ModuleName::fromDataTransferObject($frontendActionDataTransferObject->moduleName), 50 | ClassName::fromDataTransferObject($frontendActionDataTransferObject->entityClassName), 51 | ActionName::fromDataTransferObject($frontendActionDataTransferObject->actionName) 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Module/Frontend/Actions/Detail/Detail.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 29 | $this->entityClassName = $entityClassName; 30 | $this->className = new ClassName( 31 | $actionName, 32 | new PhpNamespace('Frontend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 33 | ); 34 | } 35 | 36 | public function getModuleName(): ModuleName 37 | { 38 | return $this->moduleName; 39 | } 40 | 41 | public function getEntityClassName(): ClassName 42 | { 43 | return $this->entityClassName; 44 | } 45 | 46 | public function getClassName(): ClassName 47 | { 48 | return $this->className; 49 | } 50 | 51 | public static function fromDataTransferObject(FrontendActionDataTransferObject $actionDataTransferObject): self 52 | { 53 | return new self( 54 | ModuleName::fromDataTransferObject($actionDataTransferObject->moduleName), 55 | ClassName::fromDataTransferObject($actionDataTransferObject->entityClassName), 56 | ActionName::fromDataTransferObject($actionDataTransferObject->actionName) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Module/Frontend/Actions/Index/Index.php: -------------------------------------------------------------------------------- 1 | moduleName = $moduleName; 29 | $this->entityClassName = $entityClassName; 30 | $this->className = new ClassName( 31 | $actionName, 32 | new PhpNamespace('Frontend\\Modules\\' . $this->moduleName->getName() . '\\Actions') 33 | ); 34 | } 35 | 36 | public function getModuleName(): ModuleName 37 | { 38 | return $this->moduleName; 39 | } 40 | 41 | public function getEntityClassName(): ClassName 42 | { 43 | return $this->entityClassName; 44 | } 45 | 46 | public function getClassName(): ClassName 47 | { 48 | return $this->className; 49 | } 50 | 51 | public static function fromDataTransferObject(FrontendActionDataTransferObject $actionDataTransferObject): self 52 | { 53 | return new self( 54 | ModuleName::fromDataTransferObject($actionDataTransferObject->moduleName), 55 | ClassName::fromDataTransferObject($actionDataTransferObject->entityClassName), 56 | ActionName::fromDataTransferObject($actionDataTransferObject->actionName) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Module/Frontend/Layout/Templates/Detail/Detail.php: -------------------------------------------------------------------------------- 1 | actionName = $actionName; 23 | $this->entityClassName = $entityClassName; 24 | } 25 | 26 | public function getFilePath(float $targetPhpVersion): string 27 | { 28 | return 'Frontend/Modules/' . $this->getModuleName() . '/Layout/Templates/' . $this->actionName . '.html.twig'; 29 | } 30 | 31 | public function getActionName(): ActionName 32 | { 33 | return $this->actionName; 34 | } 35 | 36 | public function getEntityClassName(): ClassName 37 | { 38 | return $this->entityClassName; 39 | } 40 | 41 | public function getTemplatePath(float $targetPhpVersion): string 42 | { 43 | return __DIR__ . '/Detail.html.twig'; 44 | } 45 | 46 | public static function fromDataTransferObject(FrontendActionDataTransferObject $frontendActionDataTransferObject): self 47 | { 48 | return new self( 49 | ModuleName::fromDataTransferObject($frontendActionDataTransferObject->moduleName), 50 | ClassName::fromDataTransferObject($frontendActionDataTransferObject->entityClassName), 51 | ActionName::fromDataTransferObject($frontendActionDataTransferObject->actionName) 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Domain/Command/Update/UpdateCommand.php: -------------------------------------------------------------------------------- 1 | className = $className; 27 | $this->entityClassName = $entityClassName; 28 | $this->dataTransferObjectClassName = $dataTransferObjectClassName; 29 | } 30 | 31 | public function getClassName(): ClassName 32 | { 33 | return $this->className; 34 | } 35 | 36 | public function getEntityClassName(): ClassName 37 | { 38 | return $this->entityClassName; 39 | } 40 | 41 | public function getDataTransferObjectClassName(): ClassName 42 | { 43 | return $this->dataTransferObjectClassName; 44 | } 45 | 46 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 47 | { 48 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 49 | 50 | return new self( 51 | new ClassName( 52 | 'Update' . $entityClassName->getRealName(), 53 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 54 | ), 55 | $entityClassName, 56 | new ClassName($entityClassName->getRealName() . 'DataTransferObject', $entityClassName->getNamespace()) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Delete/Delete.php71.php.twig: -------------------------------------------------------------------------------- 1 | get{{ class.entityClassName.name }}(); 17 | if (!${{ class.entityClassName.forParameter }} instanceof {{ class.entityClassName.name }}) { 18 | $this->redirect($this->getBackLink(['error' => 'non-existing'])); 19 | 20 | return; 21 | } 22 | 23 | $this->get('command_bus')->handle(new Delete{{ class.entityClassName.name }}(${{ class.entityClassName.forParameter }})); 24 | 25 | $this->redirect($this->getBackLink(['report' => 'deleted', 'var' => ${{ class.entityClassName.forParameter }}->getTitle()])); 26 | } 27 | 28 | private function getBackLink(array $parameters = []): string 29 | { 30 | return BackendModel::createUrlForAction( 31 | '{{ class.entityClassName.name }}Index', 32 | null, 33 | null, 34 | $parameters 35 | ); 36 | } 37 | 38 | private function get{{ class.entityClassName.name }}(): ?{{ class.entityClassName.name }} 39 | { 40 | $deleteForm = $this->createForm(DeleteType::class, null, ['module' => $this->getModule()]); 41 | $deleteForm->handleRequest($this->getRequest()); 42 | 43 | if (!$deleteForm->isSubmitted() || !$deleteForm->isValid()) { 44 | return null; 45 | } 46 | 47 | return $this->get({{ class.entityClassName.name }}Repository::class)->find($deleteForm->getData()['id']); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Module/Backend/Actions/Add/Add.php71.php.twig: -------------------------------------------------------------------------------- 1 | getForm(); 19 | 20 | if (!$form->isSubmitted() || !$form->isValid()) { 21 | $this->template->assign('form', $form->createView()); 22 | 23 | $this->parse(); 24 | $this->display(); 25 | 26 | return; 27 | } 28 | 29 | $this->handleForm($form); 30 | } 31 | 32 | private function handleForm(Form $form): void 33 | { 34 | $create{{ class.entityClassName.name }} = $form->getData(); 35 | 36 | $this->get('command_bus')->handle($create{{ class.entityClassName.name }}); 37 | 38 | $this->redirect( 39 | $this->getBackLink( 40 | [ 41 | 'report' => 'added', 42 | 'var' => $create{{ class.entityClassName.name }}->title, 43 | ] 44 | ) 45 | ); 46 | } 47 | 48 | private function getForm(): Form 49 | { 50 | $form = $this->createForm({{ class.entityClassName.name }}Type::class, new Create{{ class.entityClassName.name }}(Locale::workingLocale())); 51 | 52 | $form->handleRequest($this->getRequest()); 53 | 54 | return $form; 55 | } 56 | 57 | private function getBackLink(array $parameters = []): string 58 | { 59 | return BackendModel::createUrlForAction( 60 | '{{ class.entityClassName.name }}Index', 61 | null, 62 | null, 63 | $parameters 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Module/Backend/Info/Info.php: -------------------------------------------------------------------------------- 1 | moduleVersion = $moduleVersion; 29 | $this->minimumForkVersion = $minimumForkVersion; 30 | $this->moduleDescription = $moduleDescription; 31 | } 32 | 33 | public function getModuleVersion(): version 34 | { 35 | return $this->moduleVersion; 36 | } 37 | 38 | public function getMinimumForkVersion(): version 39 | { 40 | return $this->minimumForkVersion; 41 | } 42 | 43 | public function getModuleDescription(): string 44 | { 45 | return $this->moduleDescription; 46 | } 47 | 48 | public function getFilePath(float $targetPhpVersion): string 49 | { 50 | return 'Backend/Modules/' . $this->getModuleName() . '/info.xml'; 51 | } 52 | 53 | public function getTemplatePath(float $targetPhpVersion): string 54 | { 55 | return __DIR__ . '/info.xml.twig'; 56 | } 57 | 58 | public static function fromDataTransferObject(InfoDataTransferObject $infoDataTransferObject): self 59 | { 60 | return new self( 61 | ModuleName::fromDataTransferObject($infoDataTransferObject->moduleName), 62 | $infoDataTransferObject->moduleVersion, 63 | $infoDataTransferObject->minimumForkVersion, 64 | $infoDataTransferObject->moduleDescription 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Domain/Entity.php: -------------------------------------------------------------------------------- 1 | setName('generate:domain:entity') 22 | ->setDescription('Generates a entity'); 23 | } 24 | 25 | protected function execute(InputInterface $input, OutputInterface $output) 26 | { 27 | parent::execute($input, $output); 28 | 29 | $formInteractor = function (string $className, array $options = [], $data = null) { 30 | return $this->getFormData($className, $options, $data); 31 | }; 32 | 33 | $entity = EntityClass::fromDataTransferObject( 34 | $this->getFormData(EntityType::class, ['form-interactor' => $formInteractor]) 35 | ); 36 | 37 | $this->generateService->generateClasses( 38 | [$entity, new DataTransferObject($entity), new FormType($entity)], 39 | $this->getTargetPhpVersion() 40 | ); 41 | 42 | $moduleName = $this->extractModuleName($entity->getClassName()->getNamespace()); 43 | if ($moduleName instanceof ModuleName) { 44 | $this->generateService->generateFile( 45 | new Doctrine( 46 | $moduleName, 47 | [$entity], 48 | true 49 | ), 50 | $this->getTargetPhpVersion() 51 | ); 52 | } 53 | 54 | (new Repository($this->generateService))->setTargetPhpVersion($this->getTargetPhpVersion())->createRepository( 55 | $entity->getClassName() 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Domain/Entity/EntityType.php: -------------------------------------------------------------------------------- 1 | add( 21 | 'className', 22 | ClassNameType::class, 23 | [ 24 | 'name_label' => 'Entity name (i.e.: User)', 25 | ] 26 | )->add( 27 | 'tableName', 28 | TextType::class, 29 | [ 30 | 'label' => 'Table name', 31 | 'constraints' => [ 32 | new Regex( 33 | [ 34 | 'pattern' => '/^[\p{L}_][\p{L}\p{N}@$#_]{0,127}$/', 35 | 'message' => 'Invalid database table name', 36 | ] 37 | ), 38 | ], 39 | ] 40 | )->add( 41 | 'parameters', 42 | CollectionType::class, 43 | [ 44 | 'entry_type' => ParameterType::class, 45 | 'allow_add' => true, 46 | 'label' => 'Parameters (the id, createdOn, and editedOn are already added)!', 47 | 'constraints' => [ 48 | new Valid() 49 | ] 50 | ] 51 | ); 52 | } 53 | 54 | public function configureOptions(OptionsResolver $resolver) 55 | { 56 | $resolver->setRequired(['form-interactor']); 57 | 58 | $resolver->setDefault('data_class', EntityDataTransferObject::class); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Domain/Command/Settings/SettingsCommand.php: -------------------------------------------------------------------------------- 1 | className = $className; 27 | $this->settings = $settings; 28 | $this->moduleName = $moduleName; 29 | } 30 | 31 | public function getClassName(): ClassName 32 | { 33 | return $this->className; 34 | } 35 | 36 | public function getSettings(): array 37 | { 38 | return $this->settings; 39 | } 40 | 41 | public function getModuleName(): ModuleName 42 | { 43 | return $this->moduleName; 44 | } 45 | 46 | public static function fromDataTransferObject( 47 | BackendSettingsActionDataTransferObject $backendSettingsActionDataTransferObject 48 | ): self { 49 | return new self( 50 | new ClassName( 51 | 'Save' . $backendSettingsActionDataTransferObject->settingClassName->name, 52 | new PhpNamespace($backendSettingsActionDataTransferObject->settingClassName->namespace->name . '\Command') 53 | ), 54 | array_map( 55 | function (ParameterDataTransferObject $parameterDataTransferObject): Parameter { 56 | return Parameter::fromDataTransferObject($parameterDataTransferObject); 57 | }, 58 | $backendSettingsActionDataTransferObject->settings 59 | ), 60 | ModuleName::fromDataTransferObject($backendSettingsActionDataTransferObject->moduleName) 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Domain/ValueObject/ValueObjectDBALType.php: -------------------------------------------------------------------------------- 1 | className = $className; 31 | $this->valueObjectClassName = $valueObjectClassName; 32 | $this->type = $type; 33 | $this->name = $name; 34 | } 35 | 36 | public static function fromValueObject(ValueObject $valueObject): self 37 | { 38 | $matches = 0; 39 | $name = preg_replace( 40 | '|\\\\Backend\\\\Modules\\\\(.+?)\\\\Domain\\\\(.+?)\\\\(.+?)$|', 41 | '$1_$2_$3', 42 | $valueObject->getClassName()->getFullyQualifiedName(), 43 | -1, 44 | $matches 45 | ); 46 | 47 | if ($matches === 0) { 48 | $name = $valueObject->getClassName()->getRealName(); 49 | } 50 | 51 | return new self( 52 | new ClassName( 53 | $valueObject->getClassName()->getRealName() . 'DBALType', 54 | $valueObject->getClassName()->getNamespace() 55 | ), 56 | $valueObject->getClassName(), 57 | $valueObject->getType(), 58 | mb_strtolower($name) 59 | ); 60 | } 61 | 62 | public function getClassName(): ClassName 63 | { 64 | return $this->className; 65 | } 66 | 67 | public function getValueObjectClassName(): ClassName 68 | { 69 | return $this->valueObjectClassName; 70 | } 71 | 72 | public function getType(): string 73 | { 74 | return $this->type; 75 | } 76 | 77 | public function getName(): string 78 | { 79 | return $this->name; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Domain/Command/Create/CreateCommandHandler.php: -------------------------------------------------------------------------------- 1 | className = $className; 31 | $this->entityClassName = $entityClassName; 32 | $this->commandClassName = $commandClassName; 33 | $this->repositoryClassName = $repositoryClassName; 34 | } 35 | 36 | public function getClassName(): ClassName 37 | { 38 | return $this->className; 39 | } 40 | 41 | public function getEntityClassName(): ClassName 42 | { 43 | return $this->entityClassName; 44 | } 45 | 46 | public function getCommandClassName(): ClassName 47 | { 48 | return $this->commandClassName; 49 | } 50 | 51 | public function getRepositoryClassName(): ClassName 52 | { 53 | return $this->repositoryClassName; 54 | } 55 | 56 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 57 | { 58 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 59 | 60 | return new self( 61 | new ClassName( 62 | 'Create' . $entityClassName->getRealName() . 'Handler', 63 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 64 | ), 65 | $entityClassName, 66 | new ClassName('Create' . $entityClassName->getRealName(), $entityClassName->getNamespace()), 67 | new ClassName($entityClassName->getRealName() . 'Repository', $entityClassName->getNamespace()) 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Domain/Command/Delete/DeleteCommandHandler.php: -------------------------------------------------------------------------------- 1 | className = $className; 31 | $this->entityClassName = $entityClassName; 32 | $this->commandClassName = $commandClassName; 33 | $this->repositoryClassName = $repositoryClassName; 34 | } 35 | 36 | public function getClassName(): ClassName 37 | { 38 | return $this->className; 39 | } 40 | 41 | public function getEntityClassName(): ClassName 42 | { 43 | return $this->entityClassName; 44 | } 45 | 46 | public function getCommandClassName(): ClassName 47 | { 48 | return $this->commandClassName; 49 | } 50 | 51 | public function getRepositoryClassName(): ClassName 52 | { 53 | return $this->repositoryClassName; 54 | } 55 | 56 | public static function fromDataTransferObject(CRUDCommandDataTransferObject $CRUDCommandDataTransferObject): self 57 | { 58 | $entityClassName = ClassName::fromDataTransferObject($CRUDCommandDataTransferObject->entityClassName); 59 | 60 | return new self( 61 | new ClassName( 62 | 'Delete' . $entityClassName->getRealName() . 'Handler', 63 | PhpNamespace::fromDataTransferObject($CRUDCommandDataTransferObject->commandNamespace) 64 | ), 65 | $entityClassName, 66 | new ClassName('Delete' . $entityClassName->getRealName(), $entityClassName->getNamespace()), 67 | new ClassName($entityClassName->getRealName() . 'Repository', $entityClassName->getNamespace()) 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CLI/Console/Generate/Module/Bootstrap.php: -------------------------------------------------------------------------------- 1 | setName('generate:module:bootstrap') 27 | ->setDescription('Generates the base for a module'); 28 | } 29 | 30 | protected function execute(InputInterface $input, OutputInterface $output) 31 | { 32 | parent::execute($input, $output); 33 | 34 | $info = Info::fromDataTransferObject($this->getFormData(InfoType::class)); 35 | 36 | $this->generateService->generateClasses( 37 | [ 38 | new FrontendConfig($info->getModuleName()), 39 | new BackendConfig($info->getModuleName()), 40 | new ModuleExtension($info->getModuleName()), 41 | new Installer($info->getModuleName()), 42 | ], 43 | $this->getTargetPhpVersion() 44 | ); 45 | $this->generateService->generateFiles( 46 | [ 47 | $info, 48 | new Commands($info->getModuleName()), 49 | new Doctrine($info->getModuleName()), 50 | new Repositories($info->getModuleName()), 51 | new Services($info->getModuleName()), 52 | new Locale($info->getModuleName()), 53 | ], 54 | $this->getTargetPhpVersion() 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/PhpGenerator/ClassName/ClassName.php: -------------------------------------------------------------------------------- 1 | name = ucfirst($name); 21 | $this->namespace = $namespace; 22 | $this->alias = empty($alias) ? null : ucfirst($alias); 23 | } 24 | 25 | public function getRealName(): string 26 | { 27 | return $this->name; 28 | } 29 | 30 | public function getNamespace(): PhpNamespace 31 | { 32 | return $this->namespace; 33 | } 34 | 35 | public function getAlias(): string 36 | { 37 | return (string) $this->alias; 38 | } 39 | 40 | public function getFullyQualifiedName(): string 41 | { 42 | if ($this->namespace->isRoot()) { 43 | return '\\' . $this->name . (($this->alias === null) ? '' : ' as ' . $this->alias); 44 | } 45 | 46 | return '\\' . $this->namespace . '\\' . $this->name; 47 | } 48 | 49 | public function getForUseStatement(): string 50 | { 51 | if ($this->namespace->isRoot()) { 52 | return $this->name . (($this->alias === null) ? '' : ' as ' . $this->alias); 53 | } 54 | 55 | return $this->namespace . '\\' . $this->name . (($this->alias === null) ? '' : ' as ' . $this->alias); 56 | } 57 | 58 | public function getForParameter(): string 59 | { 60 | return lcfirst($this->getName()); 61 | } 62 | 63 | public function getName(): string 64 | { 65 | if ($this->alias === null) { 66 | return $this->name; 67 | } 68 | 69 | return $this->alias; 70 | } 71 | 72 | public function __toString(): string 73 | { 74 | return $this->getName(); 75 | } 76 | 77 | public static function fromDataTransferObject( 78 | ClassNameDataTransferObject $classNameDataTransferObject 79 | ): self { 80 | $namespace = PhpNamespace::fromDataTransferObject($classNameDataTransferObject->namespace); 81 | 82 | return new self( 83 | $classNameDataTransferObject->name, 84 | $namespace, 85 | $classNameDataTransferObject->alias 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/CLI/Console/GenerateCommand.php: -------------------------------------------------------------------------------- 1 | generateService = $generateService; 32 | parent::__construct(); 33 | } 34 | 35 | protected function execute(InputInterface $input, OutputInterface $output) 36 | { 37 | $this->input = $input; 38 | self::$output = $output; 39 | 40 | $this->targetPhpVersion = self::PHP71; 41 | } 42 | 43 | public function setTargetPhpVersion(float $targetPhpVersion): self 44 | { 45 | $this->targetPhpVersion = $targetPhpVersion; 46 | 47 | return $this; 48 | } 49 | 50 | public function getTargetPhpVersion(): float 51 | { 52 | return $this->targetPhpVersion; 53 | } 54 | 55 | public function getFormData(string $className, array $options = [], $data = null) 56 | { 57 | $formHelper = $this->getHelper('form'); 58 | 59 | return $formHelper->interactUsingForm($className, $this->input, self::$output, $options, $data); 60 | } 61 | 62 | /** 63 | * Yes I know it is dirty but it works for now 64 | * 65 | * @return OutputInterface 66 | */ 67 | public static function getOutput() 68 | { 69 | return self::$output; 70 | } 71 | 72 | public function extractModuleName(PhpNamespace $namespace): ?ModuleName 73 | { 74 | $matches = []; 75 | preg_match( 76 | '|^Backend\\\\Modules\\\\(.*?)\\\\|', 77 | $namespace, 78 | $matches 79 | ); 80 | 81 | if (\count($matches) === 2) { 82 | return new ModuleName($matches[1]); 83 | } 84 | 85 | return null; 86 | } 87 | } 88 | --------------------------------------------------------------------------------