command.php 4.7 KB

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