1<?php
2/*
3 *  $Id: 8c46403ac685f362e310ffcceff5d4193bf09ef0 $
4 *
5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 *
17 * This software consists of voluntary contributions made by many individuals
18 * and is licensed under the LGPL. For more information please see
19 * <http://phing.info>.
20 */
21
22require_once 'phing/Task.php';
23
24/**
25 * Executes PHP function or evaluates expression and sets return value to a property.
26 *
27 *    WARNING:
28 *        This task can, of course, be abused with devastating effects.  E.g. do not
29 *        modify internal Phing classes unless you know what you are doing.
30 *
31 * @author   Hans Lellelid <hans@xmpl.org>
32 * @version  $Id$
33 * @package  phing.tasks.system
34 *
35 * @todo Add support for evaluating expressions
36 */
37class PhpEvalTask extends Task {
38
39    protected $expression; // Expression to evaluate
40    protected $function; // Function to execute
41    protected $class; // Class containing function to execute
42    protected $returnProperty = null; // name of property to set to return value
43    protected $params = array(); // parameters for function calls
44
45    protected $logLevel = Project::MSG_INFO;
46
47    /**
48     * Set level of log messages generated (default = info)
49     * @param string $level
50     */
51    public function setLevel($level)
52    {
53        switch ($level)
54        {
55            case "error": $this->logLevel = Project::MSG_ERR; break;
56            case "warning": $this->logLevel = Project::MSG_WARN; break;
57            case "info": $this->logLevel = Project::MSG_INFO; break;
58            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break;
59            case "debug": $this->logLevel = Project::MSG_DEBUG; break;
60        }
61    }
62
63    /** Main entry point. */
64    function main() {
65
66        if ($this->function === null && $this->expression === null) {
67            throw new BuildException("You must specify a function to execute or PHP expression to evalute.", $this->location);
68        }
69
70        if ($this->function !== null && $this->expression !== null) {
71            throw new BuildException("You can specify function or expression, but not both.", $this->location);
72        }
73
74        if ($this->expression !== null && !empty($this->params)) {
75            throw new BuildException("You cannot use nested <param> tags when evaluationg a PHP expression.", $this->location);
76        }
77
78        if ($this->function !== null) {
79            $this->callFunction();
80        } elseif ($this->expression !== null) {
81            $this->evalExpression();
82        }
83    }
84
85    /**
86     * Calls function and returns results.
87     * @return mixed
88     */
89    protected function callFunction() {
90
91        if ($this->class !== null) {
92            // import the classname & unqualify it, if necessary
93            $this->class = Phing::import($this->class);
94
95            $user_func = array($this->class, $this->function);
96            $h_func = $this->class . '::' . $this->function; // human-readable (for log)
97        } else {
98            $user_func = $this->function;
99            $h_func = $user_func; // human-readable (for log)
100        }
101
102        // put parameters into simple array
103        $params = array();
104        foreach($this->params as $p) {
105            $params[] = $p->getValue();
106        }
107
108        $this->log("Calling PHP function: " . $h_func . "()", $this->logLevel);
109        foreach($params as $p) {
110            $this->log("  param: " . $p, Project::MSG_VERBOSE);
111        }
112
113        $return = call_user_func_array($user_func, $params);
114
115        if ($this->returnProperty !== null) {
116            $this->project->setProperty($this->returnProperty, $return);
117        }
118    }
119
120    /**
121     * Evaluates expression and returns resulting value.
122     * @return mixed
123     */
124    protected function evalExpression() {
125        $this->log("Evaluating PHP expression: " . $this->expression, $this->logLevel);
126        if (!StringHelper::endsWith(';', trim($this->expression))) {
127            $this->expression .= ';';
128        }
129
130        if ($this->returnProperty !== null) {
131            $retval = null;
132            eval('$retval = ' . $this->expression);
133            $this->project->setProperty($this->returnProperty, $retval);
134        } else {
135            eval($this->expression);
136        }
137    }
138
139    /** Set function to execute */
140    public function setFunction($f) {
141       $this->function = $f;
142    }
143
144    /** Set [static] class which contains function to execute */
145    public function setClass($c) {
146       $this->class = $c;
147    }
148
149    /** Sets property name to set with return value of function or expression.*/
150    public function setReturnProperty($r) {
151       $this->returnProperty = $r;
152    }
153
154    /** Set PHP expression to evaluate. */
155    public function addText($expression) {
156        $this->expression = $expression;
157    }
158
159    /** Set PHP expression to evaluate. */
160    public function setExpression($expression) {
161        $this->expression = $expression;
162    }
163
164    /** Add a nested <param> tag. */
165    public function createParam() {
166        $p = new FunctionParam();
167        $this->params[] = $p;
168        return $p;
169    }
170}
171
172/**
173 * Supports the <param> nested tag for PhpTask.
174 *
175 * @package  phing.tasks.system
176 */
177class FunctionParam {
178
179    private $val;
180
181    public function setValue($v) {
182        $this->val = $v;
183    }
184
185    public function addText($v) {
186        $this->val = $v;
187    }
188
189    public function getValue() {
190        return $this->val;
191    }
192}