command.php 4.8 KB

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