command.php 4.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
<?php namespace Laravel\CLI;

use Laravel\IoC;
use Laravel\Str;
use Laravel\Bundle;

class Command {

	/**
	 * Run a CLI task with the given arguments.
	 *
Taylor Otwell committed
12 13 14 15 16 17 18 19
	 * <code>
	 *		// Call the migrate artisan task
	 *		Command::run(array('migrate'));
	 *
	 *		// Call the migrate task with some arguments
	 *		Command::run(array('migrate:rollback', 'bundle-name'))
	 * </code>
	 *
20 21 22 23 24
	 * @param  array  $arguments
	 * @return void
	 */
	public static function run($arguments = array())
	{
Taylor Otwell committed
25
		static::validate($arguments);
26 27 28

		list($bundle, $task, $method) = static::parse($arguments[0]);

Taylor Otwell committed
29 30
		// If the task exists within a bundle, we will start the bundle so that any
		// dependencies can be registered in the application IoC container. If the
Taylor Otwell committed
31
		// task is registered in the container,  we'll resolve it.
Taylor Otwell committed
32 33 34 35
		if (Bundle::exists($bundle))
		{
			Bundle::start($bundle);
		}
36

Taylor Otwell committed
37 38
		$task = static::resolve($bundle, $task);

39 40 41
		// Once the bundle has been resolved, we'll make sure we could actually
		// find that task, and then verify that the method exists on the task
		// so we can successfully call it without a problem.
Taylor Otwell committed
42
		if (is_null($task))
43 44 45 46
		{
			throw new \Exception("Sorry, I can't find that task.");
		}

47
		if (is_callable(array($task, $method)))
48 49 50 51 52 53 54
		{
			$task->$method(array_slice($arguments, 1));
		}
		else
		{
			throw new \Exception("Sorry, I can't find that method!");
		}
55 56 57
	}

	/**
Taylor Otwell committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71
	 * Determine if the given command arguments are valid.
	 *
	 * @param  array  $arguments
	 * @return void
	 */
	protected static function validate($arguments)
	{
		if ( ! isset($arguments[0]))
		{
			throw new \Exception("You forgot to provide the task name.");
		}
	}

	/**
72 73 74 75 76 77 78 79 80 81 82
	 * Parse the task name to extract the bundle, task, and method.
	 *
	 * @param  string  $task
	 * @return array
	 */
	protected static function parse($task)
	{
		list($bundle, $task) = Bundle::parse($task);

		// Extract the task method from the task string. Methods are called
		// on tasks by separating the task and method with a single colon.
Taylor Otwell committed
83
		// If no task is specified, "run" is used as the default.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
		if (str_contains($task, ':'))
		{
			list($task, $method) = explode(':', $task);
		}
		else
		{
			$method = 'run';
		}

		return array($bundle, $task, $method);
	}

	/**
	 * Resolve an instance of the given task name.
	 *
Taylor Otwell committed
99 100 101 102 103 104 105 106
	 * <code>
	 *		// Resolve an instance of a task
	 *		$task = Command::resolve('application', 'migrate');
	 *
	 *		// Resolve an instance of a task wtihin a bundle
	 *		$task = Command::resolve('bundle', 'foo');
	 * </code>
	 *
107 108 109 110 111 112 113 114
	 * @param  string  $bundle
	 * @param  string  $task
	 * @return object
	 */
	public static function resolve($bundle, $task)
	{
		$identifier = Bundle::identifier($bundle, $task);

115 116
		// First we'll check to see if the task has been registered in the
		// application IoC container. This allows all dependencies to be
117
		// injected into tasks for more flexible testability.
118 119 120 121 122
		if (IoC::registered("task: {$identifier}"))
		{
			return IoC::resolve("task: {$identifier}");
		}

123 124 125
		// If the task file exists, we'll format the bundle and task name
		// into a task class name and resolve an instance of the so that
		// the requested method may be executed.
126 127 128 129 130 131 132 133 134 135 136
		if (file_exists($path = Bundle::path($bundle).'tasks/'.$task.EXT))
		{
			require $path;

			$task = static::format($bundle, $task);

			return new $task;
		}
	}

	/**
Taylor Otwell committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
	 * Parse the command line arguments and return the results.
	 *
	 * @param  array  $argv
	 * @return array
	 */
	public static function options($argv)
	{
		$options = array();

		$arguments = array();

		for ($i = 0, $count = count($argv); $i < $count; $i++)
		{
			$argument = $argv[$i];

			// If the CLI argument starts with a double hyphen, it is an option,
			// so we will extract the value and add it to the array of options
			// to be returned by the method.
			if (starts_with($argument, '--'))
			{
				// By default, we will assume the value of the options is true,
				// but if the option contains an equals sign, we will take the
				// value to the right of the equals sign as the value and
				// remove the value from the option key.
				list($key, $value) = array(substr($argument, 2), true);

				if (($equals = strpos($argument, '=')) !== false)
				{
					$key = substr($argument, 2, $equals - 2);

					$value = substr($argument, $equals + 1);
				}

				$options[$key] = $value;
			}
			// If the CLI argument does not start with a double hyphen it's
			// simply an argument to be passed to the console task so we'll
			// add it to the array of "regular" arguments.
			else
			{
				$arguments[] = $argument;
			}
		}

		return array($arguments, $options);
	}

	/**
185 186 187 188 189 190 191 192 193 194
	 * Format a bundle and task into a task class name.
	 *
	 * @param  string  $bundle
	 * @param  string  $task
	 * @return string
	 */
	protected static function format($bundle, $task)
	{
		$prefix = Bundle::class_prefix($bundle);

Kelly Banman committed
195
		return '\\'.$prefix.Str::classify($task).'_Task';
196 197
	}

198
}