コード例 #1
0
 /**
  * @param      string An absolute filesystem path to a configuration file.
  * @param      array  An associative array of validation information.
  *
  * @return     AgaviConfigValueHolder The data handlers use to perform tasks.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 public function parse($config, $validationFile = null)
 {
     // copy path in case convertEncoding() needs to complain about a missing ICONV extension
     $this->config = $config;
     $parser = new AgaviXmlConfigParser($config, AgaviConfig::get('core.environment'), null);
     $validation = array(AgaviXmlConfigParser::STEP_TRANSFORMATIONS_BEFORE => array(), AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER => array(AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA => array()));
     if ($validationFile !== null) {
         $validation[AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER][AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA][] = $validationFile;
     }
     $doc = $parser->execute(array(), $validation);
     // remember encoding for convertEncoding()
     $this->encoding = strtolower($doc->encoding);
     $rootRes = new AgaviConfigValueHolder();
     if ($doc->documentElement) {
         $this->parseNodes(array($doc->documentElement), $rootRes);
     }
     return $rootRes;
 }
コード例 #2
0
 /**
  * @param      string An absolute filesystem path to a configuration file.
  * @param      string The environment name.
  * @param      string The optional context name.
  * @param      array  An associative array of transformation information.
  * @param      array  An associative array of validation information.
  *
  * @return     DOMDocument A properly merged DOMDocument.
  *
  * @author     David Zülke <*****@*****.**>
  * @author     Dominik del Bondio <*****@*****.**>
  * @author     Noah Fontes <*****@*****.**>
  * @since      0.11.0
  */
 public static function run($path, $environment, $context = null, array $transformationInfo = array(), array $validationInfo = array())
 {
     $isAgaviConfigFormat = true;
     // build an array of documents (this one, and the parents)
     $docs = array();
     $previousPaths = array();
     $nextPath = $path;
     while ($nextPath !== null) {
         // run the single stage parser
         $parser = new AgaviXmlConfigParser($nextPath, $environment, $context);
         $doc = $parser->execute($transformationInfo[self::STAGE_SINGLE], $validationInfo[self::STAGE_SINGLE]);
         // put the new document in the list
         $docs[] = $doc;
         // make sure it (still) is a <configurations> file with the proper Agavi namespace
         if ($isAgaviConfigFormat) {
             $isAgaviConfigFormat = self::isAgaviConfigurationDocument($doc);
         }
         // is it an Agavi <configurations> element? does it have a parent attribute? yes? good. parse that next
         // TODO: support future namespaces
         if ($isAgaviConfigFormat && $doc->documentElement->hasAttribute('parent')) {
             $theNextPath = AgaviToolkit::literalize($doc->documentElement->getAttribute('parent'));
             // no infinite loop plz, kthx
             if ($nextPath === $theNextPath) {
                 throw new AgaviParseException(sprintf("Agavi detected an infinite loop while processing parent configuration files of \n%s\n\nFile\n%s\nincludes itself as a parent.", $path, $theNextPath));
             } elseif (isset($previousPaths[$theNextPath])) {
                 throw new AgaviParseException(sprintf("Agavi detected an infinite loop while processing parent configuration files of \n%s\n\nFile\n%s\nhas previously been included by\n%s", $path, $theNextPath, $previousPaths[$theNextPath]));
             } else {
                 $previousPaths[$theNextPath] = $nextPath;
                 $nextPath = $theNextPath;
             }
         } else {
             $nextPath = null;
         }
     }
     // TODO: use our own classes here that extend DOM*
     $retval = new AgaviXmlConfigDomDocument();
     foreach (self::$agaviEnvelopeNamespaces as $envelopeNamespaceUri => $envelopeNamespacePrefix) {
         $retval->getXpath()->registerNamespace($envelopeNamespacePrefix, $envelopeNamespaceUri);
     }
     if ($isAgaviConfigFormat) {
         // if it is an Agavi config, we'll create a new document with all files' <configuration> blocks inside
         $retval->appendChild(new AgaviXmlConfigDomElement('configurations', null, self::NAMESPACE_AGAVI_ENVELOPE_LATEST));
         // reverse the array - we want the parents first!
         $docs = array_reverse($docs);
         $configurationElements = array();
         // TODO: I bet this leaks memory due to the nodes being taken out of the docs. beware circular refs!
         foreach ($docs as $doc) {
             // iterate over all nodes (attributes, <sandbox>, <configuration> etc) inside the document element and append them to the <configurations> element in our final document
             foreach ($doc->documentElement->childNodes as $node) {
                 if ($node->nodeType == XML_ELEMENT_NODE && $node->localName == 'configuration' && self::isAgaviEnvelopeNamespace($node->namespaceURI)) {
                     // it's a <configuration> element - put that on a stack for processing
                     $configurationElements[] = $node;
                 } else {
                     // import the node, recursively, and store the imported node
                     $importedNode = $retval->importNode($node, true);
                     // now append it to the <configurations> element
                     $retval->documentElement->appendChild($importedNode);
                 }
             }
             // if it's a <configurations> element, then we need to copy the attributes from there
             if ($doc->isAgaviConfiguration()) {
                 $namespaces = $doc->getXPath()->query('namespace::*');
                 foreach ($namespaces as $namespace) {
                     if ($namespace->localName !== 'xml' && $namespace->localName != 'xmlns') {
                         $retval->documentElement->setAttributeNS(self::NAMESPACE_XMLNS_2000, 'xmlns:' . $namespace->localName, $namespace->namespaceURI);
                     }
                 }
                 foreach ($doc->documentElement->attributes as $attribute) {
                     // but not the "parent" attributes...
                     if ($attribute->namespaceURI === null && $attribute->localName === 'parent') {
                         continue;
                     }
                     $importedAttribute = $retval->importNode($attribute, true);
                     $retval->documentElement->setAttributeNode($importedAttribute);
                 }
             }
         }
         // generic <configuration> first, then those with an environment attribute, then those with context, then those with both
         $configurationOrder = array('count(self::node()[@agavi_annotations_latest:matched and not(@environment) and not(@context)])', 'count(self::node()[@agavi_annotations_latest:matched and @environment and not(@context)])', 'count(self::node()[@agavi_annotations_latest:matched and not(@environment) and @context])', 'count(self::node()[@agavi_annotations_latest:matched and @environment and @context])');
         // now we sort the nodes according to the rules
         foreach ($configurationOrder as $xpath) {
             // append all matching nodes from the order array...
             foreach ($configurationElements as &$element) {
                 // ... if the xpath matches, that is!
                 if ($element->ownerDocument->getXpath()->evaluate($xpath, $element)) {
                     // it did, so import the node and append it to the result doc
                     $importedNode = $retval->importNode($element, true);
                     $retval->documentElement->appendChild($importedNode);
                 }
             }
         }
         // run the compilation stage parser
         $retval = self::executeCompilation($retval, $environment, $context, $transformationInfo[self::STAGE_COMPILATION], $validationInfo[self::STAGE_COMPILATION]);
     } else {
         // it's not an agavi config file. just pass it through then
         $retval->appendChild($retval->importNode($doc->documentElement, true));
     }
     // cleanup attempt
     unset($docs);
     // set the pseudo-document URI
     $retval->documentURI = $path;
     return $retval;
 }