UnknownElement.php 7.4 KB

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