public function __construct(Xref $xref, $message = "", $code = 0, \Exception $previous = null)
 {
     if ($xref->hasLocation()) {
         $message = sprintf("Error resolving Xref of type \"%s\" from location \"%s\"%s", $xref->getType(), $xref->getLocation(), $message == '' ? '' : ': ' . $message);
     }
     parent::__construct($message, $code, $previous);
 }
 public function __construct(Xref $xref, $message = "", $code = 0, \Exception $previous = null)
 {
     if ($xref->hasLocation()) {
         $message = sprintf('Unable to fetch external reference of type "%s" from location "%s"%s.', $xref->getType(), $xref->getLocation(), $message == '' ? '' : ': ' . $message);
     } else {
         $message = sprintf('Unable to fetch external reference of type "%s": no location specified.', $xref->getType());
     }
     parent::__construct($message, $code, $previous);
 }
 public function testOnDemandResolver()
 {
     $xrefDep1 = new Xref('file', '/dep1.json');
     $xrefDep1->setData(array('on-demand1' => '{{token1}}', 'on-demand2' => '{{token2}}'))->setResolved(true);
     $xrefMain = new Xref('file', '/main.json');
     $xrefMain->setData(array('include' => array('xref' => array('dep1' => array('type' => 'file', 'src' => '/dep1.json', 'resolve' => array(array('type' => 'on-demand', 'options' => array('token-prefix' => '{{', 'token-suffix' => '}}'), 'values' => array())))), 'main' => array('dep1'))))->setResolved(true);
     $treeCompiler = new TreeCompiler();
     $treeCompiler->getXrefs()->add($xrefDep1);
     $compiled = $treeCompiler->compileXref($xrefMain);
     $expected = array('on-demand1' => '{{token1}}', 'on-demand2' => '{{token2}}');
     $this->assertEquals($expected, $compiled);
     $this->onDemandTokenValues = array('token1' => 'ok1', 'token2' => 'ok2');
     $testListener = new TestEventListener(array($this, 'eventListenerCallback'));
     $eventManager = EventManager::getInstance();
     $eventManager->register($testListener);
     $this->assertTrue($eventManager->hasListeners());
     $compiled = $treeCompiler->compileXref($xrefMain);
     $expected = array('on-demand1' => 'ok1', 'on-demand2' => 'ok2');
     $this->assertEquals($expected, $compiled);
     $eventManager->remove($testListener);
     $this->assertFalse($eventManager->hasListeners());
 }
 /**
  * Fetch the data from the specified location of the Xref.
  *
  * @param Xref $xref
  * @param boolean $force If true and Xref already fetched, force the resolver to fetch the data again.
  * @throws \Exception
  */
 public static function resolve(Xref $xref, $force = false)
 {
     $xref->setResolved(true);
 }
Exemple #5
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;
 }
 public function testTokensInValuesXrefLocation()
 {
     $xrefDep1 = new Xref('file', '/dep1.json');
     $xrefDep1->setData(array('content' => 'dep1.json', 'dep1version' => '{{version}}'))->setResolved(true);
     $xrefDep2 = new Xref('file', '/dep2.json');
     $xrefDep2->setData(array('include' => array('xref' => array('dep1' => array('type' => 'file', 'src' => '/dep1.json', 'resolve' => array(array('type' => 'registered', 'options' => array('token-prefix' => '{{', 'token-suffix' => '}}'), 'values-xref' => array('type' => 'file', 'src' => '/dep{{version}}.json'))))), 'main' => array('dep1'))))->setResolved(true);
     $xrefMain = new Xref('file', '/main.json');
     $xrefMain->setData(array('include' => array('xref' => array('dep2' => array('type' => 'file', 'src' => '/dep2.json', 'resolve' => array(array('type' => 'registered', 'options' => array('token-prefix' => '{{', 'token-suffix' => '}}'), 'values' => array('version' => '1'))))), 'main' => array('dep2'))))->setResolved(true);
     $treeCompiler = new TreeCompiler();
     $treeCompiler->getXrefs()->add($xrefDep1);
     $treeCompiler->getXrefs()->add($xrefDep2);
     $compiled = $treeCompiler->compileXref($xrefMain);
     $expected = array('content' => 'dep1.json', 'dep1version' => 1);
     $this->assertEquals($expected, $compiled);
 }
 /**
  * Fetch the data from the specified location of the Xref.
  *
  * @param Xref $xref
  * @param boolean $force If true and Xref already fetched, force the resolver to fetch the data again.
  * @throws UnknownXrefTypeException
  * @throws XrefResolverFetchException
  * @throws \ConfigToken\TreeCompiler\XrefResolver\Exception\InvalidXrefTypeException
  * @throws \ConfigToken\TreeSerializer\Exception\UnknownContentTypeException
  * @throws \ConfigToken\TreeSerializer\Exception\UnknownFileExtensionException
  */
 public static function resolve(Xref $xref, $force = false)
 {
     if ($xref->isResolved() && !$force) {
         return;
     }
     static::matchType($xref);
     if (!$xref->hasLocation()) {
         throw new XrefResolverFetchException($xref);
     }
     $data = null;
     $httpCode = null;
     $contentType = null;
     $eventManager = EventManager::getInstance();
     if ($eventManager->hasListeners()) {
         $event = new Event(self::EVENT_ID_RESOLVE_URL);
         $event->data[self::EVENT_URL] = $xref->getLocation();
         $event->data[Event::RESULT] = false;
         $eventManager->dispatch($event);
         if (isset($event->data[Event::RESULT])) {
             if ($event->data[Event::RESULT] === true) {
                 $data = $event->data[self::EVENT_DATA];
                 $contentType = $event->data[self::EVENT_CONTENT_TYPE];
                 $httpCode = 200;
             } else {
                 if ($event->data[Event::RESULT] !== false) {
                     throw new XrefResolverFetchException($xref, sprintf('Got error message from listener: %s', $event->data[Event::RESULT]));
                 }
             }
         }
     }
     if (!isset($data)) {
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         curl_setopt($ch, CURLOPT_URL, $xref->getLocation());
         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
         curl_setopt($ch, CURLOPT_TIMEOUT, 15);
         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
         curl_setopt($ch, CURLOPT_HEADER, false);
         $data = curl_exec($ch);
         $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
         $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
         curl_close($ch);
     }
     if ($httpCode != 200) {
         throw new XrefResolverFetchException($xref, sprintf('Got response code %d', $httpCode));
     }
     if (TreeSerializerFactory::isRegisteredByContentType($contentType)) {
         $serializer = TreeSerializerFactory::getByContentType($contentType);
         $xref->setContentType($contentType);
     } else {
         $path = parse_url($xref->getLocation(), PHP_URL_PATH);
         $fileExtension = pathinfo($path, PATHINFO_EXTENSION);
         if (!TreeSerializerFactory::isRegisteredByFileExtension($fileExtension)) {
             throw new UnknownXrefTypeException(sprintf('Unable to find resolver for Xref content type "%s" or file extension "%s" for location "%s".', $contentType, $fileExtension, $xref->getLocation()));
         }
         $serializer = TreeSerializerFactory::getByFileExtension($fileExtension);
         $xref->setContentType($serializer::getContentType());
     }
     // TODO: catch exception, show xref location in error message
     $data = $serializer::deserialize($data);
     $xref->setData($data);
     $xref->setResolved(true);
 }
 /**
  * Used internally to verify if this Xref has the same type as the given Xref.
  *
  * @param Xref $xref The Xref to compare to.
  * @throws InvalidXrefTypeException
  */
 protected static function matchType(Xref $xref)
 {
     if ($xref->getType() !== static::getType()) {
         throw new InvalidXrefTypeException(sprintf('%s is unable to resolve Xrefs of type %s.', get_called_class(), $xref->getType()));
     }
 }
 public function parse($xrefs, $typeDelimiter, $overwrite = False, $ignore = True)
 {
     if (!is_array($xrefs)) {
         $xrefs = array($xrefs);
     }
     $parsed = array();
     foreach ($xrefs as $key => $value) {
         $xref = Xref::makeFromDefinitionString($value, $typeDelimiter);
         if ($this->has($xref)) {
             if (!$ignore) {
                 throw new AlreadyRegisteredException(sprintf('Not allowed to overwrite Xref of type "%s" with location "%s" already in collection.', $xref->getType(), $xref->getLocation()));
             }
             if ($overwrite && !$ignore) {
                 $this->add($xref);
             }
         } else {
             $this->add($xref);
         }
         $parsed[$key] = $xref;
     }
     return $parsed;
 }
 /**
  * Fetch the data from the specified location of the Xref.
  *
  * @param Xref $xref
  * @param boolean $force If true and Xref already fetched, force the resolver to fetch the data again.
  * @throws XrefResolverFetchException
  */
 public static function resolve(Xref $xref, $force = false)
 {
     if ($xref->isResolved() && !$force) {
         return;
     }
     static::matchType($xref);
     if (!$xref->hasLocation()) {
         throw new XrefResolverFetchException($xref);
     }
     $xrefLocation = $xref->getLocation();
     if (!file_exists($xrefLocation)) {
         throw new XrefResolverFetchException($xref, 'File does not exist.');
     }
     try {
         $data = file_get_contents($xrefLocation);
     } catch (\Exception $e) {
         throw new XrefResolverFetchException($xref, $e->getMessage());
     }
     $xref->setResolved(false);
     if ($xref->hasContentType()) {
         $serializer = TreeSerializerFactory::getByContentType($xref->getContentType());
     } else {
         $fileExtension = pathinfo($xrefLocation, PATHINFO_EXTENSION);
         $serializer = TreeSerializerFactory::getByFileExtension($fileExtension);
         $xref->setContentType($serializer::getContentType());
     }
     try {
         $data = $serializer::deserialize($data);
     } catch (TreeSerializerSyntaxException $e) {
         throw new XrefResolverFetchException($xref, $e->getMessage());
     }
     $xref->setData($data);
     $xref->setResolved(true);
 }