1<?php
2
3/*
4 *  $Id: 4452f066ac71d51d3e2521d39cdee2caf4f7e9cc $
5 *
6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
8 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
9 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
10 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
11 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
12 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
16 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17 *
18 * This software consists of voluntary contributions made by many individuals
19 * and is licensed under the LGPL. For more information please see
20 * <http://phing.info>.
21 */
22
23require_once 'phing/tasks/system/condition/ConditionBase.php';
24require_once 'phing/tasks/system/SequentialTask.php';
25
26/**
27 * Perform some tasks based on whether a given condition holds true or
28 * not.
29 *
30 * <p>This task is heavily based on the Condition framework that can
31 * be found in Ant 1.4 and later, therefore it cannot be used in
32 * conjunction with versions of Ant prior to 1.4.</p>
33 *
34 * <p>This task doesn't have any attributes, the condition to test is
35 * specified by a nested element - see the documentation of your
36 * <code><condition&gt;</code> task (see
37 * <a href="http://jakarta.apache.org/ant/manual/CoreTasks/condition.html">the
38 * online documentation</a> for example) for a complete list of nested
39 * elements.</p>
40 *
41 * <p>Just like the <code><condition&gt;</code> task, only a single
42 * condition can be specified - you combine them using
43 * <code><and&gt;</code> or <code><or&gt;</code> conditions.</p>
44 *
45 * <p>In addition to the condition, you can specify three different
46 * child elements, <code><elseif&gt;</code>, <code><then&gt;</code> and
47 * <code><else&gt;</code>.  All three subelements are optional.
48 *
49 * Both <code><then&gt;</code> and <code><else&gt;</code> must not be
50 * used more than once inside the if task.  Both are
51 * containers for Ant tasks, just like Ant's
52 * <code><parallel&gt;</code> and <code><sequential&gt;</code>
53 * tasks - in fact they are implemented using the same class as Ant's
54 * <code><sequential&gt;</code> task.</p>
55 *
56 *  The <code><elseif&gt;</code> behaves exactly like an <code><if&gt;</code>
57 * except that it cannot contain the <code><else&gt;</code> element
58 * inside of it.  You may specify as may of these as you like, and the
59 * order they are specified is the order they are evaluated in.  If the
60 * condition on the <code><if&gt;</code> is false, then the first
61 * <code><elseif&gt;</code> who's conditional evaluates to true
62 * will be executed.  The <code><else&gt;</code> will be executed
63 * only if the <code><if&gt;</code> and all <code><elseif&gt;</code>
64 * conditions are false.
65 *
66 * <p>Use the following task to define the <code><if&gt;</code>
67 * task before you use it the first time:</p>
68 *
69 * <pre><code>
70 *   &lt;taskdef name=&quot;if&quot; classname=&quot;net.sf.antcontrib.logic.IfTask&quot; /&gt;
71 * </code></pre>
72 *
73 * <h3>Crude Example</h3>
74 *
75 * <code>
76 * <if>
77 *  <equals arg1="${foo}" arg2="bar" />
78 *  <then>
79 *    <echo message="The value of property foo is bar" />
80 *  </then>
81 *  <else>
82 *    <echo message="The value of property foo is not bar" />
83 *  </else>
84 * </if>
85 * </code>
86 *
87 * <code>
88 * <if>
89 *  <equals arg1="${foo}" arg2="bar" /&gt;
90 *  <then>
91 *   <echo message="The value of property foo is 'bar'" />
92 *  </then>
93 *
94 *  <elseif>
95 *   <equals arg1="${foo}" arg2="foo" />
96 *   <then>
97 *    <echo message="The value of property foo is 'foo'" />
98 *   </then>
99 *  </elseif>
100 *
101 *  <else>
102 *   <echo message="The value of property foo is not 'foo' or 'bar'" />
103 *  </else>
104 * </if>
105 * </code>
106 *
107 * @author <a href="mailto:stefan.bodewig@freenet.de">Stefan Bodewig</a>
108 * @package phing.tasks.system
109 */
110class IfTask extends ConditionBase {
111
112
113    private $thenTasks = null;
114    private $elseIfTasks = array();
115    private $elseTasks = null;
116
117    /***
118     * A nested Else if task
119     */
120    public function addElseIf(ElseIfTask $ei)
121    {
122        $this->elseIfTasks[] = $ei;
123    }
124
125    /**
126     * A nested <then> element - a container of tasks that will
127     * be run if the condition holds true.
128     *
129     * <p>Not required.</p>
130     */
131    public function addThen(SequentialTask $t) {
132        if ($this->thenTasks != null) {
133            throw new BuildException("You must not nest more than one <then> into <if>");
134        }
135        $this->thenTasks = $t;
136    }
137
138    /**
139     * A nested <else> element - a container of tasks that will
140     * be run if the condition doesn't hold true.
141     *
142     * <p>Not required.</p>
143     */
144    public function addElse(SequentialTask $e) {
145        if ($this->elseTasks != null) {
146            throw new BuildException("You must not nest more than one <else> into <if>");
147        }
148        $this->elseTasks = $e;
149    }
150
151    public function main() {
152
153        if ($this->countConditions() > 1) {
154            throw new BuildException("You must not nest more than one condition into <if>");
155        }
156        if ($this->countConditions() < 1) {
157            throw new BuildException("You must nest a condition into <if>");
158        }
159        $conditions = $this->getConditions();
160        $c = $conditions[0];
161
162        if ($c->evaluate()) {
163            if ($this->thenTasks != null) {
164                $this->thenTasks->main();
165            }
166        } else {
167            $done = false;
168            $sz = count($this->elseIfTasks);
169            for($i=0; $i < $sz && !$done; $i++) {
170                $ei = $this->elseIfTasks[$i];
171                if ($ei->evaluate()) {
172                    $done = true;
173                    $ei->main();
174                }
175            }
176
177            if (!$done && $this->elseTasks != null) {
178                $this->elseTasks->main();
179            }
180        }
181    }
182}
183
184/**
185 * "Inner" class for IfTask.
186 * This class has same basic structure as the IfTask, although of course it doesn't support <else> tags.
187 *
188 * @package phing.tasks.system
189 */
190class ElseIfTask extends ConditionBase {
191
192        private $thenTasks = null;
193
194        public function addThen(SequentialTask $t) {
195            if ($this->thenTasks != null) {
196                throw new BuildException("You must not nest more than one <then> into <elseif>");
197            }
198            $this->thenTasks = $t;
199        }
200
201        /**
202         * @return boolean
203         */
204        public function evaluate() {
205
206            if ($this->countConditions() > 1) {
207                throw new BuildException("You must not nest more than one condition into <elseif>");
208            }
209            if ($this->countConditions() < 1) {
210                throw new BuildException("You must nest a condition into <elseif>");
211            }
212
213            $conditions = $this->getConditions();
214            $c = $conditions[0];
215
216            return $c->evaluate();
217        }
218
219        /**
220         *
221         */
222        public function main() {
223            if ($this->thenTasks != null) {
224                $this->thenTasks->main();
225            }
226        }
227    }
228