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
/**
21
 * Wrapper class that holds all information necessary to create a task
22
 * that did not exist when Phing started.
23
 *
24
 * <em> This has something to do with phing encountering an task XML element
25
 * it is not aware of at start time. This is a situation where special steps
26
 * need to be taken so that the element is then known.</em>
27
 *
28
 * @author  Andreas Aderhold <andi@binarycloud.com>
29
 * @author  Hans Lellelid <hans@xmpl.org>
30
 * @package phing
31
 */
32
class UnknownElement extends Task
33
{
34
    private $elementName;
35
    private $realThing;
36
    private $children = [];
37

38
    /**
39
     * Constructs a UnknownElement object
40
     *
41
     * @param string  The XML element name that is unknown
42
     */
43 1
    public function __construct($elementName)
44
    {
45 1
        parent::__construct();
46 1
        $this->elementName = (string) $elementName;
47
    }
48

49
    /**
50
     * Return the XML element name that this <code>UnnownElement</code>
51
     * handles.
52
     *
53
     * @return string The XML element name that is unknown
54
     */
55 1
    public function getTag()
56
    {
57 1
        return (string) $this->elementName;
58
    }
59

60
    /**
61
     * Tries to configure the unknown element
62
     *
63
     * @throws BuildException if the element can not be configured
64
     */
65 1
    public function maybeConfigure()
66
    {
67 1
        if ($this->realThing !== null) {
68 1
            return;
69
        }
70 1
        $this->configure($this->makeObject($this, $this->wrapper));
71
    }
72

73 1
    public function configure($realObj)
74
    {
75 1
        if ($realObj === null) {
76 0
            return;
77
        }
78 1
        $this->realThing = $realObj;
79 1
        $this->wrapper->setProxy($this->realThing);
80

81 1
        $task = null;
82 1
        if ($this->realThing instanceof Task) {
83 1
            $task = $this->realThing;
84 1
            $task->setRuntimeConfigurableWrapper($this->wrapper);
85 1
            if ($this->getWrapper()->getId() !== null) {
86 1
                $this->getOwningTarget()->replaceChild($this, $this->realThing);
87
            }
88
        }
89

90 1
        if ($task !== null) {
91 1
            $task->maybeConfigure();
92
        } else {
93 1
            $this->getWrapper()->maybeConfigure($this->getProject());
94
        }
95 1
        $this->handleChildren($this->realThing, $this->wrapper);
96
    }
97

98
    /**
99
     * Called when the real task has been configured for the first time.
100
     *
101
     * @throws BuildException if the task can not be created
102
     */
103 1
    public function main()
104
    {
105 1
        if ($this->realThing === null) {
106
            // plain impossible to get here, maybeConfigure should
107
            // have thrown an exception.
108 0
            throw new BuildException("Should not be executing UnknownElement::main() -- task/type: {$this->elementName}");
109
        }
110

111 1
        if ($this->realThing instanceof Task) {
112 1
            $this->realThing->main();
113
        }
114
    }
115

116
    /**
117
     * Add a child element to the unknown element
118
     *
119
     * @param    UnknownElement $child
120
     * @internal param The $object object representing the child element
121
     */
122 1
    public function addChild(UnknownElement $child)
123
    {
124 1
        $this->children[] = $child;
125
    }
126

127
    /**
128
     *  Handle child elemets of the unknown element, if any.
129
     *
130
     * @param object $parent The parent object the unknown element belongs to
131
     * @param object $parentWrapper The parent wrapper object
132
     */
133 1
    public function handleChildren($parent, $parentWrapper)
134
    {
135 1
        if ($parent instanceof TypeAdapter) {
136 1
            $parent = $parent->getProxy();
137
        }
138

139 1
        $parentClass = $parent === null ? get_class() : get_class($parent);
140 1
        $ih = IntrospectionHelper::getHelper($parentClass);
141

142 1
        for ($i = 0, $childrenCount = count($this->children); $i < $childrenCount; $i++) {
143 1
            $childWrapper = $parentWrapper->getChild($i);
144 1
            $child = $this->children[$i];
145

146 1
            $realChild = null;
147 1
            if ($parent instanceof TaskContainer) {
148 1
                $parent->addTask($child);
149 1
                continue;
150
            }
151

152 1
            $project = $this->project ?? $parent->getProject();
153 1
            $realChild = $ih->createElement($project, $parent, $child->getTag());
154

155 1
            $childWrapper->setProxy($realChild);
156 1
            if ($realChild instanceof Task) {
157 1
                $realChild->setRuntimeConfigurableWrapper($childWrapper);
158
            }
159

160 1
            $childWrapper->maybeConfigure($this->project);
161 1
            $child->handleChildren($realChild, $childWrapper);
162
        }
163
    }
164

165
    /**
166
     * Creates a named task or data type. If the real object is a task,
167
     * it is configured up to the init() stage.
168
     *
169
     * @param  UnknownElement $ue The unknown element to create the real object for.
170
     *                                 Must not be <code>null</code>.
171
     * @param  RuntimeConfigurable $w Ignored in this implementation.
172
     * @throws BuildException
173
     * @return object              The Task or DataType represented by the given unknown element.
174
     */
175 1
    protected function makeObject(UnknownElement $ue, RuntimeConfigurable $w)
176
    {
177 1
        $o = $this->makeTask($ue, $w, true);
178 1
        if ($o === null) {
179 1
            $o = $this->project->createDataType($ue->getTag());
180
        }
181 1
        if ($o === null) {
182 0
            throw new BuildException(
183 0
                "Could not create task/type: '" . $ue->getTag() . "'. Make sure that this class has been declared using taskdef / typedef."
184
            );
185
        }
186 1
        if ($o instanceof Task) {
187 1
            $o->setOwningTarget($this->getOwningTarget());
188
        }
189 1
        if ($o instanceof ProjectComponent) {
190 1
            $o->setLocation($this->getLocation());
191
        }
192

193 1
        return $o;
194
    }
195

196
    /**
197
     *  Create a named task and configure it up to the init() stage.
198
     *
199
     * @param  UnknownElement $ue The unknwon element to create a task from
200
     * @param  RuntimeConfigurable $w The wrapper object
201
     * @param  boolean $onTopLevel Whether to treat this task as if it is top-level.
202
     * @throws BuildException
203
     * @return Task                The freshly created task
204
     */
205 1
    protected function makeTask(UnknownElement $ue, RuntimeConfigurable $w, $onTopLevel = false)
206
    {
207 1
        $task = $this->project->createTask($ue->getTag());
208

209 1
        if ($task === null) {
210 1
            if (!$onTopLevel) {
211 0
                throw new BuildException("Could not create task of type: '" . $this->elementName . "'. Make sure that this class has been declared using taskdef.");
212
            }
213

214 1
            return null;
215
        }
216 1
        $task->setLocation($this->getLocation());
217 1
        if ($this->target !== null) {
218 1
            $task->setOwningTarget($this->target);
219
        }
220 1
        $task->init();
221 1
        return $task;
222
    }
223

224
    /**
225
     *  Get the name of the task to use in logging messages.
226
     *
227
     * @return string The task's name
228
     */
229 1
    public function getTaskName()
230
    {
231 1
        return $this->realThing === null || !$this->realThing instanceof Task
232 1
            ? parent::getTaskName()
233 1
            : $this->realThing->getTaskName();
234
    }
235

236
    /**
237
     * Returns the task instance after it has been created and if it is a task.
238
     *
239
     * @return Task a task instance or <code>null</code> if the real object is not
240
     *              a task.
241
     */
242 0
    public function getTask()
243
    {
244 0
        if ($this->realThing instanceof Task) {
245 0
            return $this->realThing;
246
        }
247 0
        return null;
248
    }
249

250
    /**
251
     * Return the configured object
252
     *
253
     * @return object the real thing whatever it is
254
     */
255 1
    public function getRealThing()
256
    {
257 1
        return $this->realThing;
258
    }
259

260
    /**
261
     * Set the configured object
262
     *
263
     * @param object $realThing the configured object
264
     */
265 1
    public function setRealThing($realThing)
266
    {
267 1
        $this->realThing = $realThing;
268
    }
269
}

Read our documentation on viewing source code .

Loading