Skip to content

Commit 4b6da0e

Browse files
committed
First commit
1 parent 425ce45 commit 4b6da0e

File tree

4 files changed

+356
-0
lines changed

4 files changed

+356
-0
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.idea/
2+
/.vscode/
3+
/.vs/
4+
/vendor/
5+
/composer.lock

README.md

+44
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
11
# Console
22
It is a simple helper library that will allow you to write your console/cli application with PHP.
3+
4+
## Requirements
5+
6+
- PHP 7.2 or higher
7+
8+
## Installation
9+
10+
```
11+
composer require initphp/console
12+
```
13+
14+
## Usage
15+
16+
```php
17+
#!usr/bin/php
18+
require_once __DIR__ . '/../vendor/autoload.php';
19+
use InitPHP\Console\Console;
20+
21+
$console = new Console();
22+
23+
// Register commands ...
24+
25+
// hello -name=John
26+
$console->register('hello', function (Console $console) {
27+
if ($console->has_flag('name')) {
28+
$console->message("Hello {name}", [
29+
'name' => $console->flag('name')
30+
]);
31+
}else{
32+
$console->message('Hello World!');
33+
}
34+
}, 'Says hello.');
35+
36+
37+
$console->run();
38+
```
39+
40+
## Credits
41+
42+
- [Muhammet ŞAFAK](https://www.muhammetsafak.com.tr) <<[email protected]>>
43+
44+
## License
45+
46+
Copyright &copy; 2022 [MIT License](./LICENSE)

composer.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "initphp/console",
3+
"description": "It is a simple helper library that will allow you to write your console/cli application with PHP.",
4+
"type": "library",
5+
"license": "MIT",
6+
"autoload": {
7+
"psr-4": {
8+
"InitPHP\\Console\\": "src/"
9+
}
10+
},
11+
"authors": [
12+
{
13+
"name": "Muhammet ŞAFAK",
14+
"email": "[email protected]",
15+
"role": "Developer",
16+
"homepage": "https://www.muhammetsafak.com.tr"
17+
}
18+
],
19+
"minimum-stability": "stable",
20+
"require": {
21+
"php": ">=7.2"
22+
}
23+
}

src/Console.php

+284
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
<?php
2+
/**
3+
* Console.php
4+
*
5+
* This file is part of Console.
6+
*
7+
* @author Muhammet ŞAFAK <[email protected]>
8+
* @copyright Copyright © 2022 Muhammet ŞAFAK
9+
* @license ./LICENSE MIT
10+
* @version 1.0
11+
* @link https://www.muhammetsafak.com.tr
12+
*/
13+
14+
declare(strict_types=1);
15+
16+
namespace InitPHP\Console;
17+
18+
use function trim;
19+
use function strlen;
20+
use function str_repeat;
21+
use function implode;
22+
use function strtolower;
23+
use function call_user_func_array;
24+
use function array_search;
25+
use function in_array;
26+
use function fopen;
27+
use function fgets;
28+
use function fclose;
29+
use function array_shift;
30+
use function count;
31+
use function substr;
32+
use function ltrim;
33+
use function strpos;
34+
use function explode;
35+
use function is_array;
36+
use function is_object;
37+
use function method_exists;
38+
use function strtr;
39+
40+
final class Console
41+
{
42+
43+
public const COLOR_DEFAULT = 39;
44+
public const COLOR_BLACK = 30;
45+
public const COLOR_RED = 31;
46+
public const COLOR_GREEN = 32;
47+
public const COLOR_YELLOW = 33;
48+
public const COLOR_BLUE = 34;
49+
public const COLOR_MAGENTA = 35;
50+
public const COLOR_CYAN = 36;
51+
public const COLOR_LIGHT_GRAY = 37;
52+
public const COLOR_DARK_GRAY = 90;
53+
public const COLOR_LIGHT_RED = 91;
54+
public const COLOR_LIGHT_GREEN = 92;
55+
public const COLOR_LIGHT_YELLOW = 93;
56+
public const COLOR_LIGHT_BLUE = 94;
57+
public const COLOR_LIGHT_MAGENTA= 95;
58+
public const COLOR_LIGHT_CYAN = 96;
59+
public const COLOR_WHITE = 97;
60+
61+
public const BACKGROUND_BLACK = 40;
62+
public const BACKGROUND_RED = 41;
63+
public const BACKGROUND_GREEN = 42;
64+
public const BACKGROUND_YELLOW = 43;
65+
public const BACKGROUND_BLUE = 44;
66+
public const BACKGROUND_MAGENTA = 45;
67+
public const BACKGROUND_CYAN = 46;
68+
69+
public const ITALIC = 3;
70+
public const BOLD = 1;
71+
public const UNDERLINE = 4;
72+
public const STRIKETHROUGH = 9;
73+
74+
75+
/** @var null|string */
76+
protected $command = null;
77+
78+
/** @var array */
79+
protected $commands = [];
80+
81+
/** @var array */
82+
protected $flags = [];
83+
84+
/** @var array */
85+
protected $segments = [];
86+
87+
/** @var array */
88+
protected $helps = [];
89+
90+
public function __construct()
91+
{
92+
$this->setUp();
93+
94+
$this->register('help', function (Console $console) {
95+
$outputs = []; $max_command_len = 0;
96+
unset($console->helps['help']);
97+
foreach ($console->helps as $key => $value) {
98+
if(empty($value)){
99+
$value = "\e[3mNo description has been written for this command.\e[0m";
100+
}
101+
$outputs[$key] = trim($value);
102+
$len = strlen($key);
103+
if($max_command_len < $len){
104+
$max_command_len = $len;
105+
}
106+
}
107+
foreach ($outputs as $key => $value) {
108+
$space_size = $max_command_len - strlen($key);
109+
$message = "\e[1m" . $key . "\e[0m"
110+
. str_repeat(' ', $space_size)
111+
. ' : ' . $value;
112+
$console->message($message . \PHP_EOL);
113+
}
114+
});
115+
}
116+
117+
public function message(string $msg, array $context = array(), array $format = [self::COLOR_DEFAULT]): void
118+
{
119+
echo "\e[" . implode(';', $format) . 'm' . $this->interpolate($msg, $context) . "\e[0m";
120+
}
121+
122+
public function error(string $msg, array $context = array()): void
123+
{
124+
$this->message('[ERROR] ' . $msg, $context, [self::COLOR_WHITE, self::BOLD, self::BACKGROUND_RED]);
125+
}
126+
127+
public function success(string $msg, array $context = array()): void
128+
{
129+
$this->message('[SUCCESS] ' . $msg, $context, [self::COLOR_WHITE, self::BACKGROUND_GREEN, self::BOLD]);
130+
}
131+
132+
public function warning(string $msg, array $context = array()): void
133+
{
134+
$this->message('[WARNING] ' . $msg, $context, [self::COLOR_WHITE, self::BACKGROUND_YELLOW, self::BOLD]);
135+
}
136+
137+
public function info(string $msg, array $context = array()): void
138+
{
139+
$this->message('[INFO] ' . $msg, $context, [self::COLOR_CYAN]);
140+
}
141+
142+
/**
143+
* @param string $command
144+
* @param \Callable $execute
145+
* @param string $definition
146+
* @return $this
147+
*/
148+
public function register(string $command, callable $execute, string $definition = ''): Console
149+
{
150+
$lowercase = strtolower($command);
151+
$this->commands[$lowercase] = $execute;
152+
$this->helps[$lowercase] = $definition;
153+
return $this;
154+
}
155+
156+
public function run(): bool
157+
{
158+
if($this->command === null){
159+
$this->error('A command to run was not found.');
160+
return false;
161+
}
162+
$lowercase = strtolower($this->command);
163+
if(!isset($this->commands[$lowercase])){
164+
$this->error('A command to run is not defined.');
165+
return false;
166+
}
167+
call_user_func_array($this->commands[$lowercase], [$this]);
168+
return true;
169+
}
170+
171+
public function segment(int $id = 0, $default = null)
172+
{
173+
return $this->segments[$id] ?? $default;
174+
}
175+
176+
public function segments(): array
177+
{
178+
return $this->segments;
179+
}
180+
181+
/**
182+
* @return false|int
183+
*/
184+
public function search_segment(string $search)
185+
{
186+
return array_search($search, $this->segments, true);
187+
}
188+
189+
public function has_segment(string $search): bool
190+
{
191+
return in_array($search, $this->segments, true);
192+
}
193+
194+
public function has_flag(string $name): bool
195+
{
196+
$lowercase = strtolower($name);
197+
return isset($this->flags[$lowercase]);
198+
}
199+
200+
public function flag(string $name, $default = null)
201+
{
202+
$lowercase = strtolower($name);
203+
return $this->flags[$lowercase] ?? $default;
204+
}
205+
206+
public function flags(): array
207+
{
208+
return $this->flags;
209+
}
210+
211+
public function ask(string $question)
212+
{
213+
$this->message( \PHP_EOL . $question . \PHP_EOL);
214+
$handle = fopen("php://stdin", "r");
215+
do {
216+
$line = fgets($handle);
217+
} while ($line == '');
218+
fclose($handle);
219+
return $line;
220+
}
221+
222+
/**
223+
* @return void
224+
*/
225+
protected function setUp(): void
226+
{
227+
global $argv;
228+
array_shift($argv);
229+
if(empty($argv)){
230+
return;
231+
}
232+
$this->command = $argv[0];
233+
array_shift($argv);
234+
$this->segments = $argv;
235+
for ($i = 0; $i < count($this->segments); ++$i) {
236+
if(!isset($this->segments[$i])){
237+
continue;
238+
}
239+
$segment = $this->segments[$i];
240+
if (substr($segment, 0, 1) === '-') {
241+
$segment = ltrim($segment, '-');
242+
if(strpos($segment, '=')){
243+
$parse = explode('=', $segment, 2);
244+
$lowercase = strtolower($parse[0]);
245+
$this->flags[$lowercase] = $parse[1];
246+
}else{
247+
$valueId = $i + 1;
248+
$lowercase = strtolower($segment);
249+
if(!isset($this->segments[$valueId])){
250+
$this->flags[$lowercase] = '';
251+
continue;
252+
}
253+
if(substr($this->segments[$valueId], 0, 1) === '-') {
254+
$this->flags[$lowercase] = '';
255+
continue;
256+
}
257+
$this->flags[$lowercase] = $this->segments[$valueId];
258+
++$i;
259+
continue;
260+
}
261+
}
262+
}
263+
}
264+
265+
/**
266+
* @param string $message
267+
* @param array $context
268+
* @return string
269+
*/
270+
private function interpolate(string $message, array $context = []): string
271+
{
272+
if(empty($context)){
273+
return $message;
274+
}
275+
$replace = [];
276+
foreach ($context as $key => $val) {
277+
if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
278+
$replace['{' . $key . '}'] = (string)$val;
279+
}
280+
}
281+
return strtr($message, $replace);
282+
}
283+
284+
}

0 commit comments

Comments
 (0)