command.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php namespace Laravel\CLI;
  2. use Laravel\IoC;
  3. use Laravel\Str;
  4. use Laravel\Bundle;
  5. class Command {
  6. /**
  7. * Run a CLI task with the given arguments.
  8. *
  9. * <code>
  10. * // Call the migrate artisan task
  11. * Command::run(array('migrate'));
  12. *
  13. * // Call the migrate task with some arguments
  14. * Command::run(array('migrate:rollback', 'bundle-name'))
  15. * </code>
  16. *
  17. * @param array $arguments
  18. * @return void
  19. */
  20. public static function run($arguments = array())
  21. {
  22. static::validate($arguments);
  23. list($bundle, $task, $method) = static::parse($arguments[0]);
  24. // If the task exists within a bundle, we will start the bundle so that any
  25. // dependencies can be registered in the application IoC container. If the
  26. // task is registered in the container, we'll resolve it.
  27. if (Bundle::exists($bundle))
  28. {
  29. Bundle::start($bundle);
  30. }
  31. $task = static::resolve($bundle, $task);
  32. // Once the bundle has been resolved, we'll make sure we could actually
  33. // find that task, and then verify that the method exists on the task
  34. // so we can successfully call it without a problem.
  35. if (is_null($task))
  36. {
  37. throw new \Exception("Sorry, I can't find that task.");
  38. }
  39. if (is_callable(array($task, $method)))
  40. {
  41. $task->$method(array_slice($arguments, 1));
  42. }
  43. else
  44. {
  45. throw new \Exception("Sorry, I can't find that method!");
  46. }
  47. }
  48. /**
  49. * Determine if the given command arguments are valid.
  50. *
  51. * @param array $arguments
  52. * @return void
  53. */
  54. protected static function validate($arguments)
  55. {
  56. if ( ! isset($arguments[0]))
  57. {
  58. throw new \Exception("You forgot to provide the task name.");
  59. }
  60. }
  61. /**
  62. * Parse the task name to extract the bundle, task, and method.
  63. *
  64. * @param string $task
  65. * @return array
  66. */
  67. protected static function parse($task)
  68. {
  69. list($bundle, $task) = Bundle::parse($task);
  70. // Extract the task method from the task string. Methods are called
  71. // on tasks by separating the task and method with a single colon.
  72. // If no task is specified, "run" is used as the default.
  73. if (str_contains($task, ':'))
  74. {
  75. list($task, $method) = explode(':', $task);
  76. }
  77. else
  78. {
  79. $method = 'run';
  80. }
  81. return array($bundle, $task, $method);
  82. }
  83. /**
  84. * Resolve an instance of the given task name.
  85. *
  86. * <code>
  87. * // Resolve an instance of a task
  88. * $task = Command::resolve('application', 'migrate');
  89. *
  90. * // Resolve an instance of a task wtihin a bundle
  91. * $task = Command::resolve('bundle', 'foo');
  92. * </code>
  93. *
  94. * @param string $bundle
  95. * @param string $task
  96. * @return object
  97. */
  98. public static function resolve($bundle, $task)
  99. {
  100. $identifier = Bundle::identifier($bundle, $task);
  101. // First we'll check to see if the task has been registered in the
  102. // application IoC container. This allows all dependencies to be
  103. // injected into tasks for more flexible testability.
  104. if (IoC::registered("task: {$identifier}"))
  105. {
  106. return IoC::resolve("task: {$identifier}");
  107. }
  108. // If the task file exists, we'll format the bundle and task name
  109. // into a task class name and resolve an instance of the so that
  110. // the requested method may be executed.
  111. if (file_exists($path = Bundle::path($bundle).'tasks/'.$task.EXT))
  112. {
  113. require $path;
  114. $task = static::format($bundle, $task);
  115. return new $task;
  116. }
  117. }
  118. /**
  119. * Parse the command line arguments and return the results.
  120. *
  121. * @param array $argv
  122. * @return array
  123. */
  124. public static function options($argv)
  125. {
  126. $options = array();
  127. $arguments = array();
  128. for ($i = 0, $count = count($argv); $i < $count; $i++)
  129. {
  130. $argument = $argv[$i];
  131. // If the CLI argument starts with a double hyphen, it is an option,
  132. // so we will extract the value and add it to the array of options
  133. // to be returned by the method.
  134. if (starts_with($argument, '--'))
  135. {
  136. // By default, we will assume the value of the options is true,
  137. // but if the option contains an equals sign, we will take the
  138. // value to the right of the equals sign as the value and
  139. // remove the value from the option key.
  140. list($key, $value) = array(substr($argument, 2), true);
  141. if (($equals = strpos($argument, '=')) !== false)
  142. {
  143. $key = substr($argument, 2, $equals - 2);
  144. $value = substr($argument, $equals + 1);
  145. }
  146. $options[$key] = $value;
  147. }
  148. // If the CLI argument does not start with a double hyphen it's
  149. // simply an argument to be passed to the console task so we'll
  150. // add it to the array of "regular" arguments.
  151. else
  152. {
  153. $arguments[] = $argument;
  154. }
  155. }
  156. return array($arguments, $options);
  157. }
  158. /**
  159. * Format a bundle and task into a task class name.
  160. *
  161. * @param string $bundle
  162. * @param string $task
  163. * @return string
  164. */
  165. protected static function format($bundle, $task)
  166. {
  167. $prefix = Bundle::class_prefix($bundle);
  168. return '\\'.$prefix.Str::classify($task).'_Task';
  169. }
  170. }