Example #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;
 }
 /**
  * Check whether or not this is a standard Agavi configuration file, i.e. with
  * a <configurations> and <configuration> envelope.
  *
  * @return     bool true, if it is an Agavi config structure, false otherwise.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      1.0.0
  */
 public function isAgaviConfiguration()
 {
     return AgaviXmlConfigParser::isAgaviConfigurationDocument($this);
 }
 /**
  * @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;
 }
 /**
  * Builds a proper regular expression from the input pattern to test against
  * the given subject. This is for "environment" and "context" attributes of
  * configuration blocks in the files.
  *
  * @param      string A regular expression chunk without delimiters/anchors.
  *
  * @return     bool Whether or not the subject matched the pattern.
  *
  * @see        AgaviXmlConfigParser::testPattern()
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 public static function testPattern($pattern, $subject)
 {
     return AgaviXmlConfigParser::testPattern($pattern, $subject);
 }
Example #5
0
 protected function parseConfiguration($configFile, $xslFile = null, $environment = null)
 {
     return AgaviXmlConfigParser::run($configFile, $environment ? $environment : AgaviConfig::get('core.environment'), '', array(AgaviXmlConfigParser::STAGE_SINGLE => $xslFile ? array($xslFile) : array(), AgaviXmlConfigParser::STAGE_COMPILATION => array()), array(AgaviXmlConfigParser::STAGE_SINGLE => array(AgaviXmlConfigParser::STEP_TRANSFORMATIONS_BEFORE => array(), AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER => array()), AgaviXmlConfigParser::STAGE_COMPILATION => array(AgaviXmlConfigParser::STEP_TRANSFORMATIONS_BEFORE => array(), AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER => array())));
 }
 /**
  * Execute the config handler for the given file.
  * 
  * @param        string The path to the config file (full path).
  * @param        string The context which we're currently running.
  * @param        array  The config handler info.
  * 
  * @return       string The compiled data.
  * 
  * @author       Felix Gilcher <*****@*****.**>
  * @since        1.0.0
  */
 protected static function executeHandler($config, $context, array $handlerInfo)
 {
     // call the handler and retrieve the cache data
     $handler = new $handlerInfo['class']();
     if ($handler instanceof AgaviIXmlConfigHandler) {
         // a new-style config handler
         // it does not parse the config itself; instead, it is given a complete and merged DOM document
         $doc = AgaviXmlConfigParser::run($config, AgaviConfig::get('core.environment'), $context, $handlerInfo['transformations'], $handlerInfo['validations']);
         if ($context !== null) {
             $context = AgaviContext::getInstance($context);
         }
         $handler->initialize($context, $handlerInfo['parameters']);
         try {
             $data = $handler->execute($doc);
         } catch (AgaviException $e) {
             throw new $e(sprintf("Compilation of configuration file '%s' failed for the following reason(s):\n\n%s", $config, $e->getMessage()));
         }
     } else {
         $validationFile = null;
         if (isset($handlerInfo['validations'][AgaviXmlConfigParser::STAGE_SINGLE][AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER][AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA][0])) {
             $validationFile = $handlerInfo['validations'][AgaviXmlConfigParser::STAGE_SINGLE][AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER][AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA][0];
         }
         $handler->initialize($validationFile, null, $handlerInfo['parameters']);
         $data = $handler->execute($config, $context);
     }
     return $data;
 }