Skip to content

Commit 78309c7

Browse files
committed
Added console execution method
1 parent 0d23291 commit 78309c7

3 files changed

Lines changed: 193 additions & 2 deletions

File tree

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,54 @@ And than, run from command line:
4444
php script.php command-name --email=me@example.com
4545
```
4646

47+
### Log Messages
48+
49+
```php
50+
Console::log('Plain Log'); // stdout
51+
```
52+
53+
```php
54+
Console::success('Green log message'); // stdout
55+
```
56+
57+
```php
58+
Console::info('Blue log message'); // stdout
59+
```
60+
61+
```php
62+
Console::warning('Yellow log message'); // stderr
63+
```
64+
65+
```php
66+
Console::error('Red log message'); // stderr
67+
```
68+
69+
### Execute Commands
70+
71+
```php
72+
$stdout = '';
73+
$stderr = '';
74+
$stdin = '';
75+
$timeout = 3; // seconds
76+
$code = Console::execute('>&1 echo "success"', $stdin, $stdout, $stderr, $timeout);
77+
78+
echo $code; // 0
79+
echo $stdout; // 'success'
80+
echo $stderr; // ''
81+
```
82+
83+
```php
84+
$stdout = '';
85+
$stderr = '';
86+
$stdin = '';
87+
$timeout = 3; // seconds
88+
$code = Console::execute('>&2 echo "error"', $stdin, $stdout, $stderr, $timeout);
89+
90+
echo $code; // 0
91+
echo $stdout; // ''
92+
echo $stderr; // 'error'
93+
```
94+
4795
## System Requirements
4896

4997
Utopia Framework requires PHP 7.1 or later. We recommend using the latest PHP version whenever possible.

src/CLI/Console.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static public function log(string $message)
2727
*/
2828
static public function success(string $message)
2929
{
30-
return fwrite(STDERR, "\033[32m" . $message . "\033[0m\n");
30+
return fwrite(STDOUT, "\033[32m" . $message . "\033[0m\n");
3131
}
3232

3333
/**
@@ -85,4 +85,57 @@ static public function confirm(string $question) {
8585

8686
return $line;
8787
}
88+
89+
/**
90+
* Execute a Commnad
91+
*
92+
* This function was inspired by: https://stackoverflow.com/a/13287902/2299554
93+
*/
94+
public function execute(string $cmd, string $stdin = null, string &$stdout, string &$stderr, int $timeout = -1):int
95+
{
96+
$pipes = [];
97+
$process = proc_open(
98+
$cmd,
99+
[['pipe','r'],['pipe','w'],['pipe','w']],
100+
$pipes
101+
);
102+
$start = time();
103+
$stdout = '';
104+
$stderr = '';
105+
106+
if (is_resource($process)) {
107+
stream_set_blocking($pipes[0], 0);
108+
stream_set_blocking($pipes[1], 0);
109+
stream_set_blocking($pipes[2], 0);
110+
111+
fwrite($pipes[0], $stdin);
112+
fclose($pipes[0]);
113+
}
114+
115+
while(is_resource($process))
116+
{
117+
$stdout .= stream_get_contents($pipes[1]);
118+
$stderr .= stream_get_contents($pipes[2]);
119+
120+
if($timeout > 0 && time() - $start > $timeout)
121+
{
122+
proc_terminate($process, 9);
123+
return 1;
124+
}
125+
126+
$status = proc_get_status($process);
127+
128+
if(!$status['running']) {
129+
fclose($pipes[1]);
130+
fclose($pipes[2]);
131+
proc_close($process);
132+
133+
return $status['exitcode'];
134+
}
135+
136+
usleep(100000);
137+
}
138+
139+
return 1;
140+
}
88141
}

tests/CLI/ConsoleTest.php

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,99 @@ public function testLogs()
3131
// Use vars to resolve adapter key
3232
$this->assertEquals(4, Console::log('log'));
3333
$this->assertEquals(17, Console::success('success'));
34-
$this->assertEquals(15, Console::error('error'));
3534
$this->assertEquals(14, Console::info('info'));
3635
$this->assertEquals(19, Console::warning('warning'));
36+
$this->assertEquals(15, Console::error('error'));
3737
$this->assertEquals('this is an answer', Console::confirm('this is a question'));
3838
}
39+
40+
public function testExecuteBasic()
41+
{
42+
$stdout = '';
43+
$stderr = '';
44+
$stdin = '';
45+
$code = Console::execute('php -r "echo \'hello world\';"', $stdin, $stdout, $stderr, 10);
46+
47+
$this->assertEquals('', $stderr);
48+
$this->assertEquals('hello world', $stdout);
49+
$this->assertEquals(0, $code);
50+
}
51+
52+
public function testExecuteStdOut()
53+
{
54+
$stdout = '';
55+
$stderr = '';
56+
$stdin = '';
57+
$code = Console::execute('>&1 echo "success"', $stdin, $stdout, $stderr, 3);
58+
59+
$this->assertEquals('', $stderr);
60+
$this->assertEquals("success\n", $stdout);
61+
$this->assertEquals(0, $code);
62+
}
63+
64+
public function testExecuteStdErr()
65+
{
66+
$stdout = '';
67+
$stderr = '';
68+
$stdin = '';
69+
$code = Console::execute('>&2 echo "error"', $stdin, $stdout, $stderr, 3);
70+
71+
$this->assertEquals("error\n", $stderr);
72+
$this->assertEquals('', $stdout);
73+
$this->assertEquals(0, $code);
74+
}
75+
76+
public function testExecuteSyntaxError()
77+
{
78+
$stdout = '';
79+
$stderr = '';
80+
$stdin = '';
81+
$code = Console::execute('php -r "echo \'hello world\'"', $stdin, $stdout, $stderr, 10);
82+
83+
$this->assertEquals('', $stderr);
84+
$this->assertEquals("\nParse error: syntax error, unexpected end of file, expecting ',' or ';' in Command line code on line 1\n", $stdout);
85+
$this->assertEquals(254, $code);
86+
}
87+
88+
public function testExecuteExitCode()
89+
{
90+
$stdout = '';
91+
$stderr = '';
92+
$stdin = '';
93+
$code = Console::execute('php -r "echo \'hello world\'; exit(2);"', $stdin, $stdout, $stderr, 10);
94+
95+
$this->assertEquals('', $stderr);
96+
$this->assertEquals('hello world', $stdout);
97+
$this->assertEquals(2, $code);
98+
99+
$stdout = '';
100+
$stderr = '';
101+
$stdin = '';
102+
$code = Console::execute('php -r "echo \'hello world\'; exit(100);"', $stdin, $stdout, $stderr, 10);
103+
104+
$this->assertEquals('', $stderr);
105+
$this->assertEquals('hello world', $stdout);
106+
$this->assertEquals(100, $code);
107+
}
108+
109+
public function testExecuteTimeout()
110+
{
111+
$stdout = '';
112+
$stderr = '';
113+
$stdin = '';
114+
$code = Console::execute('php -r "sleep(1); echo \'hello world\'; exit(0);"', $stdin, $stdout, $stderr, 3);
115+
116+
$this->assertEquals('', $stderr);
117+
$this->assertEquals('hello world', $stdout);
118+
$this->assertEquals(0, $code);
119+
120+
$stdout = '';
121+
$stderr = '';
122+
$stdin = '';
123+
$code = Console::execute('php -r "sleep(4); echo \'hello world\'; exit(0);"', $stdin, $stdout, $stderr, 3);
124+
125+
$this->assertEquals('', $stderr);
126+
$this->assertEquals('', $stdout);
127+
$this->assertEquals(1, $code);
128+
}
39129
}

0 commit comments

Comments
 (0)