PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Doctrine/Cli.php

https://bitbucket.org/areeves42/openfisma
PHP | 353 lines | 191 code | 63 blank | 99 comment | 33 complexity | 3833233391ccb69a1d5a07e5a7bad62a MD5 | raw file
  1. <?php
  2. /*
  3. * $Id: Cli.php 2761 2007-10-07 23:42:29Z zYne $
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information, see
  19. * <http://www.phpdoctrine.org>.
  20. */
  21. /**
  22. * Command line interface class
  23. * Interface for easily executing Doctrine_Task classes from a
  24. * command line interface
  25. *
  26. * @package Doctrine
  27. * @subpackage Cli
  28. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  29. * @link www.phpdoctrine.org
  30. * @since 1.0
  31. * @version $Revision: 2761 $
  32. * @author Jonathan H. Wage <jwage@mac.com>
  33. */
  34. class Doctrine_Cli
  35. {
  36. protected $_tasks = array(),
  37. $_taskInstance = null,
  38. $_formatter = null,
  39. $_scriptName = null,
  40. $_message = null,
  41. $_config = array();
  42. /**
  43. * __construct
  44. *
  45. * @param string $config
  46. * @return void
  47. */
  48. public function __construct($config = array())
  49. {
  50. $this->_config = $config;
  51. $this->_formatter = new Doctrine_Cli_AnsiColorFormatter();
  52. $this->loadTasks();
  53. }
  54. /**
  55. * Notify the formatter of a message
  56. *
  57. * @param string $notification The notification message
  58. * @param string $style Style to format the notification with(INFO, ERROR)
  59. * @return void
  60. */
  61. public function notify($notification = null, $style = 'HEADER')
  62. {
  63. echo $this->_formatter->format($this->_taskInstance->getTaskName(), 'INFO') . ' - ' . $this->_formatter->format($notification, $style) . "\n";
  64. }
  65. /**
  66. * Notify the formatter of an exception
  67. *
  68. * @param Exception $exception
  69. * @return void
  70. */
  71. public function notifyException($exception)
  72. {
  73. echo $this->_formatter->format($exception->getMessage(), 'ERROR') . "\n";
  74. echo $this->_formatter->format($exception->getMessage() . "\n" . $exception->getTraceAsString(), 'ERROR') . "\n";
  75. }
  76. /**
  77. * Public function to run the loaded task with the passed arguments
  78. *
  79. * @param array $args
  80. * @return void
  81. * @throws new Doctrine_Cli_Exception
  82. */
  83. public function run($args)
  84. {
  85. try {
  86. $this->_run($args);
  87. } catch (Exception $exception) {
  88. $this->notifyException($exception);
  89. }
  90. }
  91. /**
  92. * Get the name of the task class based on the first argument
  93. * which is always the task name. Do some inflection to determine the class name
  94. *
  95. * @param array $args Array of arguments from the cli
  96. * @return string $taskClass Task class name
  97. */
  98. protected function _getTaskClassFromArgs($args)
  99. {
  100. $taskName = str_replace('-', '_', $args[1]);
  101. $taskClass = 'Doctrine_Task_' . Doctrine_Inflector::classify($taskName);
  102. return $taskClass;
  103. }
  104. /**
  105. * Run the actual task execution with the passed arguments
  106. *
  107. * @param array $args Array of arguments for this task being executed
  108. * @return void
  109. * @throws Doctrine_Cli_Exception $e
  110. */
  111. protected function _run($args)
  112. {
  113. $this->_scriptName = $args[0];
  114. $arg1 = isset($args[1]) ? $args[1]:null;
  115. if ( ! $arg1 || $arg1 == 'help') {
  116. echo $this->printTasks(null, $arg1 == 'help' ? true:false);
  117. return;
  118. }
  119. if (isset($args[1]) && isset($args[2]) && $args[2] === 'help') {
  120. echo $this->printTasks($args[1], true);
  121. return;
  122. }
  123. $taskClass = $this->_getTaskClassFromArgs($args);
  124. if ( ! class_exists($taskClass)) {
  125. throw new Doctrine_Cli_Exception('Cli task could not be found: ' . $taskClass);
  126. }
  127. unset($args[0]);
  128. unset($args[1]);
  129. $this->_taskInstance = new $taskClass($this);
  130. $args = $this->prepareArgs($args);
  131. $this->_taskInstance->setArguments($args);
  132. if ($this->_taskInstance->validate()) {
  133. $this->_taskInstance->execute();
  134. } else {
  135. echo $this->_formatter->format('Requires arguments missing!!', 'ERROR') . "\n\n";
  136. echo $this->printTasks($arg1, true);
  137. }
  138. }
  139. /**
  140. * Prepare the raw arguments for execution. Combines with the required and optional argument
  141. * list in order to determine a complete array of arguments for the task
  142. *
  143. * @param array $args Array of raw arguments
  144. * @return array $prepared Array of prepared arguments
  145. */
  146. protected function prepareArgs($args)
  147. {
  148. $taskInstance = $this->_taskInstance;
  149. $args = array_values($args);
  150. // First lets load populate an array with all the possible arguments. required and optional
  151. $prepared = array();
  152. $requiredArguments = $taskInstance->getRequiredArguments();
  153. foreach ($requiredArguments as $key => $arg) {
  154. $prepared[$arg] = null;
  155. }
  156. $optionalArguments = $taskInstance->getOptionalArguments();
  157. foreach ($optionalArguments as $key => $arg) {
  158. $prepared[$arg] = null;
  159. }
  160. // If we have a config array then lets try and fill some of the arguments with the config values
  161. if (is_array($this->_config) && !empty($this->_config)) {
  162. foreach ($this->_config as $key => $value) {
  163. if (array_key_exists($key, $prepared)) {
  164. $prepared[$key] = $value;
  165. }
  166. }
  167. }
  168. // Now lets fill in the entered arguments to the prepared array
  169. $copy = $args;
  170. foreach ($prepared as $key => $value) {
  171. if ( ! $value && !empty($copy)) {
  172. $prepared[$key] = $copy[0];
  173. unset($copy[0]);
  174. $copy = array_values($copy);
  175. }
  176. }
  177. return $prepared;
  178. }
  179. /**
  180. * Prints an index of all the available tasks in the CLI instance
  181. *
  182. * @return void
  183. */
  184. public function printTasks($task = null, $full = false)
  185. {
  186. $task = Doctrine_Inflector::classify(str_replace('-', '_', $task));
  187. $tasks = $this->getLoadedTasks();
  188. echo $this->_formatter->format("Doctrine Command Line Interface", 'HEADER') . "\n\n";
  189. foreach ($tasks as $taskName)
  190. {
  191. if ($task != null && strtolower($task) != strtolower($taskName)) {
  192. continue;
  193. }
  194. $className = 'Doctrine_Task_' . $taskName;
  195. $taskInstance = new $className();
  196. $taskInstance->taskName = str_replace('_', '-', Doctrine_Inflector::tableize($taskName));
  197. $syntax = $this->_scriptName . ' ' . $taskInstance->getTaskName();
  198. echo $this->_formatter->format($syntax, 'INFO');
  199. if ($full) {
  200. echo " - " . $taskInstance->getDescription() . "\n";
  201. $args = null;
  202. $requiredArguments = $taskInstance->getRequiredArgumentsDescriptions();
  203. if ( ! empty($requiredArguments)) {
  204. foreach ($requiredArguments as $name => $description) {
  205. $args .= $this->_formatter->format($name, "ERROR");
  206. if (isset($this->_config[$name])) {
  207. $args .= " - " . $this->_formatter->format($this->_config[$name], 'COMMENT');
  208. } else {
  209. $args .= " - " . $description;
  210. }
  211. $args .= "\n";
  212. }
  213. }
  214. $optionalArguments = $taskInstance->getOptionalArgumentsDescriptions();
  215. if ( ! empty($optionalArguments)) {
  216. foreach ($optionalArguments as $name => $description) {
  217. $args .= $name . ' - ' . $description."\n";
  218. }
  219. }
  220. if ($args) {
  221. echo "\n" . $this->_formatter->format('Arguments:', 'HEADER') . "\n" . $args;
  222. }
  223. }
  224. echo "\n";
  225. }
  226. }
  227. /**
  228. * Load tasks from the passed directory. If no directory is given it looks in the default
  229. * Doctrine/Task folder for the core tasks.
  230. *
  231. * @param mixed $directory Can be a string path or array of paths
  232. * @return array $loadedTasks Array of tasks loaded
  233. */
  234. public function loadTasks($directory = null)
  235. {
  236. if ($directory === null) {
  237. $directory = Doctrine::getPath() . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Task';
  238. }
  239. $parent = new ReflectionClass('Doctrine_Task');
  240. $tasks = array();
  241. if (is_dir($directory)) {
  242. foreach ((array) $directory as $dir) {
  243. $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
  244. RecursiveIteratorIterator::LEAVES_ONLY);
  245. foreach ($it as $file) {
  246. $e = explode('.', $file->getFileName());
  247. if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) {
  248. $className = 'Doctrine_Task_' . $e[0];
  249. if ( ! class_exists($className)) {
  250. require_once($file->getPathName());
  251. $class = new ReflectionClass($className);
  252. if ($class->isSubClassOf($parent)) {
  253. $tasks[$e[0]] = $e[0];
  254. }
  255. }
  256. }
  257. }
  258. }
  259. }
  260. $classes = get_declared_classes();
  261. foreach ($classes as $className) {
  262. $class = new Reflectionclass($className);
  263. if ($class->isSubClassOf($parent)) {
  264. $task = str_replace('Doctrine_Task_', '', $className);
  265. $tasks[$task] = $task;
  266. }
  267. }
  268. $this->_tasks = array_merge($this->_tasks, $tasks);
  269. return $this->_tasks;
  270. }
  271. /**
  272. * Get array of all the Doctrine_Task child classes that are loaded
  273. *
  274. * @return array $tasks
  275. */
  276. public function getLoadedTasks()
  277. {
  278. $parent = new ReflectionClass('Doctrine_Task');
  279. $classes = get_declared_classes();
  280. $tasks = array();
  281. foreach ($classes as $className) {
  282. $class = new ReflectionClass($className);
  283. if ($class->isSubClassOf($parent)) {
  284. $task = str_replace('Doctrine_Task_', '', $className);
  285. $tasks[$task] = $task;
  286. }
  287. }
  288. return array_merge($this->_tasks, $tasks);
  289. }
  290. }