PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/robmorgan/phinx/src/Phinx/Console/Command/Create.php

https://gitlab.com/alexandresgv/siteentec
PHP | 242 lines | 147 code | 31 blank | 64 comment | 24 complexity | f19fd24553e9966db7a7e63f6663d564 MD5 | raw file
  1. <?php
  2. /**
  3. * Phinx
  4. *
  5. * (The MIT license)
  6. * Copyright (c) 2015 Rob Morgan
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated * documentation files (the "Software"), to
  10. * deal in the Software without restriction, including without limitation the
  11. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  12. * sell copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  24. * IN THE SOFTWARE.
  25. *
  26. * @package Phinx
  27. * @subpackage Phinx\Console
  28. */
  29. namespace Phinx\Console\Command;
  30. use Phinx\Migration\CreationInterface;
  31. use Phinx\Util\Util;
  32. use Symfony\Component\Console\Input\InputArgument;
  33. use Symfony\Component\Console\Input\InputInterface;
  34. use Symfony\Component\Console\Input\InputOption;
  35. use Symfony\Component\Console\Output\OutputInterface;
  36. use Symfony\Component\Console\Question\ConfirmationQuestion;
  37. class Create extends AbstractCommand
  38. {
  39. /**
  40. * The name of the interface that any external template creation class is required to implement.
  41. */
  42. const CREATION_INTERFACE = 'Phinx\Migration\CreationInterface';
  43. /**
  44. * {@inheritdoc}
  45. */
  46. protected function configure()
  47. {
  48. parent::configure();
  49. $this->setName('create')
  50. ->setDescription('Create a new migration')
  51. ->addArgument('name', InputArgument::REQUIRED, 'What is the name of the migration?')
  52. ->setHelp(sprintf(
  53. '%sCreates a new database migration%s',
  54. PHP_EOL,
  55. PHP_EOL
  56. ));
  57. // An alternative template.
  58. $this->addOption('template', 't', InputOption::VALUE_REQUIRED, 'Use an alternative template');
  59. // A classname to be used to gain access to the template content as well as the ability to
  60. // have a callback once the migration file has been created.
  61. $this->addOption('class', 'l', InputOption::VALUE_REQUIRED, 'Use a class implementing "' . self::CREATION_INTERFACE . '" to generate the template');
  62. }
  63. /**
  64. * Get the confirmation question asking if the user wants to create the
  65. * migrations directory.
  66. *
  67. * @return ConfirmationQuestion
  68. */
  69. protected function getCreateMigrationDirectoryQuestion()
  70. {
  71. return new ConfirmationQuestion('Create migrations directory? [y]/n ', true);
  72. }
  73. /**
  74. * Create the new migration.
  75. *
  76. * @param InputInterface $input
  77. * @param OutputInterface $output
  78. * @throws \RuntimeException
  79. * @throws \InvalidArgumentException
  80. * @return void
  81. */
  82. protected function execute(InputInterface $input, OutputInterface $output)
  83. {
  84. $this->bootstrap($input, $output);
  85. // get the migration path from the config
  86. $path = $this->getConfig()->getMigrationPath();
  87. if (!file_exists($path)) {
  88. $helper = $this->getHelper('question');
  89. $question = $this->getCreateMigrationDirectoryQuestion();
  90. if ($helper->ask($input, $output, $question)) {
  91. mkdir($path, 0755, true);
  92. }
  93. }
  94. $this->verifyMigrationDirectory($path);
  95. $path = realpath($path);
  96. $className = $input->getArgument('name');
  97. if (!Util::isValidPhinxClassName($className)) {
  98. throw new \InvalidArgumentException(sprintf(
  99. 'The migration class name "%s" is invalid. Please use CamelCase format.',
  100. $className
  101. ));
  102. }
  103. if (!Util::isUniqueMigrationClassName($className, $path)) {
  104. throw new \InvalidArgumentException(sprintf(
  105. 'The migration class name "%s" already exists',
  106. $className
  107. ));
  108. }
  109. // Compute the file path
  110. $fileName = Util::mapClassNameToFileName($className);
  111. $filePath = $path . DIRECTORY_SEPARATOR . $fileName;
  112. if (is_file($filePath)) {
  113. throw new \InvalidArgumentException(sprintf(
  114. 'The file "%s" already exists',
  115. $filePath
  116. ));
  117. }
  118. // Get the alternative template and static class options, but only allow one of them.
  119. $altTemplate = $input->getOption('template');
  120. if (!$altTemplate) {
  121. $altTemplate = $this->getConfig()->getTemplateFile();
  122. }
  123. $creationClassName = $input->getOption('class');
  124. if (!$creationClassName) {
  125. $creationClassName = $this->getConfig()->getTemplateClass();
  126. }
  127. if ($altTemplate && $creationClassName) {
  128. throw new \InvalidArgumentException('Cannot use --template and --class at the same time');
  129. }
  130. // Verify the alternative template file's existence.
  131. if ($altTemplate && !is_file($altTemplate)) {
  132. throw new \InvalidArgumentException(sprintf(
  133. 'The alternative template file "%s" does not exist',
  134. $altTemplate
  135. ));
  136. }
  137. // Verify that the template creation class (or the aliased class) exists and that it implements the required interface.
  138. $aliasedClassName = null;
  139. if ($creationClassName) {
  140. // Supplied class does not exist, is it aliased?
  141. if (!class_exists($creationClassName)) {
  142. $aliasedClassName = $this->getConfig()->getAlias($creationClassName);
  143. if ($aliasedClassName && !class_exists($aliasedClassName)) {
  144. throw new \InvalidArgumentException(sprintf(
  145. 'The class "%s" via the alias "%s" does not exist',
  146. $aliasedClassName,
  147. $creationClassName
  148. ));
  149. } elseif (!$aliasedClassName) {
  150. throw new \InvalidArgumentException(sprintf(
  151. 'The class "%s" does not exist',
  152. $creationClassName
  153. ));
  154. }
  155. }
  156. // Does the class implement the required interface?
  157. if (!$aliasedClassName && !is_subclass_of($creationClassName, self::CREATION_INTERFACE)) {
  158. throw new \InvalidArgumentException(sprintf(
  159. 'The class "%s" does not implement the required interface "%s"',
  160. $creationClassName,
  161. self::CREATION_INTERFACE
  162. ));
  163. } elseif ($aliasedClassName && !is_subclass_of($aliasedClassName, self::CREATION_INTERFACE)) {
  164. throw new \InvalidArgumentException(sprintf(
  165. 'The class "%s" via the alias "%s" does not implement the required interface "%s"',
  166. $aliasedClassName,
  167. $creationClassName,
  168. self::CREATION_INTERFACE
  169. ));
  170. }
  171. }
  172. // Use the aliased class.
  173. $creationClassName = $aliasedClassName ?: $creationClassName;
  174. // Determine the appropriate mechanism to get the template
  175. if ($creationClassName) {
  176. // Get the template from the creation class
  177. $creationClass = new $creationClassName();
  178. $contents = $creationClass->getMigrationTemplate();
  179. } else {
  180. // Load the alternative template if it is defined.
  181. $contents = file_get_contents($altTemplate ?: $this->getMigrationTemplateFilename());
  182. }
  183. // inject the class names appropriate to this migration
  184. $classes = array(
  185. '$useClassName' => $this->getConfig()->getMigrationBaseClassName(false),
  186. '$className' => $className,
  187. '$version' => Util::getVersionFromFileName($fileName),
  188. '$baseClassName' => $this->getConfig()->getMigrationBaseClassName(true),
  189. );
  190. $contents = strtr($contents, $classes);
  191. if (false === file_put_contents($filePath, $contents)) {
  192. throw new \RuntimeException(sprintf(
  193. 'The file "%s" could not be written to',
  194. $path
  195. ));
  196. }
  197. // Do we need to do the post creation call to the creation class?
  198. if ($creationClassName) {
  199. $creationClass->postMigrationCreation($filePath, $className, $this->getConfig()->getMigrationBaseClassName());
  200. }
  201. $output->writeln('<info>using migration base class</info> ' . $classes['$useClassName']);
  202. if (!empty($altTemplate)) {
  203. $output->writeln('<info>using alternative template</info> ' . $altTemplate);
  204. } elseif (!empty($creationClassName)) {
  205. $output->writeln('<info>using template creation class</info> ' . $creationClassName);
  206. } else {
  207. $output->writeln('<info>using default template</info>');
  208. }
  209. $output->writeln('<info>created</info> .' . str_replace(getcwd(), '', $filePath));
  210. }
  211. }