From 4b088b959d825397d2a29e2d4d83d4ada1afff1e Mon Sep 17 00:00:00 2001 From: Paul Dragoonis Date: Wed, 24 Feb 2016 20:40:06 +0000 Subject: [PATCH 1/2] Adding optional module:create questions for templating and routing. also cleaning up the source a bit into separate functions --- src/Console/Command/ModuleCreateCommand.php | 239 +++++++++++++------- 1 file changed, 154 insertions(+), 85 deletions(-) diff --git a/src/Console/Command/ModuleCreateCommand.php b/src/Console/Command/ModuleCreateCommand.php index dd42e1d..32237d7 100644 --- a/src/Console/Command/ModuleCreateCommand.php +++ b/src/Console/Command/ModuleCreateCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; /** * Module Command. @@ -37,6 +38,8 @@ class ModuleCreateCommand extends AbstractCommand protected $skeletonModuleDir; protected $modulesDir; + protected $moduleDir; + protected $moduleName; protected $tplEngine; protected $routingEngine; protected $configEnabledTemplatingEngines = []; @@ -49,10 +52,7 @@ class ModuleCreateCommand extends AbstractCommand 'src/Controller', 'tests', 'resources', - 'resources/routes', - 'resources/config', - 'resources/views', - 'resources/views/index', + 'resources/config' ]; /** @@ -63,6 +63,11 @@ class ModuleCreateCommand extends AbstractCommand 'resources/config/config.php', ]; + protected $tplEngineCoreFiles = [ + 'resources/views', + 'resources/views/index' + ]; + /** * @var array */ @@ -86,6 +91,10 @@ class ModuleCreateCommand extends AbstractCommand ], ]; + protected $routingEngineCoreFiles = [ + 'resources/routes' + ]; + protected $routingEngineFilesMap = [ self::ROUTING_ENGINE_SYMFONY => [ 'src/Controller/Index.php', @@ -169,21 +178,25 @@ protected function configure() } /** - * @param InputInterface $input + * @param InputInterface $input * @param OutputInterface $output - * * @throws \Exception + * @return void */ protected function execute(InputInterface $input, OutputInterface $output) { - $moduleName = $input->getArgument('name'); - $moduleDir = $this->modulesDir . DIRECTORY_SEPARATOR . $moduleName; + $this->moduleName = $input->getArgument('name'); + $this->moduleDir = $this->modulesDir . DIRECTORY_SEPARATOR . $this->moduleName; // Acquire Module Information $this->askQuestions($input, $output); - $this->createModuleStructure($moduleDir, $moduleName); + $this->createModuleStructure($this->moduleDir, $this->moduleName); + $output->writeln("Created module successfully"); + $output->writeln("Name: {$this->moduleName}"); + $output->writeln(sprintf("Path: %s", $this->moduleDir)); + // Copy the core files - $this->copyFiles($this->skeletonModuleDir, $moduleDir, $this->coreFiles); + $this->copyFiles($this->skeletonModuleDir, $this->moduleDir, $this->coreFiles); $tokenizedFiles = []; $tokens = []; @@ -191,63 +204,19 @@ protected function execute(InputInterface $input, OutputInterface $output) $tokenizedFiles[] = $coreFile; } - if (!$this->isValidTemplatingEngine($this->tplEngine)) { - throw new \Exception('Invalid templating engine: ' . $this->tplEngine); + if(null !== $this->tplEngine && $this->isValidTemplatingEngine($this->tplEngine)) { + $this->copyTemplatingFiles($this->moduleDir, $this->moduleName, $tokens, $tokenizedFiles); + $output->writeln(sprintf("Templating: %s", $this->tplEngine)); } - // TEMPLATING - - // Copy templating files over - $tplFiles = $this->tplEngineFilesMap[$this->tplEngine]; - $this->copyFiles($this->skeletonModuleDir, $moduleDir, $tplFiles); - - // Setting up templating tokens - foreach ($tplFiles as $tplFile) { - $tokenizedFiles[] = $tplFile; - } - - $tokens['[MODULE_NAME]'] = $moduleName; - $tokens['[TPL_ENGINE_EXT]'] = $this->tplEngine; - - // ROUTING - if (!$this->isValidRoutingEngine($this->routingEngine)) { - throw new \Exception('Invalid routing engine: ' . $this->routingEngine); + if(null !== $this->routingEngine && $this->isValidRoutingEngine($this->routingEngine)) { + $this->copyRoutingFiles($this->moduleDir, $this->moduleName, $tokens, $tokenizedFiles); + $output->writeln(sprintf("Routing: %s", $this->routingEngine)); } - - // Copy routing files over - $routingFiles = $this->routingEngineFilesMap[$this->routingEngine]; - $this->copyFiles($this->skeletonModuleDir, $moduleDir, $routingFiles); - - // Setting up routing tokens - foreach ($routingFiles as $routingFile) { - $tokenizedFiles[] = $routingFile; - } - $routingTokensMap = $this->routingEngineTokenMap[$this->routingEngine]; - foreach ($routingTokensMap as $routingTokenKey => $routingTokenVal) { - $tokens[$routingTokenKey] = $routingTokenVal; - } - - // Replace tokens in all files - $this->replaceTokensInFiles($moduleDir, $tokenizedFiles, $tokens); - - if ($this->routingEngine === self::ROUTING_ENGINE_FASTROUTE) { - rename( - $moduleDir . DIRECTORY_SEPARATOR . $routingFiles[0], - str_replace('IndexInvoke', 'Index', $moduleDir . DIRECTORY_SEPARATOR . $routingFiles[0] - )); - } - - // Success - $output->writeln("Created module successfully"); - $output->writeln("Name: {$moduleName}"); - $output->writeln(sprintf("Routing: %s", $this->routingEngine)); - $output->writeln(sprintf("Templating: %s", $this->tplEngine)); - $output->writeln(sprintf("Path: %s", $moduleDir)); - $output->writeln("This module is not enabled. Enable it in config[modules] key"); - $this->checkTemplatingEngines($input, $output); - $this->checkRouters($input, $output); + $this->checkEnabledTemplatingEngines($input, $output); + $this->checkEnabledRouters($input, $output); } protected function isValidTemplatingEngine($tplEngine) @@ -336,35 +305,21 @@ protected function createModuleStructure($moduleDir, $moduleName) */ protected function askQuestions(InputInterface $input, OutputInterface $output) { + $questionHelper = $this->getHelper('question'); + // Module DIR if ($input->getOption('dir') == null) { - $questionHelper = $this->getHelper('question'); $modulesDirQuestion = new ChoiceQuestion('Where is the modules dir?', [1 => $this->modulesDir], $this->modulesDir); $modulesDirQuestion->setErrorMessage('Modules dir: %s is invalid.'); $this->modulesDir = $questionHelper->ask($input, $output, $modulesDirQuestion); } - // Templating - if ($input->getOption('tpl') == null) { - $questionHelper = $this->getHelper('question'); - $tplQuestion = new ChoiceQuestion('Choose your templating engine [php]', [1 => 'php', 2 => 'twig', 3 => 'smarty', 4 => 'plates', 5 => 'latte'], 'php'); - $tplQuestion->setErrorMessage('Templating engine %s is invalid.'); - $this->tplEngine = $questionHelper->ask($input, $output, $tplQuestion); + if($this->askForTemplating($input, $output)) { + $this->chooseTemplatingEngine($input, $output); } - // Routing - if ($input->getOption('routing') == null) { - $questionHelper = $this->getHelper('question'); - $routingQuestion = new ChoiceQuestion('Choose your routing engine [symfony]', - [ - 1 => self::ROUTING_ENGINE_SYMFONY, - 2 => self::ROUTING_ENGINE_AURA, - 3 => self::ROUTING_ENGINE_LARAVEL, - 4 => self::ROUTING_ENGINE_FASTROUTE, - ], - 'symfony' - ); - $tplQuestion->setErrorMessage('Routing engine %s is invalid.'); - $this->routingEngine = $questionHelper->ask($input, $output, $routingQuestion); + + if($this->askForRouting($input, $output)) { + $this->chooseRouter($input, $output); } } @@ -372,7 +327,7 @@ protected function askQuestions(InputInterface $input, OutputInterface $output) * @param InputInterface $input * @param OutputInterface $output */ - private function checkRouters(InputInterface $input, OutputInterface $output) + private function checkEnabledRouters(InputInterface $input, OutputInterface $output) { // Aura Check if ($this->routingEngine == self::ROUTING_ENGINE_AURA && !class_exists('\Aura\Router\Router')) { @@ -393,7 +348,7 @@ private function checkRouters(InputInterface $input, OutputInterface $output) * @param InputInterface $input * @param OutputInterface $output */ - private function checkTemplatingEngines(InputInterface $input, OutputInterface $output) + private function checkEnabledTemplatingEngines(InputInterface $input, OutputInterface $output) { // PHP Templating Engine checks if ($this->tplEngine == self::TPL_ENGINE_PHP) { @@ -442,4 +397,118 @@ private function checkTemplatingEngines(InputInterface $input, OutputInterface $ } } } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return boolean + */ + private function askForTemplating(InputInterface $input, OutputInterface $output) + { + $questionHelper = $this->getHelper('question'); + $question = new ConfirmationQuestion("Do you need templates? (yes/no):\n", false); + + return $questionHelper->ask($input, $output, $question); + } + + private function askForRouting(InputInterface $input, OutputInterface $output) + { + $questionHelper = $this->getHelper('question'); + $question = new ConfirmationQuestion("Do you need routing? (yes/no):\n", false); + + return $questionHelper->ask($input, $output, $question); + } + + private function chooseTemplatingEngine($input, $output) + { + $tplQuestion = new ChoiceQuestion('Choose your templating engine [php]', + [ + 1 => 'php', + 2 => 'twig', + 3 => 'smarty', + 4 => 'plates', + 5 => 'latte', + 99 => 'skip' + ] + ); + $tplQuestion->setErrorMessage('Templating engine %s is invalid.'); + if(99 !== ($tplEngine = $this->getHelper('question')->ask($input, $output, $tplQuestion))) { + $this->tplEngine = $tplEngine; + } + } + + private function chooseRouter(InputInterface $input, OutputInterface $output) + { + $routingQuestion = new ChoiceQuestion('Choose your routing engine:', + [ + 1 => self::ROUTING_ENGINE_SYMFONY, + 2 => self::ROUTING_ENGINE_AURA, + 3 => self::ROUTING_ENGINE_LARAVEL, + 4 => self::ROUTING_ENGINE_FASTROUTE, + 99 => 'skip' + ] + ); + + // @todo - test question when you don't choose any option, or an invalid one (like -1) + $routingQuestion->setErrorMessage('Routing engine %s is invalid.'); + if(99 !== ($routingEngine = $this->getHelper('question')->ask($input, $output, $routingQuestion))) { + $this->routingEngine = $routingEngine; + } + } + + private function copyTemplatingFiles($moduleDir, $moduleName, $tokens, $tokenizedFiles) + { + $tplFiles = $this->tplEngineFilesMap[$this->tplEngine]; + + // Copy core templating files over + foreach($this->tplEngineCoreFiles as $coreFile) { + $tplFiles[] = $coreFile; + } + + // Copy templating files over relevant to the specified engine + $this->copyFiles($this->skeletonModuleDir, $moduleDir, $tplFiles); + + // Setting up templating tokens + foreach ($tplFiles as $tplFile) { + $tokenizedFiles[] = $tplFile; + } + + $tokens['[MODULE_NAME]'] = $moduleName; + $tokens['[TPL_ENGINE_EXT]'] = $this->tplEngine; + } + + private function copyRoutingFiles($moduleDir, $moduleDir, $tokens, $tokenizedFiles) + { + // Copy routing files over + $routingFiles = $this->routingEngineFilesMap[$this->routingEngine]; + + // Copy core templating files over + foreach($this->routingEngineCoreFiles as $coreFile) { + $routingFiles[] = $coreFile; + } + + $this->copyFiles($this->skeletonModuleDir, $moduleDir, $routingFiles); + + // Setting up routing tokens + foreach ($routingFiles as $routingFile) { + $tokenizedFiles[] = $routingFile; + } + + $routingTokensMap = $this->routingEngineTokenMap[$this->routingEngine]; + foreach ($routingTokensMap as $routingTokenKey => $routingTokenVal) { + $tokens[$routingTokenKey] = $routingTokenVal; + } + + // Replace tokens in all files + $this->replaceTokensInFiles($moduleDir, $tokenizedFiles, $tokens); + + // Prepare the fastroute route file + if ($this->routingEngine === self::ROUTING_ENGINE_FASTROUTE) { + rename( + $moduleDir . DIRECTORY_SEPARATOR . $routingFiles[0], + str_replace('IndexInvoke', 'Index', $moduleDir . DIRECTORY_SEPARATOR . $routingFiles[0] + )); + } + } + } From 178c1ffffaa2ad93b00ee49f2db27ead9d77984b Mon Sep 17 00:00:00 2001 From: Paul Dragoonis Date: Fri, 26 Feb 2016 13:06:53 +0000 Subject: [PATCH 2/2] Optional routing work. Adding in traits for getRoutes() injection into a module --- src/Console/Command/ModuleCreateCommand.php | 127 +++++++++++++++----- src/Module/AbstractModule.php | 15 +-- src/Module/Routing/SymfonyTrait.php | 23 ++++ 3 files changed, 119 insertions(+), 46 deletions(-) create mode 100644 src/Module/Routing/SymfonyTrait.php diff --git a/src/Console/Command/ModuleCreateCommand.php b/src/Console/Command/ModuleCreateCommand.php index 32237d7..036c1cf 100644 --- a/src/Console/Command/ModuleCreateCommand.php +++ b/src/Console/Command/ModuleCreateCommand.php @@ -35,6 +35,7 @@ class ModuleCreateCommand extends AbstractCommand const ROUTING_ENGINE_AURA = 'aura'; const ROUTING_ENGINE_LARAVEL = 'laravel'; const ROUTING_ENGINE_FASTROUTE = 'fastroute'; + const ROUTING_ENGINE_NULL = 'NullRouter'; protected $skeletonModuleDir; protected $modulesDir; @@ -68,6 +69,10 @@ class ModuleCreateCommand extends AbstractCommand 'resources/views/index' ]; + protected $routingEngineCoreFiles = [ + 'resources/routes' + ]; + /** * @var array */ @@ -91,15 +96,11 @@ class ModuleCreateCommand extends AbstractCommand ], ]; - protected $routingEngineCoreFiles = [ - 'resources/routes' - ]; - protected $routingEngineFilesMap = [ self::ROUTING_ENGINE_SYMFONY => [ 'src/Controller/Index.php', 'src/Controller/Shared.php', - 'resources/routes/symfony.yml', + 'resources/routes/symfony.yml' ], self::ROUTING_ENGINE_AURA => [ 'src/Controller/Index.php', @@ -119,11 +120,6 @@ class ModuleCreateCommand extends AbstractCommand ]; protected $routingEngineTokenMap = [ - self::ROUTING_ENGINE_SYMFONY => [ - '[ROUTING_LOAD_METHOD]' => 'loadSymfonyRoutes', - '[ROUTING_DEF_FILE]' => 'symfony.yml', - '[ROUTING_GETROUTES_RETVAL]' => '\Symfony\Component\Routing\RouteCollection', - ], self::ROUTING_ENGINE_AURA => [ '[ROUTING_LOAD_METHOD]' => 'loadAuraRoutes', '[ROUTING_DEF_FILE]' => 'aura.php', @@ -198,21 +194,26 @@ protected function execute(InputInterface $input, OutputInterface $output) // Copy the core files $this->copyFiles($this->skeletonModuleDir, $this->moduleDir, $this->coreFiles); - $tokenizedFiles = []; + $tokenizedFiles = $this->getTokenizedCoreFiles(); $tokens = []; - foreach ($this->coreFiles as $coreFile) { - $tokenizedFiles[] = $coreFile; - } + + $tokens['[MODULE_NAME]'] = $this->moduleName; if(null !== $this->tplEngine && $this->isValidTemplatingEngine($this->tplEngine)) { - $this->copyTemplatingFiles($this->moduleDir, $this->moduleName, $tokens, $tokenizedFiles); + $this->processTemplatingFiles(); $output->writeln(sprintf("Templating: %s", $this->tplEngine)); } - if(null !== $this->routingEngine && $this->isValidRoutingEngine($this->routingEngine)) { - $this->copyRoutingFiles($this->moduleDir, $this->moduleName, $tokens, $tokenizedFiles); - $output->writeln(sprintf("Routing: %s", $this->routingEngine)); + if($this->isValidRoutingEngine($this->routingEngine)) { + $this->processRoutingFiles($tokenizedFiles, $tokens); + $output->writeln(sprintf("Router: %s", $this->routingEngine)); + } else { + $tokens['ROUTING_TRAIT'] = ''; } + + // replace tokens from specified tokenizable files + $this->replaceTokensInFiles($this->moduleDir, $tokenizedFiles, $tokens); + $output->writeln("This module is not enabled. Enable it in config[modules] key"); $this->checkEnabledTemplatingEngines($input, $output); @@ -237,6 +238,7 @@ protected function isValidRoutingEngine($routingEngine) self::ROUTING_ENGINE_AURA, self::ROUTING_ENGINE_LARAVEL, self::ROUTING_ENGINE_FASTROUTE, + self::ROUTING_ENGINE_NULL, ]); } @@ -451,14 +453,23 @@ private function chooseRouter(InputInterface $input, OutputInterface $output) // @todo - test question when you don't choose any option, or an invalid one (like -1) $routingQuestion->setErrorMessage('Routing engine %s is invalid.'); - if(99 !== ($routingEngine = $this->getHelper('question')->ask($input, $output, $routingQuestion))) { - $this->routingEngine = $routingEngine; + $chosenRouter = $this->getHelper('question')->ask($input, $output, $routingQuestion); + if(99 == $chosenRouter) { + $chosenRouter = 'NullRouter'; + } + $this->routingEngine = $chosenRouter; + } + + private function getTemplatingFilesFromEngine($tplEngine) + { + if(!isset($this->tplEngineFilesMap[$tplEngine])) { + throw new \InvalidArgumentException('Invalid templating engine specified for map files: ' . $tplEngine); } } - private function copyTemplatingFiles($moduleDir, $moduleName, $tokens, $tokenizedFiles) + private function processTemplatingFiles() { - $tplFiles = $this->tplEngineFilesMap[$this->tplEngine]; + $tplFiles = $this->getTemplatingFilesFromEngine($this->tplEngine); // Copy core templating files over foreach($this->tplEngineCoreFiles as $coreFile) { @@ -466,41 +477,62 @@ private function copyTemplatingFiles($moduleDir, $moduleName, $tokens, $tokenize } // Copy templating files over relevant to the specified engine - $this->copyFiles($this->skeletonModuleDir, $moduleDir, $tplFiles); + $this->copyFiles($this->skeletonModuleDir, $this->moduleDir, $tplFiles); // Setting up templating tokens + $tokenizedFiles = []; foreach ($tplFiles as $tplFile) { $tokenizedFiles[] = $tplFile; } - $tokens['[MODULE_NAME]'] = $moduleName; $tokens['[TPL_ENGINE_EXT]'] = $this->tplEngine; + + + $this->replaceTokensInFiles($this->moduleDir, $tokenizedFiles, $tokens); + + } - private function copyRoutingFiles($moduleDir, $moduleDir, $tokens, $tokenizedFiles) + /** + * @throws \Exception + */ + private function processRoutingFiles($tokenizedFiles, $tokens) { + + if(!isset($this->routingEngineFilesMap[$this->routingEngine])) { + throw new \Exception('Routing engine not found in routing files map: ' . $this->routingEngine); + } + // Copy routing files over $routingFiles = $this->routingEngineFilesMap[$this->routingEngine]; - // Copy core templating files over - foreach($this->routingEngineCoreFiles as $coreFile) { - $routingFiles[] = $coreFile; + // If a valid routing engine and that's not null router + if($this->routingEngine !== 99) { + // Create core routing directories + foreach($this->routingEngineCoreFiles as $coreFile) { + @mkdir($this->moduleDir . DIRECTORY_SEPARATOR . $coreFile); + } } - $this->copyFiles($this->skeletonModuleDir, $moduleDir, $routingFiles); - // Setting up routing tokens +//var_dump(__METHOD__, __LINE__, $routingFiles); exit; + $this->copyFiles($this->skeletonModuleDir, $this->moduleDir, $routingFiles); + + // Setting up routing tokenizable files foreach ($routingFiles as $routingFile) { $tokenizedFiles[] = $routingFile; } - $routingTokensMap = $this->routingEngineTokenMap[$this->routingEngine]; + // Get all the tokens for this routing engine and the values the map to. + $routingTokensMap = $this->getRoutingTokenMap($this->routingEngine); foreach ($routingTokensMap as $routingTokenKey => $routingTokenVal) { $tokens[$routingTokenKey] = $routingTokenVal; } // Replace tokens in all files - $this->replaceTokensInFiles($moduleDir, $tokenizedFiles, $tokens); + $this->replaceTokensInFiles($this->moduleDir, $tokenizedFiles, $tokens); + + // Replace the ROUTING placeholder with this heredoc // Prepare the fastroute route file if ($this->routingEngine === self::ROUTING_ENGINE_FASTROUTE) { @@ -511,4 +543,35 @@ private function copyRoutingFiles($moduleDir, $moduleDir, $tokens, $tokenizedFil } } + protected function getTokenizedCoreFiles() + { + $files = []; + foreach ($this->coreFiles as $coreFile) { + $files[] = $coreFile; + } + return $files; + } + + private function getRoutingTokenMap($routingEngine) { + +// if(!isset($this->routingEngineTokenMap[$routingEngine])) { +// throw new \Exception('No routing engine tokenizable files found for routing engine: ' . $this->routingEngine); +// } + + $tokenMap = []; + + switch($routingEngine) { + case self::ROUTING_ENGINE_SYMFONY: + $tokenMap['[ROUTING_TRAIT]'] = 'use \PPI\Framework\Module\Routing\SymfonyTrait;'; + break; + + default: + throw new \Exception('Unimplemented routing engine: ' . $routingEngine); + break; + } + + return $tokenMap; + } + + } diff --git a/src/Module/AbstractModule.php b/src/Module/AbstractModule.php index b1aafa4..432a5c7 100644 --- a/src/Module/AbstractModule.php +++ b/src/Module/AbstractModule.php @@ -347,18 +347,6 @@ public function getConfig() return array(); } - /** - * Returns the default location of where Command classes are registered. - * Override this in your child module if it differs from this default convention. - * - * @return string - */ - public function getCommandsPath() - { - return sprintf("%s/src/Command", $this->getPath()); - } - - /** * Finds and registers Commands. * @@ -371,8 +359,7 @@ public function getCommandsPath() */ public function registerCommands(Application $application) { - - if (!is_dir($dir = $this->getCommandsPath())) { + if (!is_dir($dir = $this->getPath() . '/Command')) { return; } diff --git a/src/Module/Routing/SymfonyTrait.php b/src/Module/Routing/SymfonyTrait.php new file mode 100644 index 0000000..189739d --- /dev/null +++ b/src/Module/Routing/SymfonyTrait.php @@ -0,0 +1,23 @@ +loadSymfonyRoutes($this->getRoutingFilePath()); + } + + protected function getRoutingFilePath() + { + return $this->getPath() . '/resources/routes/symfony.yml'; + } + +} \ No newline at end of file