Passed
Push — 0.7.0 ( 8cbd21...33914c )
by Alexander
02:42
created
src/components/Routing/Route.php 1 patch
Indentation   +666 added lines, -666 removed lines patch added patch discarded remove patch
@@ -41,686 +41,686 @@
 block discarded – undo
41 41
  */
42 42
 class Route 
43 43
 {
44
-	use Concerns\RouteCondition,
45
-	    Concerns\RouteDependencyResolver;
44
+    use Concerns\RouteCondition,
45
+        Concerns\RouteDependencyResolver;
46 46
 	
47
-	/**
48
-	 * Action that the route will use when called.
49
-	 *
50
-	 * @var \Closure|string|array $action
51
-	 */
52
-	public $action;
53
-
54
-	/**
55
-	 * The container instance used by the route.
56
-	 * 
57
-	 * @var \Syscodes\Container\Container $container
58
-	 */
59
-	protected $container;
60
-
61
-	/**
62
-	 * The controller instance.
63
-	 * 
64
-	 * @var string $controller
65
-	 */
66
-	public $controller;
67
-
68
-	/**
69
-	 * The default values for the route.
70
-	 * 
71
-	 * @var array $defaults
72
-	 */
73
-	public $defaults = [];
74
-
75
-	/**
76
-	 * Variable of HTTP method.
77
-	 *  
78
-	 * @var array|string $method
79
-	 */
80
-	public $method;
81
-
82
-	/**
83
-	 * The array of matched parameters.
84
-	 * 
85
-	 * @var array $parameters
86
-	 */
87
-	public $parameters = [];
88
-
89
-	/**
90
-	 * The parameter names for the route.
91
-	 * 
92
-	 * @var string|null $parameterNames
93
-	 */
94
-	public $parameterNames;
95
-
96
-	/**
97
-	* Patterns that should be replaced.
98
-	*
99
-	* @var array $patterns 
100
-	*/
101
-	public $patterns = [
102
-		'~/~'                    =>  '\/',               // Slash
103
-		'~{an:[^\/{}]+}~'        => '([0-9a-zA-Z]++)',   // Placeholder accepts alphabetic and numeric chars
104
-		'~{n:[^\/{}]+}~'         => '([0-9]++)',         // Placeholder accepts only numeric
105
-		'~{a:[^\/{}]+}~'         => '([a-zA-Z]++)',      // Placeholder accepts only alphabetic chars
106
-		'~{w:[^\/{}]+}~'         => '([0-9a-zA-Z-_]++)', // Placeholder accepts alphanumeric and underscore
107
-		'~{\*:[^\/{}]+}~'        => '(.++)',             // Placeholder match rest of url
108
-		'~(\\\/)?{\?:[^\/{}]+}~' => '\/?([^\/]*)',		 // Optional placeholder
109
-		'~{[^\/{}]+}~'           => '([^\/]++)'			 // Normal placeholder
110
-	];
111
-
112
-	/**
113
-	 * The URI pattern the route responds to.
114
-	 *
115
-	 * @var array $uri
116
-	 */
117
-	public $uri = [];
118
-
119
-	/**
120
-	 * Contains the arguments of the current route.
121
-	 *
122
-	 * @var array $where
123
-	 */
124
-	public $wheres = [];
125
-
126
-	/**
127
-	 * Constructor. Initialize route.
128
-	 *
129
-	 * @param  array|string|null  $method  (null by default)
130
-	 * @param  string|null  $uri  (null by default)
131
-	 * @param  \Closure|string|null  $action  (null by default)
132
-	 *
133
-	 * @return void
134
-	 */
135
-	public function __construct($method = null, $uri = null, $action = null)
136
-	{
137
-		$this->uri = $uri;
138
-
139
-		// Set the method
140
-		$this->parseMethod($method);
141
-
142
-		// Set the action
143
-		$this->parseAction($action);
144
-
145
-		if (is_null($prefix = Arr::get($this->action, 'prefix')))
146
-		{
147
-			$this->prefix($prefix);
148
-		}
149
-	}
150
-
151
-	// Getters
152
-
153
-	/**
154
-	 * Get the action of the current route.
155
-	 *
156
-	 * @return \Closure|string
157
-	 */
158
-	public function getAction()
159
-	{
160
-		return $this->action;
161
-	}
162
-
163
-	/**
164
-	 * Get the arguments of the current route.
165
-	 *
166
-	 * @return string
167
-	 */
168
-	public function getArguments()
169
-	{
170
-		return $this->wheres;
171
-	}
172
-
173
-	/**
174
-	 * Get the controller instance for the route.
175
-	 * 
176
-	 * @return mixed
177
-	 */
178
-	public function getController()
179
-	{
180
-		if ( ! $this->controller)
181
-		{
182
-			$class = $this->parseControllerCallback()[0];
47
+    /**
48
+     * Action that the route will use when called.
49
+     *
50
+     * @var \Closure|string|array $action
51
+     */
52
+    public $action;
53
+
54
+    /**
55
+     * The container instance used by the route.
56
+     * 
57
+     * @var \Syscodes\Container\Container $container
58
+     */
59
+    protected $container;
60
+
61
+    /**
62
+     * The controller instance.
63
+     * 
64
+     * @var string $controller
65
+     */
66
+    public $controller;
67
+
68
+    /**
69
+     * The default values for the route.
70
+     * 
71
+     * @var array $defaults
72
+     */
73
+    public $defaults = [];
74
+
75
+    /**
76
+     * Variable of HTTP method.
77
+     *  
78
+     * @var array|string $method
79
+     */
80
+    public $method;
81
+
82
+    /**
83
+     * The array of matched parameters.
84
+     * 
85
+     * @var array $parameters
86
+     */
87
+    public $parameters = [];
88
+
89
+    /**
90
+     * The parameter names for the route.
91
+     * 
92
+     * @var string|null $parameterNames
93
+     */
94
+    public $parameterNames;
95
+
96
+    /**
97
+     * Patterns that should be replaced.
98
+     *
99
+     * @var array $patterns 
100
+     */
101
+    public $patterns = [
102
+        '~/~'                    =>  '\/',               // Slash
103
+        '~{an:[^\/{}]+}~'        => '([0-9a-zA-Z]++)',   // Placeholder accepts alphabetic and numeric chars
104
+        '~{n:[^\/{}]+}~'         => '([0-9]++)',         // Placeholder accepts only numeric
105
+        '~{a:[^\/{}]+}~'         => '([a-zA-Z]++)',      // Placeholder accepts only alphabetic chars
106
+        '~{w:[^\/{}]+}~'         => '([0-9a-zA-Z-_]++)', // Placeholder accepts alphanumeric and underscore
107
+        '~{\*:[^\/{}]+}~'        => '(.++)',             // Placeholder match rest of url
108
+        '~(\\\/)?{\?:[^\/{}]+}~' => '\/?([^\/]*)',		 // Optional placeholder
109
+        '~{[^\/{}]+}~'           => '([^\/]++)'			 // Normal placeholder
110
+    ];
111
+
112
+    /**
113
+     * The URI pattern the route responds to.
114
+     *
115
+     * @var array $uri
116
+     */
117
+    public $uri = [];
118
+
119
+    /**
120
+     * Contains the arguments of the current route.
121
+     *
122
+     * @var array $where
123
+     */
124
+    public $wheres = [];
125
+
126
+    /**
127
+     * Constructor. Initialize route.
128
+     *
129
+     * @param  array|string|null  $method  (null by default)
130
+     * @param  string|null  $uri  (null by default)
131
+     * @param  \Closure|string|null  $action  (null by default)
132
+     *
133
+     * @return void
134
+     */
135
+    public function __construct($method = null, $uri = null, $action = null)
136
+    {
137
+        $this->uri = $uri;
138
+
139
+        // Set the method
140
+        $this->parseMethod($method);
141
+
142
+        // Set the action
143
+        $this->parseAction($action);
144
+
145
+        if (is_null($prefix = Arr::get($this->action, 'prefix')))
146
+        {
147
+            $this->prefix($prefix);
148
+        }
149
+    }
150
+
151
+    // Getters
152
+
153
+    /**
154
+     * Get the action of the current route.
155
+     *
156
+     * @return \Closure|string
157
+     */
158
+    public function getAction()
159
+    {
160
+        return $this->action;
161
+    }
162
+
163
+    /**
164
+     * Get the arguments of the current route.
165
+     *
166
+     * @return string
167
+     */
168
+    public function getArguments()
169
+    {
170
+        return $this->wheres;
171
+    }
172
+
173
+    /**
174
+     * Get the controller instance for the route.
175
+     * 
176
+     * @return mixed
177
+     */
178
+    public function getController()
179
+    {
180
+        if ( ! $this->controller)
181
+        {
182
+            $class = $this->parseControllerCallback()[0];
183 183
  
184
-			$this->controller = $this->container->make(ltrim($class, '\\'));
185
-		}
186
-
187
-		return $this->controller;
188
-	}
189
-
190
-	/**
191
-	 * Get the controller method used for the route.
192
-	 * 
193
-	 * @return string
194
-	 */
195
-	public function getControllerMethod()
196
-	{
197
-		return $this->parseControllerCallback()[1];
198
-	}
199
-
200
-	/**
201
-	 * Get the request method of the current route.
202
-	 *
203
-	 * @return array
204
-	 */
205
-	public function getMethod()
206
-	{
207
-		return $this->method;
208
-	}
209
-
210
-	/**
211
-	 * Get the url of the current route.
212
-	 *
213
-	 * @return string
214
-	 */
215
-	public function getName()
216
-	{
217
-		return $this->action['as'] ?? null;
218
-	}
219
-
220
-	/**
221
-	 * Get the url of the current route.
222
-	 *
223
-	 * @return string
224
-	 */
225
-	public function getRoute()
226
-	{
227
-		return $this->uri;
228
-	}
229
-
230
-	/**
231
-	 * Get or set the domain for the route.
232
-	 * 
233
-	 * @param  string|null  $domain  (null by default)
234
-	 * 
235
-	 * @return $this
236
-	 */
237
-	public function domain($domain = null)
238
-	{
239
-		if (is_null($domain))
240
-		{
241
-			return $this->getDomain();
242
-		}
243
-
244
-		$this->action['domain'] = $this->parseRoute($domain);
245
-
246
-		return $this;
247
-	}
248
-
249
-	/**
250
-	 * Get the domain defined for the route.
251
-	 * 
252
-	 * @return string|null
253
-	 */
254
-	public function getDomain()
255
-	{
256
-		return isset($this->action['domain'])
257
-				? str_replace(['http://', 'https://'], '', $this->action['domain'])
258
-				: null;
259
-	}
260
-
261
-	/**
262
-	 * Parse the controller.
263
-	 * 
264
-	 * @return array
265
-	 */
266
-	public function parseControllerCallback()
267
-	{
268
-		return Str::parseCallback($this->action['uses']);
269
-	}
184
+            $this->controller = $this->container->make(ltrim($class, '\\'));
185
+        }
186
+
187
+        return $this->controller;
188
+    }
189
+
190
+    /**
191
+     * Get the controller method used for the route.
192
+     * 
193
+     * @return string
194
+     */
195
+    public function getControllerMethod()
196
+    {
197
+        return $this->parseControllerCallback()[1];
198
+    }
199
+
200
+    /**
201
+     * Get the request method of the current route.
202
+     *
203
+     * @return array
204
+     */
205
+    public function getMethod()
206
+    {
207
+        return $this->method;
208
+    }
209
+
210
+    /**
211
+     * Get the url of the current route.
212
+     *
213
+     * @return string
214
+     */
215
+    public function getName()
216
+    {
217
+        return $this->action['as'] ?? null;
218
+    }
219
+
220
+    /**
221
+     * Get the url of the current route.
222
+     *
223
+     * @return string
224
+     */
225
+    public function getRoute()
226
+    {
227
+        return $this->uri;
228
+    }
229
+
230
+    /**
231
+     * Get or set the domain for the route.
232
+     * 
233
+     * @param  string|null  $domain  (null by default)
234
+     * 
235
+     * @return $this
236
+     */
237
+    public function domain($domain = null)
238
+    {
239
+        if (is_null($domain))
240
+        {
241
+            return $this->getDomain();
242
+        }
243
+
244
+        $this->action['domain'] = $this->parseRoute($domain);
245
+
246
+        return $this;
247
+    }
248
+
249
+    /**
250
+     * Get the domain defined for the route.
251
+     * 
252
+     * @return string|null
253
+     */
254
+    public function getDomain()
255
+    {
256
+        return isset($this->action['domain'])
257
+                ? str_replace(['http://', 'https://'], '', $this->action['domain'])
258
+                : null;
259
+    }
260
+
261
+    /**
262
+     * Parse the controller.
263
+     * 
264
+     * @return array
265
+     */
266
+    public function parseControllerCallback()
267
+    {
268
+        return Str::parseCallback($this->action['uses']);
269
+    }
270 270
 	
271
-	/**
272
-	 * Checks whether the route's action is a controller.
273
-	 * 
274
-	 * @return bool
275
-	 */
276
-	public function isControllerAction()
277
-	{
278
-		return is_string($this->action['uses']);
279
-	}
280
-
281
-	/**
282
-	 * Get the dispatcher for the route's controller.
283
-	 * 
284
-	 * @return \Syscodes\Controller\ControllerDispatcher
285
-	 */
286
-	private function controllerDispatcher()
287
-	{
288
-		return new ControllerDispatcher($this->container);
289
-	}
290
-
291
-	// Setters
271
+    /**
272
+     * Checks whether the route's action is a controller.
273
+     * 
274
+     * @return bool
275
+     */
276
+    public function isControllerAction()
277
+    {
278
+        return is_string($this->action['uses']);
279
+    }
280
+
281
+    /**
282
+     * Get the dispatcher for the route's controller.
283
+     * 
284
+     * @return \Syscodes\Controller\ControllerDispatcher
285
+     */
286
+    private function controllerDispatcher()
287
+    {
288
+        return new ControllerDispatcher($this->container);
289
+    }
290
+
291
+    // Setters
292 292
 	
293
-	/**
294
-	 * Run the route action and return the response.
295
-	 * 
296
-	 * @return mixed
297
-	 */
298
-	public function runResolver()
299
-	{
300
-		$this->container = $this->container ?: new Container;
301
-
302
-		try
303
-		{
304
-			if ($this->isControllerAction())
305
-			{
306
-				return $this->runResolverController();
307
-			}
308
-
309
-			return $this->runResolverCallable();
310
-		}
311
-		catch (HttpResponseException $e)
312
-		{
313
-			return $e->getResponse();
314
-		}
315
-	}
316
-
317
-	/**
318
-	 * Run the route action and return the response.
319
-	 *  
320
-	 * @return mixed
321
-	 */
322
-	protected function runResolverCallable()
323
-	{
324
-		$callable = $this->action['uses'];
325
-
326
-		return $callable(...array_values($this->resolveMethodDependencies(
327
-			$this->parametersWithouNulls(), new ReflectionFunction($this->action['uses'])
328
-		)));
329
-	}
330
-
331
-	/**
332
-	 * Run the route action and return the response.
333
-	 * 
334
-	 * @return mixed
335
-	 */
336
-	protected function runResolverController()
337
-	{
338
-		return $this->controllerDispatcher()->dispatch($this, $this->getController(), $this->getControllerMethod());
339
-	}
340
-
341
-	/**
342
-	 * Set the action.
343
-	 *
344
-	 * @param  \Closure|string  $action
345
-	 *
346
-	 * @return $this
347
-	 *
348
-	 * @throws \InvalidArgumentException
349
-	 */
350
-	public function parseAction($action)
351
-	{
352
-		if ( ! (is_object($action) && ($action instanceof Closure)) && ($action === null || $action === ''))
353
-		{
354
-			throw new InvalidArgumentException(__('route.actionClosureOrFunction'));
355
-		}
356
-
357
-		$this->action = RouteAction::parse($this->uri, $action);
358
-
359
-		return $this;
360
-	}
361
-
362
-	/**
363
-	 * Set the method of the current route.
364
-	 *
365
-	 * @param  array  $method
366
-	 *
367
-	 * @return string $this
368
-	 * 
369
-	 * @throws \InvalidArgumentException
370
-	 */
371
-	public function parseMethod($method)
372
-	{
373
-		if ($method === null || ! is_array($method) || empty($method))
374
-		{
375
-			throw new InvalidArgumentException(__('route.methodNotProvided'));
293
+    /**
294
+     * Run the route action and return the response.
295
+     * 
296
+     * @return mixed
297
+     */
298
+    public function runResolver()
299
+    {
300
+        $this->container = $this->container ?: new Container;
301
+
302
+        try
303
+        {
304
+            if ($this->isControllerAction())
305
+            {
306
+                return $this->runResolverController();
307
+            }
308
+
309
+            return $this->runResolverCallable();
310
+        }
311
+        catch (HttpResponseException $e)
312
+        {
313
+            return $e->getResponse();
314
+        }
315
+    }
316
+
317
+    /**
318
+     * Run the route action and return the response.
319
+     *  
320
+     * @return mixed
321
+     */
322
+    protected function runResolverCallable()
323
+    {
324
+        $callable = $this->action['uses'];
325
+
326
+        return $callable(...array_values($this->resolveMethodDependencies(
327
+            $this->parametersWithouNulls(), new ReflectionFunction($this->action['uses'])
328
+        )));
329
+    }
330
+
331
+    /**
332
+     * Run the route action and return the response.
333
+     * 
334
+     * @return mixed
335
+     */
336
+    protected function runResolverController()
337
+    {
338
+        return $this->controllerDispatcher()->dispatch($this, $this->getController(), $this->getControllerMethod());
339
+    }
340
+
341
+    /**
342
+     * Set the action.
343
+     *
344
+     * @param  \Closure|string  $action
345
+     *
346
+     * @return $this
347
+     *
348
+     * @throws \InvalidArgumentException
349
+     */
350
+    public function parseAction($action)
351
+    {
352
+        if ( ! (is_object($action) && ($action instanceof Closure)) && ($action === null || $action === ''))
353
+        {
354
+            throw new InvalidArgumentException(__('route.actionClosureOrFunction'));
355
+        }
356
+
357
+        $this->action = RouteAction::parse($this->uri, $action);
358
+
359
+        return $this;
360
+    }
361
+
362
+    /**
363
+     * Set the method of the current route.
364
+     *
365
+     * @param  array  $method
366
+     *
367
+     * @return string $this
368
+     * 
369
+     * @throws \InvalidArgumentException
370
+     */
371
+    public function parseMethod($method)
372
+    {
373
+        if ($method === null || ! is_array($method) || empty($method))
374
+        {
375
+            throw new InvalidArgumentException(__('route.methodNotProvided'));
376 376
 			
377
-		}
377
+        }
378 378
 
379
-		foreach ($method as $httpMethod) 
380
-		{
381
-			if ( ! in_array($httpMethod, ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD', 'ANY']))	
382
-			{
383
-				throw new InvalidArgumentException(__('route.methodNotAllowed'));
379
+        foreach ($method as $httpMethod) 
380
+        {
381
+            if ( ! in_array($httpMethod, ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD', 'ANY']))	
382
+            {
383
+                throw new InvalidArgumentException(__('route.methodNotAllowed'));
384 384
 				
385
-			}
386
-		}
387
-
388
-	    $this->method = $method;
389
-
390
-	    return $this;
391
-	}
392
-
393
-	/**
394
-	 * Set the route.
395
-	 *
396
-	 * @param  string  $uri
397
-	 *
398
-	 * @return string
399
-	 *
400
-	 * @throws  \InvalidArgumentException
401
-	 */
402
-	public function parseRoute($uri)
403
-	{
404
-		if ($uri === null) 
405
-		{
406
-			throw new InvalidArgumentException(__('route.uriNotProvided'));
407
-		}	
408
-
409
-		$this->uri = $this->parseRoutePath($uri);
410
-
411
-		return $this;
412
-	}
413
-
414
-	/**
415
-	 * Replace word patterns with regex in route uri.
416
-	 * 
417
-	 * @param  string  $uri
418
-	 * 
419
-	 * @return string
420
-	 */
421
-	protected function parseRoutePath($uri)
422
-	{
423
-		$uri = trim($uri, '\/?');
424
-		$uri = trim($uri, '\/');
385
+            }
386
+        }
387
+
388
+        $this->method = $method;
389
+
390
+        return $this;
391
+    }
392
+
393
+    /**
394
+     * Set the route.
395
+     *
396
+     * @param  string  $uri
397
+     *
398
+     * @return string
399
+     *
400
+     * @throws  \InvalidArgumentException
401
+     */
402
+    public function parseRoute($uri)
403
+    {
404
+        if ($uri === null) 
405
+        {
406
+            throw new InvalidArgumentException(__('route.uriNotProvided'));
407
+        }	
408
+
409
+        $this->uri = $this->parseRoutePath($uri);
410
+
411
+        return $this;
412
+    }
413
+
414
+    /**
415
+     * Replace word patterns with regex in route uri.
416
+     * 
417
+     * @param  string  $uri
418
+     * 
419
+     * @return string
420
+     */
421
+    protected function parseRoutePath($uri)
422
+    {
423
+        $uri = trim($uri, '\/?');
424
+        $uri = trim($uri, '\/');
425 425
 		
426
-		preg_match_all('/\{([\w\:]+?)\??\}/', $uri, $matches);
426
+        preg_match_all('/\{([\w\:]+?)\??\}/', $uri, $matches);
427 427
 		
428
-		foreach ($matches[1] as $match)
429
-		{
430
-			if (strpos($match, ':') === false)
431
-			{
432
-				continue;
433
-			}
428
+        foreach ($matches[1] as $match)
429
+        {
430
+            if (strpos($match, ':') === false)
431
+            {
432
+                continue;
433
+            }
434 434
 			
435
-			$pattern  = array_keys($this->patterns);
436
-			$replace  = array_values($this->patterns);
437
-			$segments = explode(':', trim($match, '{}?'));
435
+            $pattern  = array_keys($this->patterns);
436
+            $replace  = array_values($this->patterns);
437
+            $segments = explode(':', trim($match, '{}?'));
438 438
 			
439
-			$uri = strpos($match, ':') !== false
440
-					? preg_replace($pattern, $replace, $uri)
441
-					: str_replace($match, '{'.$segments[0].'}', $uri);
442
-		}
439
+            $uri = strpos($match, ':') !== false
440
+                    ? preg_replace($pattern, $replace, $uri)
441
+                    : str_replace($match, '{'.$segments[0].'}', $uri);
442
+        }
443 443
 		
444
-		return $uri;
445
-	}
446
-
447
-	/**
448
-	 * Add a prefix to the route URI.
449
-	 * 
450
-	 * @param  string  $prefix
451
-	 * 
452
-	 * @return $this
453
-	 */
454
-	public function prefix($prefix)
455
-	{
456
-		if ( ! empty($newPrefix = trim(rtrim($prefix, '/').'/'.ltrim($this->action['prefix'] ?? '', '/'), '/'))) 
457
-		{
458
-			$this->action['prefix'] = $newPrefix;
459
-		}
444
+        return $uri;
445
+    }
446
+
447
+    /**
448
+     * Add a prefix to the route URI.
449
+     * 
450
+     * @param  string  $prefix
451
+     * 
452
+     * @return $this
453
+     */
454
+    public function prefix($prefix)
455
+    {
456
+        if ( ! empty($newPrefix = trim(rtrim($prefix, '/').'/'.ltrim($this->action['prefix'] ?? '', '/'), '/'))) 
457
+        {
458
+            $this->action['prefix'] = $newPrefix;
459
+        }
460 460
 		
461
-		$uri = rtrim($prefix, '/').'/'.ltrim($this->uri, '/');
461
+        $uri = rtrim($prefix, '/').'/'.ltrim($this->uri, '/');
462 462
 		
463
-		return $this->parseRoute($uri !== '/' ? trim($uri, '/') : $uri);
464
-	}
465
-
466
-	/**
467
-	 * Set the action array for the route.
468
-	 * 
469
-	 * @param  array  $action
470
-	 * 
471
-	 * @return $this
472
-	 */
473
-	public function setAction(array $action)
474
-	{
475
-		$this->action = $action;
476
-
477
-		if (isset($this->action['domain']))
478
-		{
479
-			$this->domain($this->action['domain']);
480
-		}
463
+        return $this->parseRoute($uri !== '/' ? trim($uri, '/') : $uri);
464
+    }
465
+
466
+    /**
467
+     * Set the action array for the route.
468
+     * 
469
+     * @param  array  $action
470
+     * 
471
+     * @return $this
472
+     */
473
+    public function setAction(array $action)
474
+    {
475
+        $this->action = $action;
476
+
477
+        if (isset($this->action['domain']))
478
+        {
479
+            $this->domain($this->action['domain']);
480
+        }
481 481
 		
482
-		return $this;
483
-	}
484
-
485
-	/**
486
-	 * Set the name.
487
-	 *
488
-	 * @param  string  $name
489
-	 *
490
-	 * @return string
491
-	 */
492
-	public function name($name)
493
-	{
494
-		$this->action['as'] = isset($this->action['as']) ? $this->action['as'].$name : $name;
495
-
496
-		return $this;
497
-	}
498
-
499
-	/**
500
-	 * Determine whether the route's name matches the given patterns.
501
-	 * 
502
-	 * @param  mixed  ...$patterns
503
-	 * 
504
-	 * @return bool
505
-	 */
506
-	public function named(...$patterns)
507
-	{
508
-		if (is_null($routeName = $this->getName()))
509
-		{
510
-			return false;
511
-		}
512
-
513
-		foreach ($patterns as $pattern)
514
-		{
515
-			if (Str::is($pattern, $routeName))
516
-			{
517
-				return true;
518
-			}
519
-		}
520
-
521
-		return false;
522
-	}
523
-
524
-	/**
525
-	 * Set a default value for the route.
526
-	 * 
527
-	 * @param  string  $key
528
-	 * @param  mixed   $value
529
-	 * 
530
-	 * @return $this
531
-	 */
532
-	public function defaults($key, $value)
533
-	{
534
-		$this->defaults[$key] = $value;
535
-
536
-		return $this;
537
-	}
538
-
539
-	/**
540
-	 * Set a default values for the route.
541
-	 * 
542
-	 * @param  string  $defaults
543
-	 * 
544
-	 * @return $this
545
-	 */
546
-	public function setDefaults(array $defaults)
547
-	{
548
-		$this->defaults = $defaults;
549
-
550
-		return $this;
551
-	}
552
-
553
-	/**
554
-	 * Set the where.
555
-	 *
556
-	 * @param  array|string  $name
557
-	 * @param  string|null  $expression  (null by default)
558
-	 *
559
-	 * @return $this
560
-	 */
561
-	public function where($name, string $expression = null)
562
-	{
563
-		$wheres = is_array($name) ? $name : [$name => $expression];
482
+        return $this;
483
+    }
484
+
485
+    /**
486
+     * Set the name.
487
+     *
488
+     * @param  string  $name
489
+     *
490
+     * @return string
491
+     */
492
+    public function name($name)
493
+    {
494
+        $this->action['as'] = isset($this->action['as']) ? $this->action['as'].$name : $name;
495
+
496
+        return $this;
497
+    }
498
+
499
+    /**
500
+     * Determine whether the route's name matches the given patterns.
501
+     * 
502
+     * @param  mixed  ...$patterns
503
+     * 
504
+     * @return bool
505
+     */
506
+    public function named(...$patterns)
507
+    {
508
+        if (is_null($routeName = $this->getName()))
509
+        {
510
+            return false;
511
+        }
512
+
513
+        foreach ($patterns as $pattern)
514
+        {
515
+            if (Str::is($pattern, $routeName))
516
+            {
517
+                return true;
518
+            }
519
+        }
520
+
521
+        return false;
522
+    }
523
+
524
+    /**
525
+     * Set a default value for the route.
526
+     * 
527
+     * @param  string  $key
528
+     * @param  mixed   $value
529
+     * 
530
+     * @return $this
531
+     */
532
+    public function defaults($key, $value)
533
+    {
534
+        $this->defaults[$key] = $value;
535
+
536
+        return $this;
537
+    }
538
+
539
+    /**
540
+     * Set a default values for the route.
541
+     * 
542
+     * @param  string  $defaults
543
+     * 
544
+     * @return $this
545
+     */
546
+    public function setDefaults(array $defaults)
547
+    {
548
+        $this->defaults = $defaults;
549
+
550
+        return $this;
551
+    }
552
+
553
+    /**
554
+     * Set the where.
555
+     *
556
+     * @param  array|string  $name
557
+     * @param  string|null  $expression  (null by default)
558
+     *
559
+     * @return $this
560
+     */
561
+    public function where($name, string $expression = null)
562
+    {
563
+        $wheres = is_array($name) ? $name : [$name => $expression];
564 564
 		
565
-		foreach ($wheres as $name => $expression)
566
-		{
567
-			$this->wheres[$name] = $expression;
568
-		}
569
-
570
-		return $this;
571
-	}
572
-
573
-	/**
574
-	 * Bind the route to a given request for execution.
575
-	 * 
576
-	 * @param  \Syscodes\Http\Request  $request
577
-	 * 
578
-	 * @return $this
579
-	 */
580
-	public function bind(Request $request)
581
-	{
582
-		$this->parameters = (new RouteParamBinding($this))->parameters($request);
583
-
584
-		return $this;
585
-	}
586
-
587
-	/**
588
-	 * Get all of the parameter names for the route.
589
-	 * 
590
-	 * @return array
591
-	 */
592
-	public function parameterNames()
593
-	{
594
-		if (isset($this->parameterNames))
595
-		{
596
-			return $this->parameterNames;
597
-		}
598
-
599
-		return $this->parameterNames = $this->compileParamNames();
600
-	}
601
-
602
-	/**
603
-	 * Get the parameter names for the route.
604
-	 * 
605
-	 * @return array
606
-	 */
607
-	protected function compileParamNames()
608
-	{
609
-		preg_match_all('~[^\/\{(.*?)\}]~', $this->domain().$this->uri, $matches);
610
-
611
-		return array_map(function ($match) {
612
-			return trim($match, '?');
613
-		}, $matches[0]);
614
-	}
615
-
616
-	/**
617
-	 * Get a given parameter from the route.
618
-	 * 
619
-	 * @param  string  $name
620
-	 * @param  mixed  $default  (null by default)
621
-	 * 
622
-	 * @return array
623
-	 */
624
-	public function parameter($name, $default = null)
625
-	{
626
-		return Arr::get($this->parameters(), $name, $default);
627
-	}
628
-
629
-	/**
630
-	 * Set a parameter to the given value.
631
-	 * 
632
-	 * @param  string  $name
633
-	 * @param  mixed  $value
634
-	 * 
635
-	 * @return array
636
-	 */
637
-	public function setParameter($name, $value)
638
-	{
639
-		$this->parameters();
640
-
641
-		$this->parameters[$name] = $value;
642
-	}
643
-
644
-	/**
645
-	 * Get the key / value list of parameters without null values.
646
-	 * 
647
-	 * @return array
648
-	 */
649
-	public function parametersWithouNulls()
650
-	{
651
-		return array_filter($this->parameters(), function ($parameter) {
652
-			return ! is_null($parameter);
653
-		});
654
-	}
655
-
656
-	/**
657
-	 * Get the key / value list of parameters for the route.
658
-	 * 
659
-	 * @return array
660
-	 */
661
-	public function parameters()
662
-	{
663
-		if (isset($this->parameters))
664
-		{
665
-			return $this->parameters;
666
-		}
667
-
668
-		throw new LogicException('The route is not bound.');
669
-	}
670
-
671
-	/**
672
-	 * Determine if the route only responds to HTTP requests.
673
-	 * 
674
-	 * @return bool
675
-	 */
676
-	public function httpOnly()
677
-	{
678
-		return in_array('http', $this->action, true);
679
-	}
680
-
681
-	/**
682
-	 * Determine if the route only responds to HTTPS requests.
683
-	 * 
684
-	 * @return bool
685
-	 */
686
-	public function httpsOnly()
687
-	{
688
-		return $this->secure();
689
-	}
690
-
691
-	/**
692
-	 * Determine if the route only responds to HTTPS requests.
693
-	 * 
694
-	 * @return bool
695
-	 */
696
-	public function secure()
697
-	{
698
-		return in_array('https', $this->action, true);
699
-	}
700
-
701
-	/**
702
-	 * Set the container instance on the route.
703
-	 * 
704
-	 * @param  \Syscodes\Container\Container  $container
705
-	 * 
706
-	 * @return $this
707
-	 */
708
-	public function setContainer(Container $container)
709
-	{
710
-		$this->container = $container;
711
-
712
-		return $this;
713
-	}
714
-
715
-	/**
716
-	 * Dynamically access route parameters.
717
-	 * 
718
-	 * @param  string  $key
719
-	 * 
720
-	 * @return mixed
721
-	 */
722
-	public function __get($key)
723
-	{
724
-		return $this->parameter($key);
725
-	}
565
+        foreach ($wheres as $name => $expression)
566
+        {
567
+            $this->wheres[$name] = $expression;
568
+        }
569
+
570
+        return $this;
571
+    }
572
+
573
+    /**
574
+     * Bind the route to a given request for execution.
575
+     * 
576
+     * @param  \Syscodes\Http\Request  $request
577
+     * 
578
+     * @return $this
579
+     */
580
+    public function bind(Request $request)
581
+    {
582
+        $this->parameters = (new RouteParamBinding($this))->parameters($request);
583
+
584
+        return $this;
585
+    }
586
+
587
+    /**
588
+     * Get all of the parameter names for the route.
589
+     * 
590
+     * @return array
591
+     */
592
+    public function parameterNames()
593
+    {
594
+        if (isset($this->parameterNames))
595
+        {
596
+            return $this->parameterNames;
597
+        }
598
+
599
+        return $this->parameterNames = $this->compileParamNames();
600
+    }
601
+
602
+    /**
603
+     * Get the parameter names for the route.
604
+     * 
605
+     * @return array
606
+     */
607
+    protected function compileParamNames()
608
+    {
609
+        preg_match_all('~[^\/\{(.*?)\}]~', $this->domain().$this->uri, $matches);
610
+
611
+        return array_map(function ($match) {
612
+            return trim($match, '?');
613
+        }, $matches[0]);
614
+    }
615
+
616
+    /**
617
+     * Get a given parameter from the route.
618
+     * 
619
+     * @param  string  $name
620
+     * @param  mixed  $default  (null by default)
621
+     * 
622
+     * @return array
623
+     */
624
+    public function parameter($name, $default = null)
625
+    {
626
+        return Arr::get($this->parameters(), $name, $default);
627
+    }
628
+
629
+    /**
630
+     * Set a parameter to the given value.
631
+     * 
632
+     * @param  string  $name
633
+     * @param  mixed  $value
634
+     * 
635
+     * @return array
636
+     */
637
+    public function setParameter($name, $value)
638
+    {
639
+        $this->parameters();
640
+
641
+        $this->parameters[$name] = $value;
642
+    }
643
+
644
+    /**
645
+     * Get the key / value list of parameters without null values.
646
+     * 
647
+     * @return array
648
+     */
649
+    public function parametersWithouNulls()
650
+    {
651
+        return array_filter($this->parameters(), function ($parameter) {
652
+            return ! is_null($parameter);
653
+        });
654
+    }
655
+
656
+    /**
657
+     * Get the key / value list of parameters for the route.
658
+     * 
659
+     * @return array
660
+     */
661
+    public function parameters()
662
+    {
663
+        if (isset($this->parameters))
664
+        {
665
+            return $this->parameters;
666
+        }
667
+
668
+        throw new LogicException('The route is not bound.');
669
+    }
670
+
671
+    /**
672
+     * Determine if the route only responds to HTTP requests.
673
+     * 
674
+     * @return bool
675
+     */
676
+    public function httpOnly()
677
+    {
678
+        return in_array('http', $this->action, true);
679
+    }
680
+
681
+    /**
682
+     * Determine if the route only responds to HTTPS requests.
683
+     * 
684
+     * @return bool
685
+     */
686
+    public function httpsOnly()
687
+    {
688
+        return $this->secure();
689
+    }
690
+
691
+    /**
692
+     * Determine if the route only responds to HTTPS requests.
693
+     * 
694
+     * @return bool
695
+     */
696
+    public function secure()
697
+    {
698
+        return in_array('https', $this->action, true);
699
+    }
700
+
701
+    /**
702
+     * Set the container instance on the route.
703
+     * 
704
+     * @param  \Syscodes\Container\Container  $container
705
+     * 
706
+     * @return $this
707
+     */
708
+    public function setContainer(Container $container)
709
+    {
710
+        $this->container = $container;
711
+
712
+        return $this;
713
+    }
714
+
715
+    /**
716
+     * Dynamically access route parameters.
717
+     * 
718
+     * @param  string  $key
719
+     * 
720
+     * @return mixed
721
+     */
722
+    public function __get($key)
723
+    {
724
+        return $this->parameter($key);
725
+    }
726 726
 }
727 727
\ No newline at end of file
Please login to merge, or discard this patch.
src/components/Console/Cli.php 1 patch
Indentation   +758 added lines, -758 removed lines patch added patch discarded remove patch
@@ -34,773 +34,773 @@
 block discarded – undo
34 34
  */
35 35
 class Cli
36 36
 {
37
-	/**
38
- 	 * Background color identifier.
39
- 	 *
40
- 	 * @var array $backgroundColors
41
- 	 */
42
- 	protected static $backgroundColors = [
43
- 		'black'      => '40',
44
- 		'red'        => '41',
45
- 		'green'      => '42',
46
- 		'yellow'     => '43',
47
- 		'blue'       => '44',
48
- 		'magenta'    => '45',
49
- 		'cyan'       => '46',
50
- 		'light_gray' => '47'
51
- 	];
52
-
53
-	/**
54
-	 * Foreground color identifier.
55
- 	 *
56
- 	 * @var array $foregroundColors
57
-	 */
58
-	protected static $foregroundColors = [
59
-		'black'         => '0;30',
60
-		'dark_gray'     => '1;30',
61
-		'blue'          => '0;34',
62
-		'dark_blue'     => '1;34',
63
-		'light_blue'    => '1;34',
64
-		'green'         => '0;32',
65
-		'light_green'   => '1;32',
66
-		'cyan'          => '0;36', 
67
-		'light_cyan'    => '1;36',
68
-		'red'           => '0;31',
69
-		'light_red'     => '1;31',
70
-		'purple'        => '0;35',
71
-		'light_purple'  => '1;35',
72
-		'light_yellow'  => '0;33',
73
-		'yellow'        => '1;33',
74
-		'light_gray'    => '0;37',
75
-		'white'         => '1;37'
76
- 	];
77
-
78
-	/**
79
-	 * Indicates that you do not use any color for foreground or background.
80
-	 *
81
-	 * @var bool $noColor
82
-	 */
83
-	public static $noColor = false;
84
-
85
-	/**
86
-	 * String of arguments to be used in console.
87
-	 *
88
-	 * @var array $options
89
-	 */
90
-	protected static $options = [];
91
-
92
-	/**
93
-	 * Readline Support for command line.
94
-	 *
95
-	 * @var bool $readlineSupport
96
-	 */
97
-	public static $readlineSupport = false;
98
-
99
-	/**
100
-	 * List of array segments.
101
-	 *
102
-	 * @var array $segments
103
-	 */
104
-	protected static $segments = [];
105
-
106
- 	/**
107
- 	 * The standar STDERR is where the application writes its error messages.
108
- 	 *
109
- 	 * @var string $stderr 
110
- 	 */
111
- 	protected static $stderr;
112
-
113
- 	/**
114
- 	 * The estandar STDOUT is where the application records its output messages.
115
- 	 *
116
- 	 * @var string $stdout
117
- 	 */
118
- 	protected static $stdout;
119
-
120
- 	/**
121
-	 * Message that tells the user that he is waiting to receive an order.
122
-	 *
123
-	 * @var string $waitMsg
124
-	 */
125
-	public static $waitMsg = 'Press any key to continue...';
126
-
127
-	/**
128
-	 * Static constructor. Parses all the CLI params.
129
-	 * 
130
-	 * @return string
131
-	 * 
132
-	 * @uses   \Syscodes\Contracts\Core\Lenevor
133
-	 * 
134
-	 * @throws \Exception
135
-	 */
136
- 	public static function initialize(Lenevor $core)
137
- 	{
138
- 		if ( ! $core->initCli())
139
- 		{
140
-			throw new Exception('Cli class cannot be used outside of the command line');
141
- 		}
142
-
143
- 		// Readline is an extension for PHP that makes interactive the command console
144
- 		static::$readlineSupport = extension_loaded('readline');
145
-
146
- 		// clear segments & options to keep testing clean
147
- 		static::$options  = [];
148
- 		static::$segments = [];
149
-
150
- 		static::parseCommandLine();
151
-
152
- 		// Writes its error messages
153
- 		static::$stderr = STDERR;
154
-
155
- 		// Records its output messages
156
- 		static::$stdout = STDOUT;
157
- 	}
158
-
159
- 	/**
160
- 	 * Beeps a certain number of times.
161
-	 *
162
-	 * @param  int  $num  The number of times to beep
163
-	 *
164
- 	 * @return int
165
- 	 */
166
- 	public static function bell(int $num = 1)
167
- 	{
168
- 		echo str_repeat("\x07", $num);
169
- 	}
170
-
171
- 	/**
172
- 	 * Clears the screen of output.
173
- 	 *
174
- 	 * @return void
175
- 	 */
176
- 	public static function clearScreen()
177
- 	{
178
- 		static::isWindows() 
179
-
180
- 			// Windows doesn't work for this, but their terminal is tiny so shove this in
181
- 			? static::newLine(40)
182
-
183
- 			// Anything with a flair of Unix will handle these magic characters
184
- 			: fwrite(static::$stdout, chr(27)."[H".chr(27)."[2J");
185
- 	}
186
-
187
- 	/**
188
- 	 * Returns the given text with the correct color codes for a foreground and
189
-	 * optionally a background color.
190
- 	 *
191
- 	 * @param  string  $text  The text to color
192
- 	 * @param  string  $foreground  The foreground color
193
- 	 * @param  string  $background  The background color
194
- 	 * @param  string  $format  Other formatting to apply. Currently only 'underline' is understood
195
- 	 *
196
- 	 * @return string  The color coded string
197
- 	 *
198
- 	 * @throws \Syscodes\Core\Exceptions\LenevorException
199
- 	 */
200
- 	public static function color(string $text, string $foreground, string $background = null, string $format = null)
201
- 	{
202
- 		if (static::$noColor)
203
- 		{
204
- 			return $text;
205
- 		}
206
-
207
- 		if ( ! Arr::exists(static::$foregroundColors, $foreground))
208
- 		{
209
- 			throw new LenevorException(static::error("Invalid CLI foreground color: {$foreground}."));
210
- 		}
211
-
212
- 		if ( $background !== null && ! Arr::exists(static::$backgroundColors, $background))
213
- 		{
214
- 			throw new LenevorException(static::error("Invalid CLI background color: {$background}."));
215
- 		}
216
-
217
- 		$string = "\033[".static::$foregroundColors[$foreground]."m";
218
-
219
- 		if ($background !== null)
220
- 		{
221
- 			$string .= "\033[".static::$backgroundColors[$background]."m";
222
- 		}
223
-
224
- 		if ($format === 'underline')
225
- 		{
226
- 			$string .= "\033[4m";
227
- 		}
228
-
229
- 		$string .= $text."\033[0m";
230
-
231
- 		return $string;
232
- 	}
233
-
234
- 	/**
235
- 	 * Get the number of characters in a string.
236
- 	 *
237
- 	 * @param  string  $string
238
- 	 *
239
- 	 * @return int
240
- 	 */
241
- 	public static function strlen(?string $string)
242
- 	{
243
- 		if (is_null($string))
244
- 		{
245
- 			return 0;
246
- 		}
247
-
248
- 		foreach (static::$foregroundColors as $color)
249
- 		{
250
- 			$string = strtr($string, ["\033[".$color.'m' => '']);
251
- 		}
252
-
253
- 		foreach (static::$backgroundColors as $color)
254
- 		{
255
- 			$string = strtr($string, ["\033[".$color.'m' => '']);
256
- 		}
257
-
258
- 		$string = strtr($string, ["\033[4m" => '', "\033[0m" => '']);
259
-
260
- 		return mb_strlen($string);
261
- 	}
262
-
263
- 	/**
264
- 	 * Outputs an error to the CLI using STDERR instead of STDOUT.
265
- 	 *
266
- 	 * @param  string|array  $text  The text to output, or array of errors
267
- 	 * @param  string  $foreground  The foreground color
268
- 	 * @param  string|null  $background  the background color
269
- 	 *
270
- 	 * @return string
271
- 	 */
272
- 	public static function error(string $text = '', string $foreground = 'light_red', string $background = null)
273
- 	{
274
-		if (is_array($text))
275
-		{
276
-			$text = implode(PHP_EOL, $text);
277
-		}
37
+    /**
38
+     * Background color identifier.
39
+     *
40
+     * @var array $backgroundColors
41
+     */
42
+        protected static $backgroundColors = [
43
+            'black'      => '40',
44
+            'red'        => '41',
45
+            'green'      => '42',
46
+            'yellow'     => '43',
47
+            'blue'       => '44',
48
+            'magenta'    => '45',
49
+            'cyan'       => '46',
50
+            'light_gray' => '47'
51
+        ];
52
+
53
+    /**
54
+     * Foreground color identifier.
55
+     *
56
+     * @var array $foregroundColors
57
+     */
58
+    protected static $foregroundColors = [
59
+        'black'         => '0;30',
60
+        'dark_gray'     => '1;30',
61
+        'blue'          => '0;34',
62
+        'dark_blue'     => '1;34',
63
+        'light_blue'    => '1;34',
64
+        'green'         => '0;32',
65
+        'light_green'   => '1;32',
66
+        'cyan'          => '0;36', 
67
+        'light_cyan'    => '1;36',
68
+        'red'           => '0;31',
69
+        'light_red'     => '1;31',
70
+        'purple'        => '0;35',
71
+        'light_purple'  => '1;35',
72
+        'light_yellow'  => '0;33',
73
+        'yellow'        => '1;33',
74
+        'light_gray'    => '0;37',
75
+        'white'         => '1;37'
76
+        ];
77
+
78
+    /**
79
+     * Indicates that you do not use any color for foreground or background.
80
+     *
81
+     * @var bool $noColor
82
+     */
83
+    public static $noColor = false;
84
+
85
+    /**
86
+     * String of arguments to be used in console.
87
+     *
88
+     * @var array $options
89
+     */
90
+    protected static $options = [];
91
+
92
+    /**
93
+     * Readline Support for command line.
94
+     *
95
+     * @var bool $readlineSupport
96
+     */
97
+    public static $readlineSupport = false;
98
+
99
+    /**
100
+     * List of array segments.
101
+     *
102
+     * @var array $segments
103
+     */
104
+    protected static $segments = [];
105
+
106
+        /**
107
+         * The standar STDERR is where the application writes its error messages.
108
+         *
109
+         * @var string $stderr 
110
+         */
111
+        protected static $stderr;
112
+
113
+        /**
114
+         * The estandar STDOUT is where the application records its output messages.
115
+         *
116
+         * @var string $stdout
117
+         */
118
+        protected static $stdout;
119
+
120
+        /**
121
+         * Message that tells the user that he is waiting to receive an order.
122
+         *
123
+         * @var string $waitMsg
124
+         */
125
+    public static $waitMsg = 'Press any key to continue...';
126
+
127
+    /**
128
+     * Static constructor. Parses all the CLI params.
129
+     * 
130
+     * @return string
131
+     * 
132
+     * @uses   \Syscodes\Contracts\Core\Lenevor
133
+     * 
134
+     * @throws \Exception
135
+     */
136
+        public static function initialize(Lenevor $core)
137
+        {
138
+            if ( ! $core->initCli())
139
+            {
140
+            throw new Exception('Cli class cannot be used outside of the command line');
141
+            }
142
+
143
+            // Readline is an extension for PHP that makes interactive the command console
144
+            static::$readlineSupport = extension_loaded('readline');
145
+
146
+            // clear segments & options to keep testing clean
147
+            static::$options  = [];
148
+            static::$segments = [];
149
+
150
+            static::parseCommandLine();
151
+
152
+            // Writes its error messages
153
+            static::$stderr = STDERR;
154
+
155
+            // Records its output messages
156
+            static::$stdout = STDOUT;
157
+        }
158
+
159
+        /**
160
+         * Beeps a certain number of times.
161
+         *
162
+         * @param  int  $num  The number of times to beep
163
+         *
164
+         * @return int
165
+         */
166
+        public static function bell(int $num = 1)
167
+        {
168
+            echo str_repeat("\x07", $num);
169
+        }
170
+
171
+        /**
172
+         * Clears the screen of output.
173
+         *
174
+         * @return void
175
+         */
176
+        public static function clearScreen()
177
+        {
178
+            static::isWindows() 
179
+
180
+                // Windows doesn't work for this, but their terminal is tiny so shove this in
181
+             ? static::newLine(40)
182
+
183
+                // Anything with a flair of Unix will handle these magic characters
184
+             : fwrite(static::$stdout, chr(27)."[H".chr(27)."[2J");
185
+        }
186
+
187
+        /**
188
+         * Returns the given text with the correct color codes for a foreground and
189
+         * optionally a background color.
190
+         *
191
+         * @param  string  $text  The text to color
192
+         * @param  string  $foreground  The foreground color
193
+         * @param  string  $background  The background color
194
+         * @param  string  $format  Other formatting to apply. Currently only 'underline' is understood
195
+         *
196
+         * @return string  The color coded string
197
+         *
198
+         * @throws \Syscodes\Core\Exceptions\LenevorException
199
+         */
200
+        public static function color(string $text, string $foreground, string $background = null, string $format = null)
201
+        {
202
+            if (static::$noColor)
203
+            {
204
+                return $text;
205
+            }
206
+
207
+            if ( ! Arr::exists(static::$foregroundColors, $foreground))
208
+            {
209
+                throw new LenevorException(static::error("Invalid CLI foreground color: {$foreground}."));
210
+            }
211
+
212
+            if ( $background !== null && ! Arr::exists(static::$backgroundColors, $background))
213
+            {
214
+                throw new LenevorException(static::error("Invalid CLI background color: {$background}."));
215
+            }
216
+
217
+            $string = "\033[".static::$foregroundColors[$foreground]."m";
218
+
219
+            if ($background !== null)
220
+            {
221
+                $string .= "\033[".static::$backgroundColors[$background]."m";
222
+            }
223
+
224
+            if ($format === 'underline')
225
+            {
226
+                $string .= "\033[4m";
227
+            }
228
+
229
+            $string .= $text."\033[0m";
230
+
231
+            return $string;
232
+        }
233
+
234
+        /**
235
+         * Get the number of characters in a string.
236
+         *
237
+         * @param  string  $string
238
+         *
239
+         * @return int
240
+         */
241
+        public static function strlen(?string $string)
242
+        {
243
+            if (is_null($string))
244
+            {
245
+                return 0;
246
+            }
247
+
248
+            foreach (static::$foregroundColors as $color)
249
+            {
250
+                $string = strtr($string, ["\033[".$color.'m' => '']);
251
+            }
252
+
253
+            foreach (static::$backgroundColors as $color)
254
+            {
255
+                $string = strtr($string, ["\033[".$color.'m' => '']);
256
+            }
257
+
258
+            $string = strtr($string, ["\033[4m" => '', "\033[0m" => '']);
259
+
260
+            return mb_strlen($string);
261
+        }
262
+
263
+        /**
264
+         * Outputs an error to the CLI using STDERR instead of STDOUT.
265
+         *
266
+         * @param  string|array  $text  The text to output, or array of errors
267
+         * @param  string  $foreground  The foreground color
268
+         * @param  string|null  $background  the background color
269
+         *
270
+         * @return string
271
+         */
272
+        public static function error(string $text = '', string $foreground = 'light_red', string $background = null)
273
+        {
274
+        if (is_array($text))
275
+        {
276
+            $text = implode(PHP_EOL, $text);
277
+        }
278 278
 		
279
-		if ($foreground || $background)
280
-		{
281
-			$text = static::color($text, $foreground, $background);
282
-		}
279
+        if ($foreground || $background)
280
+        {
281
+            $text = static::color($text, $foreground, $background);
282
+        }
283 283
 		
284
-		fwrite(static::$stderr, $text.PHP_EOL);
285
-	}
286
-
287
-	/**
288
-	 * Attempts to determine the width of the viewable CLI window.
289
-	 *
290
-	 * @param  int  $default
291
-	 *
292
-	 * @return int
293
-	 */
294
-	public static function getWidth(int $default = 80)
295
-	{
296
-		if (static::isWindows() || (int) shell_exec('tput cols') === 0)
297
-		{
298
-			return $default;
299
-		}
300
-
301
-		return (int) shell_exec('tput cols');
302
-	}
303
-
304
-	/**
305
-	 * Attempts to determine the height of the viewable CLI window.
306
-	 *
307
-	 * @param  int  $default
308
-	 *
309
-	 * @return int
310
-	 */
311
-	public static function getHeight(int $default = 32)
312
-	{
313
-		if (static::isWindows())
314
-		{
315
-			return $default;
316
-		}
317
-
318
-		return (int) shell_exec('tput lines');
319
-	}
320
-
321
-	/**
322
-	 * Takes a string and writes it to the command line, wrapping to a maximum width. 
323
-	 * If no maximum width is specified, will wrap to the window's max.
324
-	 *
325
-	 * @param  string  $string  (null by default)
326
-	 * @param  int  $max  (0 by default)
327
-	 * @param  int $padLeft  (0 by default)
328
-	 *
329
-	 * @return string
330
-	 */
331
-	public static function wrap(string $string = null, int $max = 0, int $padLeft = 0)
332
-	{
333
-		if (empty($string))
334
-		{
335
-			return '';
336
-		}
337
-
338
-		if ($max === 0)
339
-		{
340
-			$max = static::getWidth();
341
-		}
342
-
343
-		if (static::getWidth() < $max)
344
-		{
345
-			$max = static::getWidth();
346
-		}
347
-
348
-		$max = $max - $padLeft;
349
-
350
-		$lines = wordwrap($string, $max);
351
-
352
-		if ($pad_left > 0)
353
-		{
354
-			$lines = explode(PHP_EOL, $lines);
355
-
356
-			$first = true;
357
-
358
-			array_walk ($lines, function (&$line, $index) use ($pad_left, &$first) {
359
-
360
-				if ( ! $first)
361
-				{
362
-					$line = str_repeat(' ', $pad_left) . $line;
363
-				}
364
-				else
365
-				{
366
-					$first = false;
367
-				}
368
-
369
-			});
370
-
371
-			$lines = implode(PHP_EOL, $lines);
372
-		}
373
-
374
-		return $lines;
375
-	}
376
-
377
- 	/**
378
- 	 * Get input from the shell, using readline or the standard STDIN.
379
- 	 *
380
- 	 * @param  string|int  $prefix  The name of the option (int if unnamed)
381
- 	 *
382
- 	 * @return string
383
- 	 */
384
- 	public static function input($prefix = '')
385
- 	{
386
- 		if (static::$readlineSupport)
387
- 		{
388
- 			return readline($prefix);
389
- 		}
390
-
391
- 		echo $prefix;
392
-
393
- 		return fgets(STDIN);
394
- 	}
395
-
396
- 	/**
397
- 	 * If operating system === windows.
398
- 	 * 
399
- 	 * @return string
400
- 	 */
401
- 	public static function isWindows()
402
- 	{
403
- 		return 'win' === strtolower(substr(php_uname("s"), 0, 3));
404
- 	}
405
-
406
- 	/**
407
- 	 * Enter a number of empty lines.
408
- 	 * 
409
- 	 * @param  int  $num  Number of lines to output
410
- 	 *
411
- 	 * @return void
412
- 	 */
413
- 	public static function newLine(int $num = 1)
414
- 	{
415
- 		for ($i = 0; $i < $num; $i++)
416
- 		{			
417
- 			static::write();
418
- 		}
419
- 	}
420
-
421
- 	/**
422
-	 * Returns the option with the given name. You can also give the option number.
423
-	 *
424
-	 * @param  string|int  $name  The name of the option (int if unnamed)
425
-	 * @param  mixed  $default  The value to return if the option is not defined
426
-	 *
427
-	 * @return mixed
428
-	 * 
429
-	 * @uses   \Syscodes\Contract\Core\Lenevor
430
-	 */
431
- 	public static function option($name, $default = null)
432
- 	{
433
- 		if ( ! isset(static::$options[$name]))
434
- 		{
435
- 			return Lenevor::value($default);
436
- 		}
437
-
438
- 		return static::$options[$name];
439
-	}
440
-
441
-	/**
442
-	 * Parses the command line it was called from and collects all
443
-	 * options and valid segments.
444
-	 * 
445
-	 * @return bool
446
-	 */
447
-	protected static function parseCommandLine()
448
-	{
449
-		$options = false;
450
-
451
-		for ($i = 1; $i < $_SERVER['argc']; $i++)
452
-		{
453
-			if ( ! $options && mb_strpos($_SERVER['argv'][$i], '-') === false)
454
-			{
455
-				static::$segments[] = $_SERVER['argv'][$i];
456
-
457
-				continue;
458
-			}
459
-
460
-			$options = true;
461
-
462
-			$args  = str_replace('-', '', $_SERVER['argv'][$i]);
463
-			$value = null;
464
-
465
-			if (isset($_SERVER['argv'][$i + 1]) && mb_strpos($_SERVER['argv'][$i + 1], '-') !== 0)
466
-			{
467
-				$value = $_SERVER['argv'][$i + 1];
468
-				$i++;
469
-			}
470
-
471
-			static::$options[$args] = $value;
472
-
473
-			$options = false;
474
-		}
475
-	}
476
-
477
-	/**
478
-	 * Returns the command line string portions of the arguments, minus
479
-	 * any options, as a string.
480
-	 *
481
-	 * @return string
482
-	 */
483
-	public static function getURI()
484
-	{
485
-		return implode('/', static::$segments);
486
-	}
487
-
488
-	/**
489
-	 * Returns an individual segment.
490
-	 *
491
-	 * @param  int  $index
492
-	 * 
493
-	 * @return mixed|null
494
-	 */
495
-	public static function getSegment(int $index)
496
-	{
497
-		if ( ! isset(static::$segments[$index - 1]))
498
-		{
499
-			return null;
500
-		}
501
-
502
-		return static::$segments[$index - 1];
503
-	}
504
-
505
-	/**
506
-	 * Returns the raw array of segments found.
507
-	 *
508
-	 * @return array
509
-	 */
510
-	public static function getSegments()
511
-	{
512
-		return static::$segments;
513
-	}
514
-
515
- 	/**
516
- 	 * Asks the user for input.  This can have either 1 or 2 arguments.
517
-	 *
518
-	 * Usage:
519
-	 *
520
-	 * // Waits for any key press
521
-	 * Cli::prompt();
522
-	 *
523
-	 * // Takes any input
524
-	 * $color = Cli::prompt('What is your favorite color?');
525
-	 *
526
-	 * // Takes any input, but offers default
527
-	 * $color = Cli::prompt('What is your favourite color?', 'white');
528
-	 *
529
-	 * // Will only accept the options in the array
530
-	 * $ready = Cli::prompt('Are you ready?', array('y','n'));
531
-	 *
532
-	 * @return string The user input
533
-	 */
534
- 	public static function prompt()
535
- 	{
536
- 		$args = func_get_args();
537
-
538
-		$options = [];
539
-		$output  = '';
540
-		$default = null;
541
-
542
-		// How many we got
543
-		$arg_count = count($args);
544
-
545
-		// Is the last argument a boolean? True means required
546
-		$required = end($args) === true;
547
-
548
-		// Reduce the argument count if required was passed, we don't care about that anymore
549
-		$required === true and --$arg_count;
550
-
551
-		// This method can take a few crazy combinations of arguments, so lets work it out
552
-		switch ($arg_count)
553
-		{
554
-			case 2:
555
-
556
-				// E.g: $ready = Cli::prompt('Are you ready?', ['y','n']);
557
-				if (is_array($args[1]))
558
-				{
559
-					list($output, $options) = $args;
560
-				}
561
-
562
-				// E.g: $color = Cli::prompt('What is your favourite color?', 'white');
563
-				elseif (is_string($args[1]))
564
-				{
565
-					list($output, $default) = $args;
566
-				}
567
-
568
-			break;
569
-
570
-			case 1:
571
-
572
-				// No question (probably been asked already) so just show options
573
-				// E.g: $ready = Cli::prompt(array('y','n'));
574
-				if (is_array($args[0]))
575
-				{
576
-					$options = $args[0];
577
-				}
578
-
579
-				// Question without options
580
-				// E.g: $ready = Cli::prompt('What did you do today?');
581
-				elseif (is_string($args[0]))
582
-				{
583
-					$output = $args[0];
584
-				}
585
-
586
-			break;
587
-		}
588
-
589
-		// If a question has been asked with the read
590
-		if ($output !== '')
591
-		{
592
-			$extra_output = '';
593
-
594
-			if ($default !== null)
595
-			{
596
-				$extra_output = ' [ Default: "'.$default.'" ]';
597
-			}
598
-			elseif ($options !== [])
599
-			{
600
-				$extra_output = ' [ '.implode(' | ', $options).' ]';
601
-			}
602
-
603
-			fwrite(static::$stdout, $output.$extra_output.': ');
604
-		}
605
-
606
-		// Read the input from keyboard.
607
-		$input = trim(static::input()) ?: $default;
608
-
609
-		// No input provided and we require one (default will stop this being called)
610
-		if (empty($input) and $required === true)
611
-		{
612
-			static::write('This is required.');
613
-			static::newLine();
614
-
615
-			$input = forward_static_call_array([__CLASS__, 'prompt'], $args);
616
-		}
617
-
618
-		// If options are provided and the choice is not in the array, tell them to try again
619
-		if ( ! empty($options) and ! in_array($input, $options))
620
-		{
621
-			static::write('This is not a valid option. Please try again.');
622
-			static::newLine();
623
-
624
-			$input = forward_static_call_array([__CLASS__, 'prompt'], $args);
625
-		}
626
-
627
-		return $input;
628
- 	}
629
-
630
- 	/**
631
- 	 * Allows you to set a commandline option from code.
632
- 	 *
633
- 	 * @param  string|int  $name  The name of the option (int if unnamed)
634
-	 * @param  mixed|null  $value  The value to set, or null to delete the option
635
-	 *
636
-	 * @return mixed
637
-	 */
638
- 	public static function setOption($name, $value = null)
639
- 	{
640
- 		if ($value == null)
641
- 		{
642
- 			if (isset(static::$options[$name]))
643
- 			{
644
- 				unset(static::$options[$name]);
645
- 			}
646
- 		}
647
- 		else
648
- 		{
649
- 			static::$options[$name] = $value;
650
- 		}
651
- 	}
652
-
653
- 	/**
654
- 	 * Waits a certain number of seconds, optionally showing a wait message and
655
-	 * waiting for a key press.
656
- 	 *
657
- 	 * @param  int  $seconds  Number of seconds
658
- 	 * @param  bool  $countdown  Show a countdown or not
659
- 	 *
660
- 	 * @return string
661
- 	 */
662
- 	public static function wait(int $seconds = 0, bool $countdown = false)
663
- 	{
664
- 		if ($countdown === true)
665
- 		{
666
-			$time = $seconds;
667
-
668
- 			while ($time > 0)
669
- 			{
670
- 				fwrite(static::$stdout, $time.'... ');
671
- 				sleep(1);
672
- 				$time--;
673
- 			}
674
-
675
- 			static::write();
676
- 		}
677
- 		else
678
- 		{
679
- 			if ($seconds = 0)
680
- 			{
681
- 				sleep($seconds);
682
- 			}
683
- 			else
684
- 			{
685
- 				static::write(static::$waitMsg);
686
- 				static::input();
687
- 			}
688
- 		}
689
- 	}
690
-
691
- 	/**
692
- 	 * Outputs a string to the cli.	If you send an array it will implode them 
693
- 	 * with a line break.
694
- 	 * 
695
- 	 * @param  string|array  $text  The text to output, or array of lines
696
- 	 * @param  string|null  $foreground  The foreground color
697
- 	 * @param  string|null  $background  The background color
698
- 	 *
699
- 	 * @return string
700
- 	 */
701
- 	public static function write(string $text = '', string $foreground = null, string $background = null)
702
- 	{
703
- 		if (is_array($text))
704
- 		{
705
- 			$text = implode(PHP_EOL, $text);
706
- 		}
707
-
708
- 		if ($foreground OR $background)
709
- 		{
710
- 			$text = static::color($text, $foreground, $background);
711
- 		}
712
-
713
- 		fwrite(static::$stdout, $text.PHP_EOL);
714
- 	}
715
-
716
- 	/**
717
- 	 * Returns a well formatted table.
718
- 	 *
719
- 	 * @param  array  $tbody  List of rows
720
- 	 * @param  array  $thead  List of columns
721
- 	 *
722
- 	 * @return void
723
- 	 */
724
- 	public static function table(array $tbody, array $thead = [])
725
- 	{
726
- 		$rows = [];
727
-
728
- 		if ( ! empty($thead))
729
- 		{
730
- 			$rows[] = array_values($thead);
731
- 		}
732
-
733
- 		foreach ($tbody as $tr)
734
- 		{
735
- 			$rows[] = count($rows);
736
- 		}
737
-
738
- 		$totalRows = count($rows);
739
-
740
- 		// Store all columns lengths
741
- 		$allColsLengths = [];
742
-
743
- 		// Store maximum lengths by column
744
- 		$maxColsLengths = [];
745
-
746
- 		for ($row = 0; $row < $totalRows; $row++)
747
- 		{
748
- 			$column = 0;
749
-
750
- 			foreach ($rows[$row] as $col)
751
- 			{
752
- 				$allColsLengths[$row][$column] = static::strlen($col);
753
-
754
- 				if ( ! isset($maxColsLengths[$column]) || $allColsLengths[$row][$column] > $maxColsLengths[$column])
755
- 				{
756
- 					$maxColsLengths[$column] = $allColsLengths[$row][$column];
757
- 				}
758
-
759
- 				$column++;
760
- 			}
761
- 		}
762
-
763
- 		for ($row = 0; $row < $totalRows; $row++)
764
- 		{
765
- 			$column = 0;
766
-
767
- 			foreach ($rows[$row] as $col)
768
- 			{
769
- 				$diverse = $maxColsLengths[$column] - static::strlen($col);
284
+        fwrite(static::$stderr, $text.PHP_EOL);
285
+    }
286
+
287
+    /**
288
+     * Attempts to determine the width of the viewable CLI window.
289
+     *
290
+     * @param  int  $default
291
+     *
292
+     * @return int
293
+     */
294
+    public static function getWidth(int $default = 80)
295
+    {
296
+        if (static::isWindows() || (int) shell_exec('tput cols') === 0)
297
+        {
298
+            return $default;
299
+        }
300
+
301
+        return (int) shell_exec('tput cols');
302
+    }
303
+
304
+    /**
305
+     * Attempts to determine the height of the viewable CLI window.
306
+     *
307
+     * @param  int  $default
308
+     *
309
+     * @return int
310
+     */
311
+    public static function getHeight(int $default = 32)
312
+    {
313
+        if (static::isWindows())
314
+        {
315
+            return $default;
316
+        }
317
+
318
+        return (int) shell_exec('tput lines');
319
+    }
320
+
321
+    /**
322
+     * Takes a string and writes it to the command line, wrapping to a maximum width. 
323
+     * If no maximum width is specified, will wrap to the window's max.
324
+     *
325
+     * @param  string  $string  (null by default)
326
+     * @param  int  $max  (0 by default)
327
+     * @param  int $padLeft  (0 by default)
328
+     *
329
+     * @return string
330
+     */
331
+    public static function wrap(string $string = null, int $max = 0, int $padLeft = 0)
332
+    {
333
+        if (empty($string))
334
+        {
335
+            return '';
336
+        }
337
+
338
+        if ($max === 0)
339
+        {
340
+            $max = static::getWidth();
341
+        }
342
+
343
+        if (static::getWidth() < $max)
344
+        {
345
+            $max = static::getWidth();
346
+        }
347
+
348
+        $max = $max - $padLeft;
349
+
350
+        $lines = wordwrap($string, $max);
351
+
352
+        if ($pad_left > 0)
353
+        {
354
+            $lines = explode(PHP_EOL, $lines);
355
+
356
+            $first = true;
357
+
358
+            array_walk ($lines, function (&$line, $index) use ($pad_left, &$first) {
359
+
360
+                if ( ! $first)
361
+                {
362
+                    $line = str_repeat(' ', $pad_left) . $line;
363
+                }
364
+                else
365
+                {
366
+                    $first = false;
367
+                }
368
+
369
+            });
370
+
371
+            $lines = implode(PHP_EOL, $lines);
372
+        }
373
+
374
+        return $lines;
375
+    }
376
+
377
+        /**
378
+         * Get input from the shell, using readline or the standard STDIN.
379
+         *
380
+         * @param  string|int  $prefix  The name of the option (int if unnamed)
381
+         *
382
+         * @return string
383
+         */
384
+        public static function input($prefix = '')
385
+        {
386
+            if (static::$readlineSupport)
387
+            {
388
+                return readline($prefix);
389
+            }
390
+
391
+            echo $prefix;
392
+
393
+            return fgets(STDIN);
394
+        }
395
+
396
+        /**
397
+         * If operating system === windows.
398
+         * 
399
+         * @return string
400
+         */
401
+        public static function isWindows()
402
+        {
403
+            return 'win' === strtolower(substr(php_uname("s"), 0, 3));
404
+        }
405
+
406
+        /**
407
+         * Enter a number of empty lines.
408
+         * 
409
+         * @param  int  $num  Number of lines to output
410
+         *
411
+         * @return void
412
+         */
413
+        public static function newLine(int $num = 1)
414
+        {
415
+            for ($i = 0; $i < $num; $i++)
416
+            {			
417
+                static::write();
418
+            }
419
+        }
420
+
421
+        /**
422
+         * Returns the option with the given name. You can also give the option number.
423
+         *
424
+         * @param  string|int  $name  The name of the option (int if unnamed)
425
+         * @param  mixed  $default  The value to return if the option is not defined
426
+         *
427
+         * @return mixed
428
+         * 
429
+         * @uses   \Syscodes\Contract\Core\Lenevor
430
+         */
431
+        public static function option($name, $default = null)
432
+        {
433
+            if ( ! isset(static::$options[$name]))
434
+            {
435
+                return Lenevor::value($default);
436
+            }
437
+
438
+            return static::$options[$name];
439
+    }
440
+
441
+    /**
442
+     * Parses the command line it was called from and collects all
443
+     * options and valid segments.
444
+     * 
445
+     * @return bool
446
+     */
447
+    protected static function parseCommandLine()
448
+    {
449
+        $options = false;
450
+
451
+        for ($i = 1; $i < $_SERVER['argc']; $i++)
452
+        {
453
+            if ( ! $options && mb_strpos($_SERVER['argv'][$i], '-') === false)
454
+            {
455
+                static::$segments[] = $_SERVER['argv'][$i];
456
+
457
+                continue;
458
+            }
459
+
460
+            $options = true;
461
+
462
+            $args  = str_replace('-', '', $_SERVER['argv'][$i]);
463
+            $value = null;
464
+
465
+            if (isset($_SERVER['argv'][$i + 1]) && mb_strpos($_SERVER['argv'][$i + 1], '-') !== 0)
466
+            {
467
+                $value = $_SERVER['argv'][$i + 1];
468
+                $i++;
469
+            }
470
+
471
+            static::$options[$args] = $value;
472
+
473
+            $options = false;
474
+        }
475
+    }
476
+
477
+    /**
478
+     * Returns the command line string portions of the arguments, minus
479
+     * any options, as a string.
480
+     *
481
+     * @return string
482
+     */
483
+    public static function getURI()
484
+    {
485
+        return implode('/', static::$segments);
486
+    }
487
+
488
+    /**
489
+     * Returns an individual segment.
490
+     *
491
+     * @param  int  $index
492
+     * 
493
+     * @return mixed|null
494
+     */
495
+    public static function getSegment(int $index)
496
+    {
497
+        if ( ! isset(static::$segments[$index - 1]))
498
+        {
499
+            return null;
500
+        }
501
+
502
+        return static::$segments[$index - 1];
503
+    }
504
+
505
+    /**
506
+     * Returns the raw array of segments found.
507
+     *
508
+     * @return array
509
+     */
510
+    public static function getSegments()
511
+    {
512
+        return static::$segments;
513
+    }
514
+
515
+        /**
516
+         * Asks the user for input.  This can have either 1 or 2 arguments.
517
+         *
518
+         * Usage:
519
+         *
520
+         * // Waits for any key press
521
+         * Cli::prompt();
522
+         *
523
+         * // Takes any input
524
+         * $color = Cli::prompt('What is your favorite color?');
525
+         *
526
+         * // Takes any input, but offers default
527
+         * $color = Cli::prompt('What is your favourite color?', 'white');
528
+         *
529
+         * // Will only accept the options in the array
530
+         * $ready = Cli::prompt('Are you ready?', array('y','n'));
531
+         *
532
+         * @return string The user input
533
+         */
534
+        public static function prompt()
535
+        {
536
+            $args = func_get_args();
537
+
538
+        $options = [];
539
+        $output  = '';
540
+        $default = null;
541
+
542
+        // How many we got
543
+        $arg_count = count($args);
544
+
545
+        // Is the last argument a boolean? True means required
546
+        $required = end($args) === true;
547
+
548
+        // Reduce the argument count if required was passed, we don't care about that anymore
549
+        $required === true and --$arg_count;
550
+
551
+        // This method can take a few crazy combinations of arguments, so lets work it out
552
+        switch ($arg_count)
553
+        {
554
+            case 2:
555
+
556
+                // E.g: $ready = Cli::prompt('Are you ready?', ['y','n']);
557
+                if (is_array($args[1]))
558
+                {
559
+                    list($output, $options) = $args;
560
+                }
561
+
562
+                // E.g: $color = Cli::prompt('What is your favourite color?', 'white');
563
+                elseif (is_string($args[1]))
564
+                {
565
+                    list($output, $default) = $args;
566
+                }
567
+
568
+            break;
569
+
570
+            case 1:
571
+
572
+                // No question (probably been asked already) so just show options
573
+                // E.g: $ready = Cli::prompt(array('y','n'));
574
+                if (is_array($args[0]))
575
+                {
576
+                    $options = $args[0];
577
+                }
578
+
579
+                // Question without options
580
+                // E.g: $ready = Cli::prompt('What did you do today?');
581
+                elseif (is_string($args[0]))
582
+                {
583
+                    $output = $args[0];
584
+                }
585
+
586
+            break;
587
+        }
588
+
589
+        // If a question has been asked with the read
590
+        if ($output !== '')
591
+        {
592
+            $extra_output = '';
593
+
594
+            if ($default !== null)
595
+            {
596
+                $extra_output = ' [ Default: "'.$default.'" ]';
597
+            }
598
+            elseif ($options !== [])
599
+            {
600
+                $extra_output = ' [ '.implode(' | ', $options).' ]';
601
+            }
602
+
603
+            fwrite(static::$stdout, $output.$extra_output.': ');
604
+        }
605
+
606
+        // Read the input from keyboard.
607
+        $input = trim(static::input()) ?: $default;
608
+
609
+        // No input provided and we require one (default will stop this being called)
610
+        if (empty($input) and $required === true)
611
+        {
612
+            static::write('This is required.');
613
+            static::newLine();
614
+
615
+            $input = forward_static_call_array([__CLASS__, 'prompt'], $args);
616
+        }
617
+
618
+        // If options are provided and the choice is not in the array, tell them to try again
619
+        if ( ! empty($options) and ! in_array($input, $options))
620
+        {
621
+            static::write('This is not a valid option. Please try again.');
622
+            static::newLine();
623
+
624
+            $input = forward_static_call_array([__CLASS__, 'prompt'], $args);
625
+        }
626
+
627
+        return $input;
628
+        }
629
+
630
+        /**
631
+         * Allows you to set a commandline option from code.
632
+         *
633
+         * @param  string|int  $name  The name of the option (int if unnamed)
634
+         * @param  mixed|null  $value  The value to set, or null to delete the option
635
+         *
636
+         * @return mixed
637
+         */
638
+        public static function setOption($name, $value = null)
639
+        {
640
+            if ($value == null)
641
+            {
642
+                if (isset(static::$options[$name]))
643
+                {
644
+                    unset(static::$options[$name]);
645
+                }
646
+            }
647
+            else
648
+            {
649
+                static::$options[$name] = $value;
650
+            }
651
+        }
652
+
653
+        /**
654
+         * Waits a certain number of seconds, optionally showing a wait message and
655
+         * waiting for a key press.
656
+         *
657
+         * @param  int  $seconds  Number of seconds
658
+         * @param  bool  $countdown  Show a countdown or not
659
+         *
660
+         * @return string
661
+         */
662
+        public static function wait(int $seconds = 0, bool $countdown = false)
663
+        {
664
+            if ($countdown === true)
665
+            {
666
+            $time = $seconds;
667
+
668
+                while ($time > 0)
669
+                {
670
+                    fwrite(static::$stdout, $time.'... ');
671
+                    sleep(1);
672
+                    $time--;
673
+                }
674
+
675
+                static::write();
676
+            }
677
+            else
678
+            {
679
+                if ($seconds = 0)
680
+                {
681
+                    sleep($seconds);
682
+                }
683
+                else
684
+                {
685
+                    static::write(static::$waitMsg);
686
+                    static::input();
687
+                }
688
+            }
689
+        }
690
+
691
+        /**
692
+         * Outputs a string to the cli.	If you send an array it will implode them 
693
+         * with a line break.
694
+         * 
695
+         * @param  string|array  $text  The text to output, or array of lines
696
+         * @param  string|null  $foreground  The foreground color
697
+         * @param  string|null  $background  The background color
698
+         *
699
+         * @return string
700
+         */
701
+        public static function write(string $text = '', string $foreground = null, string $background = null)
702
+        {
703
+            if (is_array($text))
704
+            {
705
+                $text = implode(PHP_EOL, $text);
706
+            }
707
+
708
+            if ($foreground OR $background)
709
+            {
710
+                $text = static::color($text, $foreground, $background);
711
+            }
712
+
713
+            fwrite(static::$stdout, $text.PHP_EOL);
714
+        }
715
+
716
+        /**
717
+         * Returns a well formatted table.
718
+         *
719
+         * @param  array  $tbody  List of rows
720
+         * @param  array  $thead  List of columns
721
+         *
722
+         * @return void
723
+         */
724
+        public static function table(array $tbody, array $thead = [])
725
+        {
726
+            $rows = [];
727
+
728
+            if ( ! empty($thead))
729
+            {
730
+                $rows[] = array_values($thead);
731
+            }
732
+
733
+            foreach ($tbody as $tr)
734
+            {
735
+                $rows[] = count($rows);
736
+            }
737
+
738
+            $totalRows = count($rows);
739
+
740
+            // Store all columns lengths
741
+            $allColsLengths = [];
742
+
743
+            // Store maximum lengths by column
744
+            $maxColsLengths = [];
745
+
746
+            for ($row = 0; $row < $totalRows; $row++)
747
+            {
748
+                $column = 0;
749
+
750
+                foreach ($rows[$row] as $col)
751
+                {
752
+                    $allColsLengths[$row][$column] = static::strlen($col);
753
+
754
+                    if ( ! isset($maxColsLengths[$column]) || $allColsLengths[$row][$column] > $maxColsLengths[$column])
755
+                    {
756
+                        $maxColsLengths[$column] = $allColsLengths[$row][$column];
757
+                    }
758
+
759
+                    $column++;
760
+                }
761
+            }
762
+
763
+            for ($row = 0; $row < $totalRows; $row++)
764
+            {
765
+                $column = 0;
766
+
767
+                foreach ($rows[$row] as $col)
768
+                {
769
+                    $diverse = $maxColsLengths[$column] - static::strlen($col);
770 770
  				
771
- 				if ($diverse)	
772
- 				{
773
- 					$rows[$row][$column] = $rows[$row][$column].str_repeat(' ', $diverse);
774
- 				}
771
+                    if ($diverse)	
772
+                    {
773
+                        $rows[$row][$column] = $rows[$row][$column].str_repeat(' ', $diverse);
774
+                    }
775 775
 
776
- 				$column++;
777
- 			} 			
778
- 		}
776
+                    $column++;
777
+                } 			
778
+            }
779 779
 
780
- 		$table = '';
780
+            $table = '';
781 781
 
782
- 		for ($row = 0; $row < $rows; $row++)
783
- 		{
784
- 			if (0 === $row)
785
- 			{
786
- 				$cols = '+';
782
+            for ($row = 0; $row < $rows; $row++)
783
+            {
784
+                if (0 === $row)
785
+                {
786
+                    $cols = '+';
787 787
 
788
- 				foreach ($rows[$row] as $col) 
789
- 				{
790
- 					$cols .= str_repeat('-', static::strlen($col) + 2).'+';
791
- 				}
788
+                    foreach ($rows[$row] as $col) 
789
+                    {
790
+                        $cols .= str_repeat('-', static::strlen($col) + 2).'+';
791
+                    }
792 792
 
793
- 				$table .= $cols.PHP_EOL;
794
- 			}
793
+                    $table .= $cols.PHP_EOL;
794
+                }
795 795
 
796
- 			$table .= '| '.implode('-', $rows[$row]).' |'.PHP_EOL;
796
+                $table .= '| '.implode('-', $rows[$row]).' |'.PHP_EOL;
797 797
 
798
- 			if (0 === $row && ! empty($thead) || $row + 1 === $rows)
799
- 			{
800
- 				$table .= $cols.PHP_EOL;
801
- 			}
802
- 		}
798
+                if (0 === $row && ! empty($thead) || $row + 1 === $rows)
799
+                {
800
+                    $table .= $cols.PHP_EOL;
801
+                }
802
+            }
803 803
 
804
- 		fwrite(static::$stdout, $table);
805
- 	}
804
+            fwrite(static::$stdout, $table);
805
+        }
806 806
 }
807 807
\ No newline at end of file
Please login to merge, or discard this patch.