Beispiel #1
0
 /**
  * Recursively resolve Xrefs and compile data.
  *
  * @param Xref $xref
  * @param XrefTokenResolverCollection $tokenResolvers
  * @param string|null $includeType
  * @param string|array|null $includeTypeValue
  * @param array $xrefPath
  * @return array
  *
  * @throws CircularReferenceException
  * @throws Exception\AlreadyRegisteredException
  * @throws TreeCompiler\XrefResolver\Exception\UnknownXrefTypeException
  * @throws UnknownXrefException
  * @throws XrefResolverFormatException
  * @throws \Exception
  */
 protected function recursiveCompileXref(Xref $xref, XrefTokenResolverCollection $tokenResolvers = null, $includeType = null, $includeTypeValue = null, &$xrefPath)
 {
     static $XREF_KEY = 0;
     static $XREF_RESOLVERS_KEY = 1;
     if (!isset($includeType)) {
         $includeType = static::INCLUDE_TYPE_GROUP;
     }
     switch ($includeType) {
         case static::INCLUDE_TYPE_GROUP:
             if (!isset($includeTypeValue)) {
                 $includeTypeValue = $this->includeMainKey;
             } else {
                 if (gettype($includeTypeValue) != 'string') {
                     throw new XrefResolverFormatException($xref, sprintf("Include type value must be a string representing the include group name. " . "\"%s\" given instead.", gettype($includeTypeValue)));
                 }
             }
             break;
         case static::INCLUDE_TYPE_XREF:
             if (!is_array($includeTypeValue) || empty($includeTypeValue)) {
                 throw new XrefResolverFormatException($xref, "Include type value must be a non-empty array of strings for named includes.");
             }
             break;
         default:
             throw new \Exception(sprintf('Unknown include type "%s".', $includeType));
     }
     $mustIncludeSpecificGroup = $includeTypeValue != $this->includeMainKey;
     $xref->resolve();
     $xrefData = $xref->getData();
     if (empty($xrefData)) {
         if (!is_array($xrefData)) {
             throw new XrefResolverFormatException($xref, "De-serialized data must be an array.");
         }
         return array();
     }
     if (!isset($xrefData[$this->includeKey]) || !is_array($xrefData[$this->includeKey])) {
         switch ($includeType) {
             case static::INCLUDE_TYPE_XREF:
                 throw new XrefResolverFormatException($xref, sprintf("Required to explicitly include the list of Xref keys [\"%s\"] " . "but the \"%s\" key is missing from the first level.", implode('", "', $includeTypeValue), $this->includeKey));
             case static::INCLUDE_TYPE_GROUP:
                 if (!$mustIncludeSpecificGroup) {
                     if (isset($xrefData[$this->addKey])) {
                         $result = $xrefData[$this->addKey];
                     } else {
                         if (isset($xrefData[$this->removeKey])) {
                             unset($xrefData[$this->removeKey]);
                         }
                         $result = $xrefData;
                     }
                     if (isset($tokenResolvers)) {
                         $tokenResolvers->applyToArray($result);
                     }
                     return $result;
                 }
                 throw new XrefResolverFormatException($xref, sprintf("Required to explicitly include the \"%s\" group of Xref keys " . "but the \"%s\" key is missing from the first level.", $includeTypeValue, $this->includeKey));
         }
     }
     $xrefDataInclude =& $xrefData[$this->includeKey];
     if (!isset($xrefDataInclude[$this->includeXrefKey]) || !is_array($xrefDataInclude[$this->includeXrefKey])) {
         switch ($includeType) {
             case static::INCLUDE_TYPE_XREF:
                 throw new XrefResolverFormatException($xref, sprintf("Required to explicitly include the list of Xref keys [\"%s\"] " . "but the \"%s\" key is missing from the \"%s\" key on the first level.", implode('", "', $includeTypeValue), $this->includeXrefKey, $this->includeKey));
             case static::INCLUDE_TYPE_GROUP:
                 if (!$mustIncludeSpecificGroup) {
                     if (isset($xrefData[$this->addKey])) {
                         $result = $xrefData[$this->addKey];
                     } else {
                         if (isset($xrefData[$this->removeKey])) {
                             unset($xrefData[$this->removeKey]);
                         }
                         $result = $xrefData;
                     }
                     if (isset($tokenResolvers)) {
                         $tokenResolvers->applyToArray($result);
                     }
                     return $result;
                 }
                 throw new XrefResolverFormatException($xref, sprintf("Required to explicitly include the \"%s\" group of Xref keys " . "but the \"%s\" key is missing from the \"%s\" key on the first level.", $includeTypeValue, $this->includeXrefKey, $this->includeKey));
         }
     }
     $xrefDataIncludeXrefs =& $xrefDataInclude[$this->includeXrefKey];
     $xrefKeysToBeResolved = $this->getXrefKeysToBeResolved($xref, $xrefDataInclude, $xrefDataIncludeXrefs, $includeType, $includeTypeValue);
     $xrefsToBeParsed = array();
     foreach ($xrefKeysToBeResolved as $xrefKeyToBeResolved) {
         if (!isset($xrefDataIncludeXrefs[$xrefKeyToBeResolved])) {
             throw new UnknownXrefException(sprintf("Unable to find the required Xref definition named \"%s\".", $xrefKeyToBeResolved));
         }
         $xrefsToBeParsed[$xrefKeyToBeResolved] = $xrefDataIncludeXrefs[$xrefKeyToBeResolved];
     }
     unset($xrefDataIncludeXrefs);
     $xrefId = $xref->getId();
     $xrefPath[$xrefId] = $xref;
     $xrefsToBeResolved = array();
     foreach ($xrefsToBeParsed as $xrefKey => $xrefInfo) {
         $includedXref = $this->parseXrefInfo($xrefKey, $xrefInfo, $tokenResolvers, $xrefPath);
         if (is_array($xrefInfo) && isset($xrefInfo[$this->includeXrefResolversKey])) {
             $xrefTokenResolvers = $this->parseXrefTokenResolverDefinitions($xrefKey, $xrefInfo[$this->includeXrefResolversKey], $tokenResolvers, $xrefPath);
         } else {
             $xrefTokenResolvers = null;
         }
         $xrefsToBeResolved[] = array($XREF_KEY => $includedXref, $XREF_RESOLVERS_KEY => $xrefTokenResolvers);
     }
     /** @var array $includedXrefs */
     $result = array();
     foreach ($xrefsToBeResolved as $xrefToBeResolved) {
         /** @var Xref $includedXref */
         $includedXref = $xrefToBeResolved[$XREF_KEY];
         if (isset($xrefPath[$includedXref->getId()])) {
             throw new CircularReferenceException(sprintf('Tree compiler encountered circular reference at "%s" in path ["%s"].', sprintf('%s:%s', $includedXref->getType(), $includedXref->getLocation()), implode('", "', $xrefPath)));
         }
         $this->xrefs->add($includedXref);
         /** @var XrefTokenResolverCollection $includeTokenResolvers */
         $includeTokenResolvers = $xrefToBeResolved[$XREF_RESOLVERS_KEY];
         if (isset($includeTokenResolvers)) {
             $downTokenResolvers = $includeTokenResolvers;
         } else {
             $downTokenResolvers = new XrefTokenResolverCollection();
         }
         if (isset($tokenResolvers)) {
             $downTokenResolvers->addCollection($tokenResolvers);
         }
         $includeData = $this->recursiveCompileXref($includedXref, $downTokenResolvers, static::INCLUDE_TYPE_GROUP, $this->includeMainKey, $xrefPath);
         $this->recursiveAddData($includeData, $result);
     }
     unset($xrefPath[$xrefId]);
     if (isset($xrefData[$this->removeKey])) {
         if (isset($tokenResolvers)) {
             $tokenResolvers->applyToArray($xrefData[$this->removeKey]);
         }
         $this->recursiveRemoveData($xrefData[$this->removeKey], $result);
     }
     if (isset($xrefData[$this->addKey])) {
         if (isset($tokenResolvers)) {
             $tokenResolvers->applyToArray($xrefData[$this->addKey]);
         }
         $this->recursiveAddData($xrefData[$this->addKey], $result);
     }
     return $result;
 }