Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite8d995c

Browse files
committed
[Process] Add commandline parameter binding support
1 parentd94d837 commite8d995c

File tree

5 files changed

+229
-19
lines changed

5 files changed

+229
-19
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Process;
13+
14+
useSymfony\Component\Process\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Romain Neutron <imprec@gmail.com>
18+
*
19+
* @api
20+
*/
21+
class CommandLine
22+
{
23+
constDEFAULT_PLACEHOLDER ='{}';
24+
private$commandLine;
25+
private$placeholder;
26+
private$disabled =false;
27+
28+
publicfunction__construct($commandLine,$placeholder =self::DEFAULT_PLACEHOLDER)
29+
{
30+
$this->commandLine = (string)$commandLine;
31+
$this->setPlaceholder($placeholder);
32+
}
33+
34+
/**
35+
* @return string
36+
*
37+
* @api
38+
*/
39+
publicfunctiongetCommandLine()
40+
{
41+
return$this->commandLine;
42+
}
43+
44+
/**
45+
* @param string $commandLine
46+
*
47+
* @return CommandLine
48+
*
49+
* @api
50+
*/
51+
publicfunctionsetCommandLine($commandLine)
52+
{
53+
$this->commandLine =$commandLine;
54+
55+
return$this;
56+
}
57+
58+
/**
59+
* @return string
60+
*
61+
* @api
62+
*/
63+
publicfunctiongetPlaceholder()
64+
{
65+
return$this->placeholder;
66+
}
67+
68+
/**
69+
* @param string $placeholder
70+
*
71+
* @return CommandLine
72+
*
73+
* @throws InvalidArgumentException
74+
*
75+
* @api
76+
*/
77+
publicfunctionsetPlaceholder($placeholder)
78+
{
79+
if (null !==$placeholder &&0 ===strlen($placeholder)) {
80+
thrownewInvalidArgumentException('Invalid placeholder');
81+
}
82+
83+
$this->placeholder =$placeholder;
84+
85+
return$this;
86+
}
87+
88+
/**
89+
* @param array $parameters
90+
*
91+
* @return string
92+
*
93+
* @throws InvalidArgumentException
94+
*
95+
* @api
96+
*/
97+
publicfunctionprepare(array$parameters)
98+
{
99+
if ($this->disabled) {
100+
return$this->commandLine;
101+
}
102+
103+
$placeholders =$this->countPlaceholders(array_filter(array_keys($parameters),function ($value) {return !is_numeric($value); }));
104+
105+
if (count($parameters) !==$placeholders) {
106+
thrownewInvalidArgumentException('Invalid number of bound parameters');
107+
}
108+
109+
if (0 ===$placeholders) {
110+
return$this->commandLine;
111+
}
112+
113+
$command ='';
114+
$offset =0;
115+
116+
foreach ($parametersas$key =>$value) {
117+
$placeholder =is_numeric($key) ?$this->placeholder :$key;
118+
119+
$pos =strpos($this->commandLine,$placeholder,$offset);
120+
$command .=substr($this->commandLine,$offset,$pos -$offset);
121+
$offset =$pos +strlen($placeholder);
122+
$command .=$this->escape($value);
123+
}
124+
$command .=substr($this->commandLine,$offset);
125+
126+
return$command;
127+
}
128+
129+
/**
130+
* @internal
131+
*/
132+
publicfunctiondisableArguments()
133+
{
134+
$this->disabled =true;
135+
}
136+
137+
/**
138+
* @param array $placeholders
139+
*
140+
* @return int
141+
*/
142+
privatefunctioncountPlaceholders(array$placeholders)
143+
{
144+
if (null ===$this->placeholder &&0 ===count($placeholders)) {
145+
return0;
146+
}
147+
148+
$total =preg_match_all('#' .preg_quote($this->placeholder,'#') .'#',$this->commandLine,$matches);
149+
150+
foreach ($placeholdersas$placeholder) {
151+
$total +=preg_match_all('#' .preg_quote($placeholder,'#') .'#',$this->commandLine,$matches);
152+
}
153+
154+
return$total;
155+
}
156+
157+
/**
158+
* @param string $string
159+
*
160+
* @return string
161+
*/
162+
privatefunctionescape($string)
163+
{
164+
return ProcessUtils::escapeArgument($string);
165+
}
166+
}

‎src/Symfony/Component/Process/PhpProcess.php‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ public function setPhpBinary($php)
5959
/**
6060
* {@inheritdoc}
6161
*/
62-
publicfunctionstart($callback =null)
62+
publicfunctionstart($callback =null,array$parameters =array())
6363
{
64-
if (null ===$this->getCommandLine()) {
64+
if ('' ===$this->getCommandLine()) {
6565
if (false ===$php =$this->executableFinder->find()) {
6666
thrownewRuntimeException('Unable to find the PHP executable.');
6767
}
6868
$this->setCommandLine($php);
6969
}
7070

71-
parent::start($callback);
71+
parent::start($callback,$parameters);
7272
}
7373
}

‎src/Symfony/Component/Process/Process.php‎

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Process
4646
constTIMEOUT_PRECISION =0.2;
4747

4848
private$callback;
49+
/** @var CommandLine */
4950
private$commandline;
5051
private$cwd;
5152
private$env;
@@ -148,7 +149,7 @@ public function __construct($commandline, $cwd = null, array $env = null, $input
148149
thrownewRuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
149150
}
150151

151-
$this->commandline =$commandline;
152+
$this->setCommandLine($commandline);
152153
$this->cwd =$cwd;
153154

154155
// on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
@@ -194,18 +195,20 @@ public function __clone()
194195
*
195196
* @param callable|null $callback A PHP callback to run whenever there is some
196197
* output available on STDOUT or STDERR
198+
* @param array $parameters
197199
*
198200
* @return int The exit status code
199201
*
200202
* @throws RuntimeException When process can't be launched
201203
* @throws RuntimeException When process stopped after receiving signal
202204
* @throws LogicException In case a callback is provided and output has been disabled
205+
* @throws InvalidArgumentException
203206
*
204207
* @api
205208
*/
206-
publicfunctionrun($callback =null)
209+
publicfunctionrun($callback =null,array$parameters =array())
207210
{
208-
$this->start($callback);
211+
$this->start($callback,$parameters);
209212

210213
return$this->wait();
211214
}
@@ -253,14 +256,16 @@ public function mustRun($callback = null)
253256
*
254257
* @param callable|null $callback A PHP callback to run whenever there is some
255258
* output available on STDOUT or STDERR
259+
* @param array $parameters
256260
*
257261
* @return Process The process itself
258262
*
259263
* @throws RuntimeException When process can't be launched
260264
* @throws RuntimeException When process is already running
261265
* @throws LogicException In case a callback is provided and output has been disabled
266+
* @throws InvalidArgurmentException
262267
*/
263-
publicfunctionstart($callback =null)
268+
publicfunctionstart($callback =null,array$parameters =array())
264269
{
265270
if ($this->isRunning()) {
266271
thrownewRuntimeException('Process is already running');
@@ -272,9 +277,8 @@ public function start($callback = null)
272277
$this->resetProcessData();
273278
$this->starttime =$this->lastOutputTime =microtime(true);
274279
$this->callback =$this->buildCallback($callback);
275-
$descriptors =$this->getDescriptors();
276-
277-
$commandline =$this->commandline;
280+
$commandline =$this->commandline->prepare($parameters);
281+
list($descriptors,$commandline) =$this->getDescriptors($commandline);
278282

279283
if (defined('PHP_WINDOWS_VERSION_BUILD') &&$this->enhanceWindowsCompatibility) {
280284
$commandline ='cmd /V:ON /E:ON /C "('.$commandline.')';
@@ -310,22 +314,24 @@ public function start($callback = null)
310314
*
311315
* @param callable|null $callback A PHP callback to run whenever there is some
312316
* output available on STDOUT or STDERR
317+
* @param array $parameters
313318
*
314319
* @return Process The new process
315320
*
316321
* @throws RuntimeException When process can't be launched
317322
* @throws RuntimeException When process is already running
323+
* @throws InvalidArgumentException
318324
*
319325
* @see start()
320326
*/
321-
publicfunctionrestart($callback =null)
327+
publicfunctionrestart($callback =null,array$parameters =array())
322328
{
323329
if ($this->isRunning()) {
324330
thrownewRuntimeException('Process is already running');
325331
}
326332

327333
$process =clone$this;
328-
$process->start($callback);
334+
$process->start($callback,$parameters);
329335

330336
return$process;
331337
}
@@ -843,11 +849,13 @@ public function addErrorOutput($line)
843849
/**
844850
* Gets the command line to be executed.
845851
*
846-
* @return string The command to execute
852+
* @param bool $asObject
853+
*
854+
* @return string|CommandLine The command to execute
847855
*/
848-
publicfunctiongetCommandLine()
856+
publicfunctiongetCommandLine($asObject =false)
849857
{
850-
return$this->commandline;
858+
return$asObject ?$this->commandline :$this->commandline->getCommandLine();
851859
}
852860

853861
/**
@@ -859,6 +867,9 @@ public function getCommandLine()
859867
*/
860868
publicfunctionsetCommandLine($commandline)
861869
{
870+
if (!$commandlineinstanceof CommandLine) {
871+
$commandline =newCommandLine($commandline);
872+
}
862873
$this->commandline =$commandline;
863874

864875
return$this;
@@ -1245,9 +1256,11 @@ public static function isPtySupported()
12451256
/**
12461257
* Creates the descriptors needed by the proc_open.
12471258
*
1259+
* @param string $commandline
1260+
*
12481261
* @return array
12491262
*/
1250-
privatefunctiongetDescriptors()
1263+
privatefunctiongetDescriptors($commandline)
12511264
{
12521265
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
12531266
$this->processPipes = WindowsPipes::create($this,$this->input);
@@ -1260,10 +1273,10 @@ private function getDescriptors()
12601273
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
12611274
$descriptors =array_merge($descriptors,array(array('pipe','w')));
12621275

1263-
$this->commandline ='('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
1276+
$commandline ='('.$commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
12641277
}
12651278

1266-
return$descriptors;
1279+
returnarray($descriptors,$commandline);
12671280
}
12681281

12691282
/**

‎src/Symfony/Component/Process/Tests/AbstractProcessTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ public function testProcessThrowsExceptionWhenExternallySignaled()
641641

642642
$termSignal =defined('SIGKILL') ?SIGKILL :9;
643643

644-
$process =$this->getProcess('exec php -r "while (true) {}"');
644+
$process =$this->getProcess('exec php -r "while (true) {}"');
645645
$process->start();
646646
posix_kill($process->getPid(),$termSignal);
647647

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespaceSymfony\Component\Process\Tests;
4+
5+
useSymfony\Component\Process\CommandLine;
6+
7+
class CommandLineTestextends \PHPUnit_Framework_TestCase
8+
{
9+
/**
10+
* @dataProvider provideVariousCommandsAndParameters
11+
*/
12+
publicfunctiontestCommandLinePrepare($commandLine,$placeholder,$parameters,$expected)
13+
{
14+
$commandLine =newCommandLine($commandLine,$placeholder);
15+
$this->assertSame($expected,$commandLine->prepare($parameters));
16+
}
17+
18+
publicfunctionprovideVariousCommandsAndParameters()
19+
{
20+
returnarray(
21+
array("{} | grep {}", CommandLine::DEFAULT_PLACEHOLDER,array('/usr/bin/ls','symfony'),"'/usr/bin/ls' | grep 'symfony'"),
22+
array("## | grep ##",'##',array('/usr/bin/ls','symfony'),"'/usr/bin/ls' | grep 'symfony'"),
23+
array("{ } | grep {}", CommandLine::DEFAULT_PLACEHOLDER,array('symfony'),"{ } | grep 'symfony'"),
24+
array("exec {} | grep {} > symfony.log", CommandLine::DEFAULT_PLACEHOLDER,array('/usr/bin/ls','symfony'),"exec '/usr/bin/ls' | grep 'symfony' > symfony.log"),
25+
array("exec ## | grep ## > symfony.log",'##',array('/usr/bin/ls','symfony'),"exec '/usr/bin/ls' | grep 'symfony' > symfony.log"),
26+
array("exec Ê™ | grep Ê™ > symfony.log",'Ê™',array('/usr/bin/ls','symfony'),"exec '/usr/bin/ls' | grep 'symfony' > symfony.log"),
27+
array("exec {} | grep {} > symfony.log", CommandLine::DEFAULT_PLACEHOLDER,array('i\'m','symfony'),"exec 'i'\\''m' | grep 'symfony' > symfony.log"),
28+
array("{} | grep {}", CommandLine::DEFAULT_PLACEHOLDER,array('/usr/bin/ls','symfony'),"'/usr/bin/ls' | grep 'symfony'"),
29+
);
30+
}
31+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp