/**
  * Check if filters are properly assigned to resource.
  *
  * @param ContainerInterface $container Current container.
  * @param LibraryDefinitionInterface $definition Current definition.
  * @param ResourceInterface $resource Current resource.
  * @throws ConfigurationException
  */
 private function checkFiltersAssignment(ContainerInterface $container, LibraryDefinitionInterface $definition, ResourceInterface $resource)
 {
     if ($this->options['check_filter_assignment']) {
         if (isset($resource->getOptions()['filters'])) {
             $filters = $resource->getOptions()['filters'];
             if (!is_array($filters)) {
                 throw new ConfigurationException(sprintf('Expected array of filters for assigned for resource "%s" in definition "%s", "%s" given.', $resource->getSource(), $definition->getName(), gettype($filters)));
             }
             if ($resource instanceof ReferenceResource) {
                 throw new ConfigurationException(sprintf('You can not assign filters for reference resource "%s" in definition "%s".', $resource->getSource(), $definition->getName()));
             }
             $filters = array_map(function ($filter) {
                 return ltrim($filter, '?');
             }, $filters);
             if (count($duplicates = array_unique(array_diff_assoc($filters, array_unique($filters)))) > 0) {
                 throw new ConfigurationException(sprintf('Filters "%s" for resource "%s" in definition "%s" are used more than once.', implode('", "', $duplicates), $resource->getSource(), $definition->getName()));
             }
         }
     }
 }
 /**
  * Checks for circular references within the definitions in ContainerInterface using recursive function and
  * pointer to processed definitions list.
  *
  * @param ContainerInterface $container Container to check.
  * @param LibraryDefinitionInterface $definition Library definition to process.
  * @param array $registeredReferences List of already processed definitions in path.
  * @throws CircularReferenceException If circular reference is detected.
  */
 private function doCheckCircularReferences(ContainerInterface $container, LibraryDefinitionInterface $definition, array $registeredReferences)
 {
     /**
      * @var ResourceInterface $resource
      */
     foreach ($resources = $definition->getResources() as $resource) {
         /**
          * @var ReferenceResource $resource
          */
         if ($resource instanceof ReferenceResource) {
             if (array_key_exists($resource->getSource(), $registeredReferences)) {
                 throw new CircularReferenceException(sprintf('Circular reference detected at definition "%s", dependency chain (path: [%s] => [%s]).', $resource->getSource(), implode('] => [', $registeredReferences), $resource->getSource()));
             } else {
                 $newPath = $registeredReferences;
                 $newPath[$resource->getSource()] = $resource->getSource();
                 $this->doCheckCircularReferences($container, $container->getLibraries()->getDefinition($resource->getSource()), $newPath);
             }
         }
     }
 }
 /**
  * Process one single library definition resolving referenced dependencies.
  *
  * @param LibraryDefinitionInterface $definition Library definition to process.
  * @param ContainerInterface $container Container which is subject of process.
  * @param array $processedDefinitions List of already processed definitions.
  * @param int $count Number of processed definition for detecting circular references.
  * @throws CircularReferenceException If circular reference is detected.
  */
 private function processDefinition(LibraryDefinitionInterface $definition, ContainerInterface $container, array &$processedDefinitions, &$count = 0)
 {
     $count++;
     if ($count > count($container->getLibraries()->getDefinitions())) {
         throw new CircularReferenceException('Circular reference detected.');
     }
     /**
      * @var ResourceInterface $resource
      */
     foreach ($resources = $definition->getResources() as $resource) {
         /**
          * @var ReferenceResource $resource
          */
         if ($resource instanceof ReferenceResource) {
             if (!isset($processedDefinitions[$resource->getSource()])) {
                 $this->processDefinition($container->getLibraries()->getDefinition($resource->getSource()), $container, $processedDefinitions, $count);
             }
             $definition->replaceResource($resource, array_filter($this->getReferencedResources($resource, $container), function (ResourceInterface $replacement) use($definition) {
                 return !in_array($replacement, $definition->getResources());
             }));
         }
     }
     $processedDefinitions[$definition->getName()] = $definition->getName();
 }
 /**
  * Check if definition name is valid.
  *
  * @param ContainerInterface $container Current container.
  * @param LibraryDefinitionInterface $definition Current definition.
  */
 public function checkDefinitionName(ContainerInterface $container, LibraryDefinitionInterface $definition)
 {
     if (!ctype_alnum(str_replace(array('-', '_', '/'), '', $definition->getName()))) {
         throw new InvalidArgumentException(sprintf('Library definition name "%s" is not valid.', $definition->getName()));
     }
 }