/** * {@inheritDoc} * Add the new bundle to the BundleBundle loader infrastructure instead of main kernel * * @param QuestionHelper $questionHelper dialog * @param InputInterface $input input * @param OutputInterface $output output * @param KernelInterface $kernel kernel * @param string $namespace namespace * @param string $bundle bundle * * @return string[] */ protected function updateKernel(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, KernelInterface $kernel, $namespace, $bundle) { // skip if kernel manipulation disabled by options (defaults to true) $doUpdate = $input->getOption('doUpdateKernel'); if ($doUpdate == 'false') { return; } $auto = true; if ($input->isInteractive()) { $auto = $questionHelper->doAsk($output, $questionHelper->getQuestion('Confirm automatic update of your core bundle', 'yes', '?')); } $output->write('Enabling the bundle inside the core bundle: '); $coreBundle = $kernel->getBundle($input->getOption('loaderBundleName')); if (!is_a($coreBundle, '\\Graviton\\BundleBundle\\GravitonBundleInterface')) { throw new \LogicException('GravitonCoreBundle does not implement GravitonBundleInterface'); } $manip = new BundleBundleManipulator($coreBundle); try { $ret = $auto ? $manip->addBundle($namespace . '\\' . $bundle) : false; if (!$ret) { $reflected = new \ReflectionObject($kernel); return array(sprintf('- Edit <comment>%s</comment>', $reflected->getFilename()), ' and add the following bundle in the <comment>GravitonCoreBundle::getBundles()</comment> method:', '', sprintf(' <comment>new %s(),</comment>', $namespace . '\\' . $bundle), ''); } } catch (\RuntimeException $e) { return array(sprintf('Bundle <comment>%s</comment> is already defined in <comment>%s)</comment>.', $namespace . '\\' . $bundle, 'sGravitonCoreBundle::getBundles()'), ''); } }
private function loopBundle(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output) { $bundles = ['admin' => ['kernel' => [['bundle' => 'SKCMSAdminBundle', 'namespace' => 'SKCMS\\AdminBundle'], ['bundle' => 'IvoryCKEditorBundle', 'namespace' => 'Ivory\\CKEditorBundle'], ['bundle' => 'FMElfinderBundle', 'namespace' => 'FM\\ElfinderBundle'], ['bundle' => 'StofDoctrineExtensionsBundle', 'namespace' => 'Stof\\DoctrineExtensionsBundle']], 'config' => ['loadSkCMSAdmin', 'loadCKEditor', 'loadDoctrineFunctions'], 'route' => ['routeAdmin']], 'user' => ['kernel' => [['bundle' => 'SKCMSUserBundle', 'namespace' => 'SKCMS\\UserBundle'], ['bundle' => 'FOSUserBundle', 'namespace' => 'FOS\\UserBundle']], 'config' => ['loadFosUser', 'setSecurity'], 'route' => ['routeUser']], 'contact' => ['kernel' => [['bundle' => 'SKCMSContactBundle', 'namespace' => 'SKCMS\\ContactBundle']], 'config' => ['loadSKContact'], 'route' => ['routeContact']], 'tracking' => ['kernel' => [['bundle' => 'SKCMSTrackingBundle', 'namespace' => 'SKCMS\\TrackingBundle']], 'route' => ['routeTracking']], 'shop' => ['kernel' => [['bundle' => 'SKCMSShopBundle', 'namespace' => 'SKCMS\\ShopBundle']], 'route' => ['routeShop']], 'front' => ['kernel' => [['bundle' => 'SKCMSFrontBundle', 'namespace' => 'SKCMS\\FrontBundle']], 'route' => ['routeFront']]]; foreach ($bundles as $bundleName => $bundle) { if ($input->isInteractive()) { $question = new ConfirmationQuestion($questionHelper->getQuestion('Install ' . $bundleName . ' (kernel + config)', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $question); $this->module_installed = $auto; } if ($auto) { foreach ($bundle['kernel'] as $bundleKernel) { $kernelUpdate = $this->updateKernel($this->getContainer()->get('kernel'), $bundleKernel['namespace'], $bundleKernel['bundle']); } if (array_key_exists('config', $bundle) && is_array($bundle['config'])) { foreach ($bundle['config'] as $configMethod) { call_user_func([$this, $configMethod]); } } if (array_key_exists('route', $bundle) && is_array($bundle['route'])) { foreach ($bundle['route'] as $routeMethod) { call_user_func([$this, $routeMethod]); } } } } }
/** * Asks for the prefix and sets it on the InputInterface as the 'prefix' option, if this option is not set yet. * Will set the default to a snake_cased namespace when the namespace has been set on the InputInterface. * * @param array $text What you want printed before the prefix is asked. If null is provided it'll write a default text. * @param string $namespace An optional namespace. If this is set it'll create the default based on this prefix. * If it's not provided it'll check if the InputInterface already has the namespace option. * * @return string The prefix. But it's also been set on the InputInterface. */ public function askForPrefix(array $text = null, $namespace = null) { $prefix = $this->input->hasOption('prefix') ? $this->input->getOption('prefix') : null; if (is_null($text)) { $text = array('', 'You can add a prefix to the table names of the generated entities for example: <comment>projectname_bundlename_</comment>', 'Enter an underscore \'_\' if you don\'t want a prefix.', ''); } while (is_null($prefix)) { if (count($text) > 0) { $this->output->writeln($text); } if (is_null($namespace) || empty($namespace)) { $namespace = $this->input->hasOption('namespace') ? $this->input->getOption('namespace') : null; } else { $namespace = $this->fixNamespace($namespace); } $defaultPrefix = GeneratorUtils::cleanPrefix($this->convertNamespaceToSnakeCase($namespace)); $question = new Question($this->questionHelper->getQuestion('Tablename prefix', $defaultPrefix), $defaultPrefix); $prefix = $this->questionHelper->ask($this->input, $this->output, $question); $prefix = GeneratorUtils::cleanPrefix($prefix); if ($this->input->hasOption('prefix')) { $this->input->setOption('prefix', $prefix); } if ($prefix == '') { break; } if (!preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $prefix)) { $this->output->writeln(sprintf('<bg=red> "%s" contains invalid characters</>', $prefix)); $prefix = $text = null; continue; } } return $prefix; }
public function addActions(InputInterface $input, OutputInterface $output, \Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper $questionHelper) { $output->writeln(array('', 'Instead of starting with a blank controller, you can add some actions now. An action', 'is a PHP function or method that executes, for example, when a given route is matched.', 'Actions should be suffixed by <comment>Action</comment>.', '')); $templateNameValidator = function ($name) { if ('default' == $name) { return $name; } if (2 != substr_count($name, ':')) { throw new \InvalidArgumentException(sprintf('Template name "%s" does not have 2 colons', $name)); } return $name; }; $actions = $this->parseActions($input->getOption('actions')); while (true) { // name $output->writeln(''); $actionName = $questionHelper->askAndValidate($output, $questionHelper->getQuestion('New action name (press <return> to stop adding actions)', null), function ($name) use($actions) { if (null == $name) { return $name; } if (isset($actions[$name])) { throw new \InvalidArgumentException(sprintf('Action "%s" is already defined', $name)); } return $name; }); if (!$actionName) { break; } $usualActions = array('home', 'add', 'see', 'modify', 'delete'); if (in_array($actionName, $usualActions)) { $route = '/' . $actionName; $placeholders = $this->getPlaceholdersFromRoute($route); $template = $input->getOption('controller') . ':' . $actionName . '.html.' . $input->getOption('template-format'); } else { // route $route = $questionHelper->ask($output, $questionHelper->getQuestion('Action route', '/' . $actionName), '/' . $actionName); $placeholders = $this->getPlaceholdersFromRoute($route); // template $defaultTemplate = $input->getOption('controller') . ':' . $actionName . '.html.' . $input->getOption('template-format'); $template = $questionHelper->askAndValidate($output, $questionHelper->getQuestion('Templatename (optional)', $defaultTemplate), $templateNameValidator, false, 'default'); } // adding action $actions[$actionName] = array('name' => $actionName, 'route' => $route, 'placeholders' => $placeholders, 'template' => $template); } return $actions; }
/** * Interactively ask user to add field to his new Entity. * * @param InputInterface $input * @param OutputInterface $output * @param QuestionHelper $questionHelper * * @return $fields */ private function addFields(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper) { $fields = $this->parseFields($input->getOption('fields')); $output->writeln(['', 'Instead of starting with a blank entity, you can add some fields now.', 'Note that the primary key will be added automatically (named <comment>id</comment>).', '']); $output->write('<info>Available types:</info> '); $types = array_keys(Type::getTypesMap()); $count = 20; foreach ($types as $i => $type) { if ($count > 50) { $count = 0; $output->writeln(''); } $count += strlen($type); $output->write(sprintf('<comment>%s</comment>', $type)); if (count($types) != $i + 1) { $output->write(', '); } else { $output->write('.'); } } $output->writeln(''); $fieldValidator = function ($type) use($types) { if (!in_array($type, $types)) { throw new \InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } return $type; }; $lengthValidator = function ($length) { if (!$length) { return $length; } $result = filter_var($length, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); if (false === $result) { throw new \InvalidArgumentException(sprintf('Invalid length "%s".', $length)); } return $length; }; while (true) { $output->writeln(''); $generator = $this->getEntityGenerator(); $question = new Question($questionHelper->getQuestion('New field name (press <return> to stop adding fields)', null)); $question->setValidator(function ($name) use($fields, $generator) { if (isset($fields[$name]) || 'id' == $name) { throw new \InvalidArgumentException(sprintf('Field "%s" is already defined.', $name)); } // check reserved words by database if ($generator->isReservedKeyword($name)) { throw new \InvalidArgumentException(sprintf('Name "%s" is a reserved word.', $name)); } // check reserved words by victoire if ($this->isReservedKeyword($name)) { throw new \InvalidArgumentException(sprintf('Name "%s" is a Victoire reserved word.', $name)); } return $name; }); $columnName = $questionHelper->ask($input, $output, $question); if (!$columnName) { break; } $defaultType = 'string'; // try to guess the type by the column name prefix/suffix if (substr($columnName, -3) == '_at') { $defaultType = 'datetime'; } elseif (substr($columnName, -3) == '_id') { $defaultType = 'integer'; } elseif (substr($columnName, 0, 3) == 'is_') { $defaultType = 'boolean'; } elseif (substr($columnName, 0, 4) == 'has_') { $defaultType = 'boolean'; } $question = new Question($questionHelper->getQuestion('Field type', $defaultType), $defaultType); $question->setValidator($fieldValidator); $question->setAutocompleterValues($types); $type = $questionHelper->ask($input, $output, $question); $data = ['columnName' => $columnName, 'fieldName' => lcfirst(Container::camelize($columnName)), 'type' => $type]; if ($type == 'string') { $question = new Question($questionHelper->getQuestion('Field length', 255), 255); $question->setValidator($lengthValidator); $data['length'] = $questionHelper->ask($input, $output, $question); } $fields[$columnName] = $data; } return $fields; }
/** * @param QuestionHelper $questionHelper * @param InputInterface $input * @param OutputInterface $output * @param BundleInterface $bundle * @param $entity * @param $prefix * @return array */ protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, BundleInterface $bundle, $format, $entity, $prefix) { $auto = true; if ($input->isInteractive()) { $question = new ConfirmationQuestion($questionHelper->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $question); } $output->write('Importing the REST api routes: '); $this->getContainer()->get('filesystem')->mkdir($bundle->getPath() . '/Resources/config/'); $routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir') . '/config/routing.yml'); try { $ret = $auto ? $routing->addResource($bundle->getName(), '/' . $prefix, $entity) : false; } catch (\RuntimeException $exc) { $ret = false; } if (!$ret) { $help = sprintf(" <comment>resource: \"@%s/Controller/%sRESTController.php\"</comment>\n", $bundle->getName(), $entity); $help .= sprintf(" <comment>type: %s</comment>\n", 'rest'); $help .= sprintf(" <comment>prefix: /%s</comment>\n", $prefix); return array('- Import this resource into the Apps routing file', sprintf(' (%s).', $this->getContainer()->getParameter('kernel.root_dir') . '/config/routing.yml'), '', sprintf(' <comment>%s:</comment>', substr($bundle->getName(), 0, -6) . '_' . $entity . ('' !== $prefix ? '_' . str_replace('/', '_', $prefix) : '')), $help, ''); } }
protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, BundleInterface $bundle, $format, $entity, $prefix) { $auto = true; if ($input->isInteractive()) { $question = new ConfirmationQuestion($questionHelper->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $question); } $output->write('Importing the CRUD routes: '); $this->getContainer()->get('filesystem')->mkdir($bundle->getPath() . '/Resources/config/'); // first, import the routing file from the bundle's main routing.yml file $routing = new RoutingManipulator($bundle->getPath() . '/Resources/config/routing.yml'); try { $ret = $auto ? $routing->addResource($bundle->getName(), $format, '/' . $prefix, 'routing/' . strtolower(str_replace('\\', '_', $entity))) : false; } catch (\RuntimeException $exc) { $ret = false; } if (!$ret) { $help = sprintf(" <comment>resource: \"@%s/Resources/config/routing/%s.%s\"</comment>\n", $bundle->getName(), strtolower(str_replace('\\', '_', $entity)), $format); $help .= sprintf(" <comment>prefix: /%s</comment>\n", $prefix); return array('- Import the bundle\'s routing resource in the bundle routing file', sprintf(' (%s).', $bundle->getPath() . '/Resources/config/routing.yml'), '', sprintf(' <comment>%s:</comment>', $routing->getImportedResourceYamlKey($bundle->getName(), $prefix)), $help, ''); } // second, import the bundle's routing.yml file from the application's routing.yml file $routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir') . '/config/routing.yml'); try { $ret = $auto ? $routing->addResource($bundle->getName(), 'yml') : false; } catch (\RuntimeException $e) { // the bundle is already imported form app's routing.yml file $errorMessage = sprintf("\n\n[ERROR] The bundle's \"Resources/config/routing.yml\" file cannot be imported\n" . "from \"app/config/routing.yml\" because the \"%s\" bundle is\n" . "already imported. Make sure you are not using two different\n" . "configuration/routing formats in the same bundle because it won't work.\n", $bundle->getName()); $output->write($errorMessage); $ret = true; } catch (\Exception $e) { $ret = false; } if (!$ret) { return array('- Import the bundle\'s routing.yml file in the application routing.yml file', sprintf('# app/config/routing.yml'), sprintf('%s:', $bundle->getName()), sprintf(' <comment>resource: "@%s/Resources/config/routing.yml"</comment>', $bundle->getName()), '', '# ...', ''); } }
protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, $bundle, $format) { $auto = true; if ($input->isInteractive()) { $question = new ConfirmationQuestion($questionHelper->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $question); } $output->write('Importing the bundle routing resource: '); $routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir') . '/config/routing.yml'); try { $ret = $auto ? $routing->addResource($bundle, $format) : true; if (!$ret) { if ('annotation' === $format) { $help = sprintf(" <comment>resource: \"@%s/Controller/\"</comment>\n <comment>type: annotation</comment>\n", $bundle); } else { $help = sprintf(" <comment>resource: \"@%s/Resources/config/routing.%s\"</comment>\n", $bundle, $format); } $help .= " <comment>prefix: /</comment>\n"; return array('- Import the bundle\'s routing resource in the app main routing file:', '', sprintf(' <comment>%s:</comment>', $bundle), $help, ''); } } catch (\RuntimeException $e) { return array(sprintf('Bundle <comment>%s</comment> is already imported.', $bundle), ''); } }
/** * @param QuestionHelper $questionHelper The question helper * @param InputInterface $input The command input * @param OutputInterface $output The command output * @param Bundle $bundle The bundle * @param string $entityClass The classname of the entity * * @return void */ protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, Bundle $bundle, $entityClass) { $auto = true; $multilang = false; if ($input->isInteractive()) { $confirmationQuestion = new ConfirmationQuestion($questionHelper->getQuestion('Is it a multilanguage site', 'yes', '?'), true); $multilang = $questionHelper->ask($input, $output, $confirmationQuestion); $confirmationQuestion = new ConfirmationQuestion($questionHelper->getQuestion('Do you want to update the routing automatically', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $confirmationQuestion); } $prefix = $multilang ? '/{_locale}' : ''; $code = sprintf("%s:\n", strtolower($bundle->getName()) . '_' . strtolower($entityClass) . '_admin_list'); $code .= sprintf(" resource: '@%s/Controller/%sAdminListController.php'\n", $bundle->getName(), $entityClass, "'"); $code .= " type: annotation\n"; $code .= sprintf(" prefix: %s/admin/%s/\n", $prefix, strtolower($entityClass)); if ($multilang) { $code .= " requirements:\n"; $code .= " _locale: %requiredlocales%\n"; } if ($auto) { $file = $bundle->getPath() . '/Resources/config/routing.yml'; $content = ''; if (file_exists($file)) { $content = file_get_contents($file); } elseif (!is_dir($dir = dirname($file))) { mkdir($dir, 0777, true); } $content .= "\n"; $content .= $code; if (false === file_put_contents($file, $content)) { $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock("Failed adding the content automatically", 'error')); } else { return; } } $output->writeln('Add the following to your routing.yml'); $output->writeln('/*******************************/'); $output->write($code); $output->writeln('/*******************************/'); }
/** * @param InputInterface $input * @param OutputInterface $output * @param QuestionHelper $dialog * @param array $fields * * @return string */ private function askForFieldName(InputInterface $input, OutputInterface $output, QuestionHelper $dialog, $fields) { $question = new Question($dialog->getQuestion('New field name (press <return> to stop adding fields)', null)); $question->setValidator(function ($name) use($fields) { if (isset($fields[$name]) || 'id' == $name) { throw new \InvalidArgumentException(sprintf('Field "%s" is already defined.', $name)); } return $name; }); return $dialog->ask($input, $output, $question); }
/** * @param InputInterface $input * @param OutputInterface $output * @param QuestionHelper $dialog * @param $document */ private function askForRoutePrefix(InputInterface $input, OutputInterface $output, QuestionHelper $dialog, $document) { $prefix = $this->getRoutePrefix($input, $document); $output->writeln(array('', 'Determine the routes prefix (all the routes will be "mounted" under this', 'prefix: /prefix/, /prefix/new, ...).', '')); $question = new Question($dialog->getQuestion('Routes prefix', '/' . $prefix), '/' . $prefix); $prefix = $dialog->ask($input, $output, $question, '/' . $prefix); $input->setOption('route-prefix', $prefix); }
protected function getHelperSet($input) { $question = new QuestionHelper(); $question->setInputStream($this->getInputStream($input)); return new HelperSet(array(new FormatterHelper(), $question)); }
public function addActions(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper) { $output->writeln(array('', 'Instead of starting with a blank controller, you can add some actions now. An action', 'is a PHP function or method that executes, for example, when a given route is matched.', 'Actions should be suffixed by <comment>Action</comment>.', '')); $templateNameValidator = function ($name) { if ('default' == $name) { return $name; } if (2 != substr_count($name, ':')) { throw new \InvalidArgumentException(sprintf('Template name "%s" does not have 2 colons', $name)); } return $name; }; $actions = $this->parseActions($input->getOption('actions')); while (true) { // name $output->writeln(''); $question = new Question($questionHelper->getQuestion('New action name (press <return> to stop adding actions)', null), null); $question->setValidator(function ($name) use($actions) { if (null == $name) { return $name; } if (isset($actions[$name])) { throw new \InvalidArgumentException(sprintf('Action "%s" is already defined', $name)); } if ('Action' != substr($name, -6)) { throw new \InvalidArgumentException(sprintf('Name "%s" is not suffixed by Action', $name)); } return $name; }); $actionName = $questionHelper->ask($input, $output, $question); if (!$actionName) { break; } // route $question = new Question($questionHelper->getQuestion('Action route', '/' . substr($actionName, 0, -6)), '/' . substr($actionName, 0, -6)); $route = $questionHelper->ask($input, $output, $question); $placeholders = $this->getPlaceholdersFromRoute($route); // template $defaultTemplate = $input->getOption('controller') . ':' . strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr(substr($actionName, 0, -6), '_', '.'))) . '.html.' . $input->getOption('template-format'); $question = new Question($questionHelper->getQuestion('Template name (optional)', $defaultTemplate), $defaultTemplate); $template = $questionHelper->ask($input, $output, $question); // adding action $actions[$actionName] = array('name' => $actionName, 'route' => $route, 'placeholders' => $placeholders, 'template' => $template); } return $actions; }
public function ask($question, $default = null, array $autoComplete = null) { $askQuestion = new Question($this->questionHelper->getQuestion($question, $default), $default); $askQuestion->setAutocompleterValues($autoComplete); return $this->getQuestionHelper()->ask($this->input, $this->output, $askQuestion); }
public function addModules(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper, $moduleType, $vendorName) { $modules = $this->parseModules($input->getOption('modules'), $moduleType); if (is_null($input->getOption('more-modules'))) { $input->setOption('more-modules', 'yes'); } while ($input->getOption('more-modules') == 'yes') { /** module name **/ if (count($modules) == 0) { $moduleName = null; $output->writeln(array('', 'The minimum syntax of the module name is a single word,', 'with additional optional words separated by hyphens, indicating the ', 'channel that the module relates to (like <comment>twitter</comment> or <comment>analytics-cta</comment>).', '', 'The first module name entered will also be used to generate', 'the default bundle and package name. You will have the opportunity to', 'change this later.', '', 'Provide the module name in CamelCase (e.g. "MailChimp")', 'if you want to influence how the respective classes will', 'be auto-generated. Should the module name consist of more than', 'one word, then provide it with a blank character and upper case', '(e.g. "Social Media").', '')); $question = new Question($questionHelper->getQuestion('Module name', $moduleName), $moduleName); $question->setValidator(function ($answer) { return Validators::validateModuleName($answer, false); }); $moduleName = $questionHelper->ask($input, $output, $question); if (!$moduleName) { $output->writeln(array('<comment>You must define at least one module.</comment>')); continue; } } else { $moduleName = $modules[0]['module_name']; } $moduleNameUnderscore = strtolower(str_replace(' ', '_', $moduleName)); $moduleNameHyphen = strtolower(str_replace(' ', '-', $moduleName)); /** module name suffix **/ $moduleNameSuffix = null; $output->writeln(array('', 'To further describe your module, add an optional suffix.', 'The recommended syntax of the module suffix is to use hyphens (-)', 'to separate words (like <comment>update-status</comment>).', '')); $question = new Question($questionHelper->getQuestion('Module name suffix', $moduleNameSuffix), $moduleNameSuffix); if (count($modules) == 0) { $question->setValidator(function ($answer) { return Validators::validateModuleNameSuffix($answer, false); }); } else { $question->setValidator(function ($answer) use($modules) { return Validators::validateModuleNameSuffix($answer, $modules, true, false); }); } $moduleNameSuffix = $questionHelper->ask($input, $output, $question); $moduleIdentifier = $this->createModuleIdentifier($vendorName, $moduleNameHyphen, $moduleNameSuffix); $output->writeln(array('', 'Based on your inputs, the module identifier for your module will be.', '<comment>' . $moduleIdentifier . '</comment>).', '')); /** module display name **/ $moduleDisplayName = null; $output->writeln(array('', 'The module display name is a human-readable label that will be shown', 'in CampaignChain\'s graphical user interface', '(like <comment>Update Twitter Status</comment>).', '')); $question = new Question($questionHelper->getQuestion('Module display name', $moduleDisplayName), $moduleDisplayName); $question->setValidator(function ($answer) { return Validators::validateDisplayName($answer, false); }); $moduleDisplayName = $questionHelper->ask($input, $output, $question); /** module description **/ $moduleDescription = null; $output->writeln(array('', 'The module description (optional) briefly explains the purpose of the module', '(like <comment>This module updates your Twitter status</comment>).', '')); $question = new Question($questionHelper->getQuestion('Module description', $moduleDescription), $moduleDescription); $question->setValidator(function ($answer) { return Validators::validateDescription($answer, false); }); $moduleDescription = $questionHelper->ask($input, $output, $question); /** owns_location value **/ $operationOwnsLocation = null; if ($moduleType == 'operation') { $output->writeln(array('', 'For Operation modules only, specify whether the operation owns its location.', 'State <comment>true</comment> or <comment>false</comment>.', 'For example, choose <comment>true</comment> if the operation creates a location, such as when posting on Twitter.', '')); $question = new Question($questionHelper->getQuestion('Does the operation own its location?', 'true'), 'true'); $question->setValidator(function ($answer) { return Validators::validateOperationOwnsLocation($answer, false); }); $operationOwnsLocation = $questionHelper->ask($input, $output, $question); } /* metrics value */ $metricsForOperation = null; if ($moduleType == 'operation') { $output->writeln(array('', 'For Operation modules only, specify the metrics for the operation', '(like <comment>Clicks</comment> or <comment>Clicks, Likes, Shares</comment>).', '', 'List the metrics as a comma-separated list.', '')); $question = new Question($questionHelper->getQuestion('Metrics for the operation', $metricsForOperation), $metricsForOperation); $question->setValidator(function ($answer) { return Validators::validateMetricsForOperation($answer, false); }); $metricsForOperation = $questionHelper->ask($input, $output, $question); } /* channels value */ $channelsForActivity = null; if ($moduleType == 'activity') { $output->writeln(array('', 'Usually, an Activity is being executed in a single Channel.', 'For example, the Activity of posting to a Twitter stream happens', 'in the Twitter Channel.', '', 'Yet, there are Activities that are being executed in multiple', 'Channels which are being managed by other Modules. Such Activities', 'must NOT be related to a Channel. For example, a Module for posting', 'the same content to various social media channels.')); $question = new Question($questionHelper->getQuestion('Does the Activity module execute in a single Channel?', 'yes'), 'yes'); $question->setValidator(function ($answer) { return Validators::validateBooleanAnswer($answer, false); }); $singleChannel = $questionHelper->ask($input, $output, $question) == 'yes' ? true : false; if ($singleChannel) { $output->writeln(array('', 'For Activity modules only, specify the channels for the activity.', '', 'The format for each channel module name is', '<comment>vendor/channel-[module-name]/[module-id]</comment>', '(like <comment>acme/channel-twitter/acme-twitter</comment>).', '', 'List the channels as a comma-separated list.', '')); $question = new Question($questionHelper->getQuestion('Channels for the activity', $channelsForActivity), $channelsForActivity); $question->setValidator(function ($answer) { return Validators::validateChannelsForActivity($answer, false); }); $channelsForActivity = $questionHelper->ask($input, $output, $question); } } /* hooks value */ $hooksForActivity = null; if ($moduleType == 'activity') { $output->writeln(array('', 'For Activity modules only, specify the hooks for the activity.', '', 'The format for each hook name is <comment>[module-name]</comment>', '(like <comment>campaignchain-assignee</comment>).', '', 'List the hooks as a comma-separated list.', '')); $question = new Question($questionHelper->getQuestion('Hooks for the activity', $hooksForActivity), $hooksForActivity); $question->setValidator(function ($answer) { return Validators::validateHooksForActivity($answer, false); }); $hooksForActivity = $questionHelper->ask($input, $output, $question); } /* Location parameter name */ $locationParameterName = null; if ($moduleType == 'activity' && $singleChannel) { $locationParameterName = strtolower('campaignchain.location.' . $vendorName . '.' . $moduleNameUnderscore); $output->writeln(array('', 'For Activity modules only, specify the name of the related Location parameter.', '', 'The format for each Location parameter name is <comment>campaignchain.location.[vendor-name].[module-name].[optional module-suffix]</comment>', '(like <comment>campaignchain-assignee</comment>).', '', 'List the hooks as a comma-separated list.', '')); $question = new Question($questionHelper->getQuestion('Location parameter name', $locationParameterName), $locationParameterName); $question->setValidator(function ($answer) { return Validators::validateLocationParameterName($answer); }); $locationParameterName = $questionHelper->ask($input, $output, $question); } /* Does the Activity equal an Operation? */ $equalsOperation = null; if ($moduleType == 'activity') { $question = new Question($questionHelper->getQuestion('Does the Activity equal an Operation?', 'true'), 'true'); $question->setValidator(function ($answer) { return Validators::validateEqualsOperation($answer); }); $equalsOperation = $questionHelper->ask($input, $output, $question); } /* Operations related to Activity */ $operationParameterNames = null; if ($moduleType == 'activity') { $operationParameterNames = 'campaignchain.operation.' . $vendorName . '.' . $moduleNameUnderscore; if ($moduleNameSuffix) { $operationParameterNames .= '.' . str_replace('-', '_', $moduleNameSuffix); } $operationParameterNames = strtolower($operationParameterNames); $output->writeln(array('', 'For Activity modules only, specify the parameter names of', 'each Operation that belongs to the Activity.', '', 'The format for each Operation parameter name is', '<comment>campaignchain.operation.[vendor-name].[module-name].[optional module-suffix]</comment>', '(like <comment>acme.operation.twitter.publish</comment>).', '', 'List the parameter names as a comma-separated list.', '')); $question = new Question($questionHelper->getQuestion('Operation parameter names for the Activity', $operationParameterNames), $operationParameterNames); $question->setValidator(function ($answer) { return Validators::validateOperationParameterNames($answer); }); $operationParameterNames = $questionHelper->ask($input, $output, $question); } $derivedClassName = implode('', array_map('ucwords', explode('-', $moduleNameHyphen . '-' . $moduleNameSuffix))); if ($channelsForActivity) { $channelsForActivity = explode(',', $channelsForActivity); } $moduleNameSuffixUnderscore = strtolower(str_replace(' ', '_', $moduleNameSuffix)); $moduleNameSuffixHyphen = strtolower(str_replace(' ', '-', $moduleNameSuffix)); $modules[] = array('module_name' => $moduleName, 'module_identifier' => $moduleIdentifier, 'module_name_underscore' => $moduleNameUnderscore, 'module_name_hyphen' => $moduleNameHyphen, 'module_name_suffix' => $moduleNameSuffix, 'module_name_suffix_underscore' => $moduleNameSuffixUnderscore, 'module_name_suffix_hyphen' => $moduleNameSuffixHyphen, 'module_display_name' => $moduleDisplayName, 'module_description' => $moduleDescription, 'operation_owns_location' => $operationOwnsLocation, 'channels_for_activity' => $channelsForActivity, 'hooks_for_activity' => !empty($hooksForActivity) ? explode(',', $hooksForActivity) : null, 'metrics_for_operation' => !empty($metricsForOperation) ? explode(',', $metricsForOperation) : null, 'location_parameter_name' => $locationParameterName, 'activity_equals_operation' => $equalsOperation, 'operation_parameter_names' => explode(',', $operationParameterNames), 'class_name' => $derivedClassName); $output->writeln(array('')); $question = new Question($questionHelper->getQuestion('Add another module?', 'no'), 'no'); $question->setValidator(function ($answer) { return Validators::validateBooleanAnswer($answer, false); }); $anotherModule = $questionHelper->ask($input, $output, $question); $input->setOption('more-modules', $anotherModule); } return $modules; }
protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, BundleInterface $bundle, $format, $entity, $prefix) { $auto = true; if ($input->isInteractive()) { $question = new ConfirmationQuestion($questionHelper->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true); $auto = $questionHelper->ask($input, $output, $question); } $output->write('Importing the CRUD routes: '); $this->getContainer()->get('filesystem')->mkdir($bundle->getPath() . '/Resources/config/'); $routing = new RoutingManipulator($bundle->getPath() . '/Resources/config/routing.yml'); try { $ret = $auto ? $routing->addResource($bundle->getName(), $format, '/' . $prefix, 'routing/' . strtolower(str_replace('\\', '_', $entity))) : false; } catch (\RuntimeException $exc) { $ret = false; } if (!$ret) { $help = sprintf(" <comment>resource: \"@%s/Resources/config/routing/%s.%s\"</comment>\n", $bundle->getName(), strtolower(str_replace('\\', '_', $entity)), $format); $help .= sprintf(" <comment>prefix: /%s</comment>\n", $prefix); return array('- Import the bundle\'s routing resource in the bundle routing file', sprintf(' (%s).', $bundle->getPath() . '/Resources/config/routing.yml'), '', sprintf(' <comment>%s:</comment>', $bundle->getName() . ('' !== $prefix ? '_' . str_replace('/', '_', $prefix) : '')), $help, ''); } }
private function addFields(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper) { $fields = $this->parseFields($input->getOption('fields')); $output->writeln(array('', 'Instead of starting with a blank entity, you can add some fields now.', 'Note that the primary key will be added automatically (named <comment>id</comment>).', '')); $output->write('<info>Available types:</info> '); $types = array_keys(Type::getTypesMap()); $count = 20; foreach ($types as $i => $type) { if ($count > 50) { $count = 0; $output->writeln(''); } $count += strlen($type); $output->write(sprintf('<comment>%s</comment>', $type)); if (count($types) != $i + 1) { $output->write(', '); } else { $output->write('.'); } } $output->writeln(''); $fieldValidator = function ($type) use($types) { if (!in_array($type, $types)) { throw new \InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } return $type; }; $lengthValidator = function ($length) { if (!$length) { return $length; } $result = filter_var($length, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1))); if (false === $result) { throw new \InvalidArgumentException(sprintf('Invalid length "%s".', $length)); } return $length; }; $boolValidator = function ($value) { if (null === ($valueAsBool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE))) { throw new \InvalidArgumentException(sprintf('Invalid bool value "%s".', $value)); } return $valueAsBool; }; $precisionValidator = function ($precision) { if (!$precision) { return $precision; } $result = filter_var($precision, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65))); if (false === $result) { throw new \InvalidArgumentException(sprintf('Invalid precision "%s".', $precision)); } return $precision; }; $scaleValidator = function ($scale) { if (!$scale) { return $scale; } $result = filter_var($scale, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 30))); if (false === $result) { throw new \InvalidArgumentException(sprintf('Invalid scale "%s".', $scale)); } return $scale; }; while (true) { $output->writeln(''); $generator = $this->getGenerator(); $question = new Question($questionHelper->getQuestion('New field name (press <return> to stop adding fields)', null), null); $question->setValidator(function ($name) use($fields, $generator) { if (isset($fields[$name]) || 'id' == $name) { throw new \InvalidArgumentException(sprintf('Field "%s" is already defined.', $name)); } // check reserved words if ($generator->isReservedKeyword($name)) { throw new \InvalidArgumentException(sprintf('Name "%s" is a reserved word.', $name)); } // check for valid PHP variable name if (!is_null($name) && !$generator->isValidPhpVariableName($name)) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP variable name.', $name)); } return $name; }); $columnName = $questionHelper->ask($input, $output, $question); if (!$columnName) { break; } $defaultType = 'string'; // try to guess the type by the column name prefix/suffix if (substr($columnName, -3) == '_at') { $defaultType = 'datetime'; } elseif (substr($columnName, -3) == '_id') { $defaultType = 'integer'; } elseif (substr($columnName, 0, 3) == 'is_') { $defaultType = 'boolean'; } elseif (substr($columnName, 0, 4) == 'has_') { $defaultType = 'boolean'; } $question = new Question($questionHelper->getQuestion('Field type', $defaultType), $defaultType); $question->setValidator($fieldValidator); $question->setAutocompleterValues($types); $type = $questionHelper->ask($input, $output, $question); $data = array('columnName' => $columnName, 'fieldName' => lcfirst(Container::camelize($columnName)), 'type' => $type); if ($type == 'string') { $question = new Question($questionHelper->getQuestion('Field length', 255), 255); $question->setValidator($lengthValidator); $data['length'] = $questionHelper->ask($input, $output, $question); } elseif ('decimal' === $type) { // 10 is the default value given in \Doctrine\DBAL\Schema\Column::$_precision $question = new Question($questionHelper->getQuestion('Precision', 10), 10); $question->setValidator($precisionValidator); $data['precision'] = $questionHelper->ask($input, $output, $question); // 0 is the default value given in \Doctrine\DBAL\Schema\Column::$_scale $question = new Question($questionHelper->getQuestion('Scale', 0), 0); $question->setValidator($scaleValidator); $data['scale'] = $questionHelper->ask($input, $output, $question); } $question = new Question($questionHelper->getQuestion('Is nullable', 'false'), false); $question->setValidator($boolValidator); $question->setAutocompleterValues(array('true', 'false')); if ($nullable = $questionHelper->ask($input, $output, $question)) { $data['nullable'] = $nullable; } $question = new Question($questionHelper->getQuestion('Unique', 'false'), false); $question->setValidator($boolValidator); $question->setAutocompleterValues(array('true', 'false')); if ($unique = $questionHelper->ask($input, $output, $question)) { $data['unique'] = $unique; } $fields[$columnName] = $data; } return $fields; }
/** * @param InputInterface $input * @param OutputInterface $output * @param QuestionHelper $questionHelper * @throws \InvalidArgumentException * @return array */ private function addFields(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper, Bundle\BundleInterface $bundle) { $fields = []; $output->writeln(['', 'Add some fields to the class', '']); $lengthValidator = function ($length) { if (!$length) { return $length; } $result = filter_var($length, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1))); if (false === $result) { throw new \InvalidArgumentException(sprintf('Invalid length "%s".', $length)); } return $length; }; $generator = $this->getGenerator($bundle); while (true) { $output->writeln(''); // Ask column name $question = new Question($questionHelper->getQuestion('New field name (press <return> to stop adding fields)', null), null); $question->setValidator(function ($name) use($fields, $generator) { if (isset($fields[$name]) || 'id' == $name) { throw new \InvalidArgumentException(sprintf('Field "%s" is already defined.', $name)); } return $name; }); $fieldName = $questionHelper->ask($input, $output, $question); if (!$fieldName) { break; } // Ask type $question = new Question($questionHelper->getQuestion('Field type', null), null); $type = $questionHelper->ask($input, $output, $question); $data = ['fieldName' => $fieldName, 'type' => $type]; $fields[$fieldName] = $data; } return $fields; }