Passed
Push — master ( e1f86a...4e1a3a )
by Siad
05:23
created

PhpEvalTask::addParam()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
namespace Phing\Tasks\System;
21
22
use Phing\Exception\BuildException;
23
use Phing\Phing;
24
use Phing\Project;
25
use Phing\Task;
26
use Phing\Tasks\System\Element\LogLevelAware;
27
use Phing\Type\Parameter;
28
use Phing\Util\StringHelper;
29
30
/**
31
 * Executes PHP function or evaluates expression and sets return value to a property.
32
 *
33
 *    WARNING:
34
 *        This task can, of course, be abused with devastating effects.  E.g. do not
35
 *        modify internal Phing classes unless you know what you are doing.
36
 *
37
 * @author  Hans Lellelid <[email protected]>
38
 * @package phing.tasks.system
39
 *
40
 * @todo Add support for evaluating expressions
41
 */
42
class PhpEvalTask extends Task
43
{
44
    use LogLevelAware;
45
46
    protected $expression; // Expression to evaluate
47
    protected $function; // Function to execute
48
    protected $class; // Class containing function to execute
49
    protected $returnProperty = null; // name of property to set to return value
50
    protected $params = []; // parameters for function calls
51
52
    public function init()
53
    {
54
        $this->logLevel = Project::MSG_INFO;
55
    }
56
57
    /**
58
     * Main entry point.
59
     */
60
    public function main()
61
    {
62
        if ($this->function === null && $this->expression === null) {
63
            throw new BuildException(
64
                "You must specify a function to execute or PHP expression to evalute.",
65
                $this->getLocation()
66
            );
67
        }
68
69
        if ($this->function !== null && $this->expression !== null) {
70
            throw new BuildException("You can specify function or expression, but not both.", $this->getLocation());
71
        }
72
73
        if ($this->expression !== null && !empty($this->params)) {
74
            throw new BuildException(
75
                "You cannot use nested <param> tags when evaluationg a PHP expression.",
76
                $this->getLocation()
77
            );
78
        }
79
80
        if ($this->function !== null) {
81
            $this->callFunction();
82
        } elseif ($this->expression !== null) {
83
            $this->evalExpression();
84
        }
85
    }
86
87
    /**
88
     * Calls function and returns results.
89
     *
90
     * @return mixed
91
     */
92
    protected function callFunction()
93
    {
94
        if ($this->class !== null) {
95
            // import the classname & unqualify it, if necessary
96
            $this->class = Phing::import($this->class);
97
98
            $user_func = [$this->class, $this->function];
99
            $h_func = $this->class . '::' . $this->function; // human-readable (for log)
100
        } else {
101
            $user_func = $this->function;
102
            $h_func = $user_func; // human-readable (for log)
103
        }
104
105
        // put parameters into simple array
106
        $params = [];
107
        foreach ($this->params as $p) {
108
            if ($p instanceof Parameter) {
109
                $value = $p->getParams();
110
                array_walk_recursive(
111
                    $value,
112
                    function (&$item) {
113
                        if ($item instanceof Parameter) {
114
                            $item = $item->getValue();
115
                        }
116
                    }
117
                );
118
                if ($value === null) {
119
                    continue;
120
                }
121
                $params[] = $value;
122
            } else {
123
                $params[] = $p->getValue();
124
            }
125
        }
126
127
        $this->log("Calling PHP function: " . $h_func . "()", $this->logLevel);
128
        foreach ($params as $p) {
129
            $this->log("  param: " . print_r($p, true), Project::MSG_VERBOSE);
0 ignored issues
show
Bug introduced by
Are you sure print_r($p, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
            $this->log("  param: " . /** @scrutinizer ignore-type */ print_r($p, true), Project::MSG_VERBOSE);
Loading history...
130
        }
131
132
        $return = call_user_func_array($user_func, $params);
133
134
        if ($this->returnProperty !== null) {
135
            $this->project->setProperty($this->returnProperty, $return);
136
        }
137
    }
138
139
    private function resolveParams(&$iterator)
140
    {
141
        foreach ($iterator as &$value) {
142
            if (is_string($value)) {
143
                continue;
144
            }
145
            if (is_array($value->getValue())) {
146
                $this->resolveParams($value->getValue());
0 ignored issues
show
Bug introduced by
$value->getValue() cannot be passed to Phing\Tasks\System\PhpEvalTask::resolveParams() as the parameter $iterator expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
                $this->resolveParams(/** @scrutinizer ignore-type */ $value->getValue());
Loading history...
147
            }
148
            $value = is_string($value) ? $value : $value->getValue();
149
        }
150
151
        return $iterator;
152
    }
153
154
    /**
155
     * Evaluates expression and returns resulting value.
156
     *
157
     * @return mixed
158
     */
159
    protected function evalExpression()
160
    {
161
        $this->log("Evaluating PHP expression: " . $this->expression, $this->logLevel);
162
        if (!StringHelper::endsWith(';', trim($this->expression))) {
163
            $this->expression .= ';';
164
        }
165
166
        if ($this->returnProperty !== null) {
167
            $retval = null;
168
            eval('$retval = ' . $this->expression);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
169
            $this->project->setProperty($this->returnProperty, $retval);
170
        } else {
171
            eval($this->expression);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
172
        }
173
    }
174
175
    /**
176
     * Set function to execute
177
     *
178
     * @param $f
179
     */
180
    public function setFunction($f)
181
    {
182
        $this->function = $f;
183
    }
184
185
    /**
186
     * Set [static] class which contains function to execute
187
     *
188
     * @param $c
189
     */
190
    public function setClass($c)
191
    {
192
        $this->class = $c;
193
    }
194
195
    /**
196
     * Sets property name to set with return value of function or expression.
197
     *
198
     * @param $r
199
     */
200
    public function setReturnProperty($r)
201
    {
202
        $this->returnProperty = $r;
203
    }
204
205
    /**
206
     * Set PHP expression to evaluate.
207
     *
208
     * @param $expression
209
     */
210
    public function addText($expression)
211
    {
212
        $this->expression = $expression;
213
    }
214
215
    /**
216
     * Set PHP expression to evaluate.
217
     *
218
     * @param $expression
219
     */
220
    public function setExpression($expression)
221
    {
222
        $this->expression = $expression;
223
    }
224
225
    /**
226
     * Add a nested <param> tag.
227
     */
228
    public function addParam(Parameter $p)
229
    {
230
        $this->params[] = $p;
231
    }
232
}
233