/** * Creates a named nested element. * * Valid creators can be in the form createFoo() or addFoo(Bar). * * @param Project $project * @param object $element Object the XML tag is child of. * Often a task object. * @param string $elementName XML tag name * @return object Returns the nested element. * @throws BuildException */ public function createElement(Project $project, $element, $elementName) { $addMethod = "add" . strtolower($elementName); $createMethod = "create" . strtolower($elementName); $nestedElement = null; if (isset($this->nestedCreators[$createMethod])) { $method = $this->nestedCreators[$createMethod]; try { // try to invoke the creator method on object $project->log(" -calling creator " . $method->getDeclaringClass()->getName() . "::" . $method->getName() . "()", Project::MSG_DEBUG); $nestedElement = $method->invoke($element); } catch (Exception $exc) { throw new BuildException($exc); } } elseif (isset($this->nestedCreators[$addMethod])) { $method = $this->nestedCreators[$addMethod]; // project components must use class hints to support the add methods try { // try to invoke the adder method on object $project->log(" -calling adder " . $method->getDeclaringClass()->getName() . "::" . $method->getName() . "()", Project::MSG_DEBUG); // we've already assured that correct num of params // exist and that method is using class hints $params = $method->getParameters(); $classname = null; if (($hint = $params[0]->getClass()) !== null) { $classname = $hint->getName(); } // create a new instance of the object and add it via $addMethod $clazz = new ReflectionClass($classname); if ($clazz->getConstructor() !== null && $clazz->getConstructor()->getNumberOfRequiredParameters() === 1) { $nestedElement = new $classname(Phing::getCurrentProject()); } else { $nestedElement = new $classname(); } $method->invoke($element, $nestedElement); } catch (Exception $exc) { throw new BuildException($exc); } } elseif ($this->bean->implementsInterface("CustomChildCreator")) { $method = $this->bean->getMethod('customChildCreator'); try { $nestedElement = $method->invoke($element, strtolower($elementName), $project); } catch (Exception $exc) { throw new BuildException($exc); } } else { //try the add method for the element's parent class $typedefs = $project->getDataTypeDefinitions(); if (isset($typedefs[$elementName])) { $elementClass = Phing::import($typedefs[$elementName]); $parentClass = get_parent_class($elementClass); $addMethod = 'add' . strtolower($parentClass); if (isset($this->nestedCreators[$addMethod])) { $method = $this->nestedCreators[$addMethod]; try { $project->log(" -calling parent adder " . $method->getDeclaringClass()->getName() . "::" . $method->getName() . "()", Project::MSG_DEBUG); $nestedElement = new $elementClass(); $method->invoke($element, $nestedElement); } catch (Exception $exc) { throw new BuildException($exc); } } } if ($nestedElement === null) { $msg = $this->getElementName($project, $element) . " doesn't support the '{$elementName}' creator/adder."; throw new BuildException($msg); } } if ($nestedElement instanceof ProjectComponent) { $nestedElement->setProject($project); } return $nestedElement; }