root/branches/2.3/classes/phing/UnknownElement.php

Revision 205, 7.3 kB (checked in by hans, 1 year ago)

ticket:118 - Added fix from domain51.com for NULL projects in UnknownElement

  • Property svn:keywords set to author date id revision
Line 
1 <?php
2 /*
3  *  $Id$
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
22 require_once 'phing/Task.php';
23
24 /**
25  * Wrapper class that holds all information necessary to create a task
26  * that did not exist when Phing started.
27  *
28  * <em> This has something to do with phing encountering an task XML element
29  * it is not aware of at start time. This is a situation where special steps
30  * need to be taken so that the element is then known.</em>
31  *
32  * @author    Andreas Aderhold <andi@binarycloud.com>
33  * @author    Hans Lellelid <hans@xmpl.org>
34  * @version   $Revision: 1.9 $
35  * @package   phing
36  */
37 class UnknownElement extends Task {
38
39     private $elementName;
40     private $realThing;
41     private $children = array();
42
43     /**
44      * Constructs a UnknownElement object
45      *
46      * @param    string  The XML element name that is unknown
47      * @access   public
48      */
49     function __construct($elementName) {
50         $this->elementName = (string) $elementName;
51     }
52
53     /**
54      * Return the XML element name that this <code>UnnownElement</code>
55      * handles.
56      *
57      * @return  string  The XML element name that is unknown
58      */
59     public function getTag() {
60         return (string) $this->elementName;
61     }
62
63     /**
64      * Tries to configure the unknown element
65      *
66      * @throws  BuildException if the element can not be configured
67      */
68     public function maybeConfigure() {
69     
70         $this->realThing = $this->makeObject($this, $this->wrapper);
71         $this->wrapper->setProxy($this->realThing);
72         if ($this->realThing instanceof Task) {
73             $this->realThing->setRuntimeConfigurableWrapper($this->wrapper);
74         }
75     
76         $this->handleChildren($this->realThing, $this->wrapper);
77         $this->wrapper->maybeConfigure($this->getProject());
78                                     
79     }
80
81     /**
82      * Called when the real task has been configured for the first time.
83      *
84      * @throws  BuildException if the task can not be created
85      */
86     public function main() {
87     
88         if ($this->realThing === null) {
89             // plain impossible to get here, maybeConfigure should
90             // have thrown an exception.
91             throw new BuildException("Should not be executing UnknownElement::main() -- task/type: {$this->elementName}");
92         }
93         
94         if ($this->realThing instanceof Task) {
95             $this->realThing->main();
96         }
97         
98     }
99
100     /**
101      * Add a child element to the unknown element
102      *
103      * @param   object  The object representing the child element
104      */
105     public function addChild(UnknownElement $child) {
106         $this->children[] = $child;
107     }
108
109     /**
110      *  Handle child elemets of the unknown element, if any.
111      *
112      *  @param ProjectComponent The parent object the unkown element belongs to
113      *  @param object The parent wrapper object
114      */
115     function handleChildren(ProjectComponent $parent, $parentWrapper) {
116
117         if ($parent instanceof TaskAdapter) {
118             $parent = $parent->getProxy();
119         }
120
121         $parentClass = get_class($parent);
122         $ih = IntrospectionHelper::getHelper($parentClass);
123
124         for ($i=0, $childrenCount=count($this->children); $i < $childrenCount; $i++) {
125
126             $childWrapper = $parentWrapper->getChild($i);
127             $child = $this->children[$i];
128             $realChild = null;
129             if ($parent instanceof TaskContainer) {
130                 $realChild = $this->makeTask($child, $childWrapper, false);
131                 $parent->addTask($realChild);
132             } else {
133                 $project = $this->project === null ? $parent->project : $this->project;
134                 $realChild = $ih->createElement($project, $parent, $child->getTag());
135             }
136
137             $childWrapper->setProxy($realChild);
138             if ($realChild instanceof Task) {
139                 $realChild->setRuntimeConfigurableWrapper($childWrapper);
140             }
141             
142             if ($realChild instanceof ProjectComponent) {
143                 $child->handleChildren($realChild, $childWrapper);
144             }
145             
146             if ($realChild instanceof Task) {
147                 $realChild->maybeConfigure();
148             }
149         }
150     }
151
152     /**
153      * Creates a named task or data type. If the real object is a task,
154      * it is configured up to the init() stage.
155      *
156      * @param UnknownElement $ue The unknown element to create the real object for.
157      *           Must not be <code>null</code>.
158      * @param RuntimeConfigurable $w  Ignored in this implementation.
159      * @return object The Task or DataType represented by the given unknown element.
160      */
161     protected function makeObject(UnknownElement $ue, RuntimeConfigurable $w) {
162         $o = $this->makeTask($ue, $w, true);
163         if ($o === null) {
164             $o = $this->project->createDataType($ue->getTag());
165         }
166         if ($o === null) {
167             throw new BuildException("Could not create task/type: '".$ue->getTag()."'. Make sure that this class has been declared using taskdef / typedef.");
168         }
169         return $o;
170     }
171     
172     /**
173      *  Create a named task and configure it up to the init() stage.
174      *
175      * @param UnknownElement $ue The unknwon element to create a task from
176      * @param RuntimeConfigurable $w The wrapper object
177      * @param boolean $onTopLevel Whether to treat this task as if it is top-level.
178      * @return Task The freshly created task
179      */
180     protected function makeTask(UnknownElement $ue, RuntimeConfigurable $w, $onTopLevel = false) {
181
182         $task = $this->project->createTask($ue->getTag());
183
184         if ($task === null) {
185             if (!$onTopLevel) {
186                 throw new BuildException("Could not create task of type: '".$this->elementName."'. Make sure that this class has been declared using taskdef.");
187             }
188             return null;           
189         }
190
191         // used to set the location within the xmlfile so that exceptions can
192         // give detailed messages
193
194         $task->setLocation($this->getLocation());
195         $attrs = $w->getAttributes();
196         if (isset($attrs['id'])) {
197             $this->project->addReference($attrs['id'], $task);
198         }
199
200         // UnknownElement always has an associated target
201         $task->setOwningTarget($this->target);
202
203         $task->init();
204         return $task;
205     }
206
207     /**
208      *  Get the name of the task to use in logging messages.
209      *
210      *  @return  string  The task's name
211      */
212     function getTaskName() {
213         return $this->realThing === null ? parent::getTaskName() : $this->realThing->getTaskName();
214     }
215 }
216
Note: See TracBrowser for help on using the browser.