Process a set of schema files

@param string|string[] $taxonomy_xsd
@param number $depth
@return NULL|XBRL
347833
private static function postProcessSchemaFile( $taxonomy_xsd, $depth = 0 )
	{
		$context = XBRL_Global::getInstance();

		if ( ! is_array( $taxonomy_xsd ) )
		{
			if ( empty( $taxonomy_xsd ) )
			{
				XBRL_Log::getInstance()->warning( "The taxonomy file name supplied is empty" );
				return null;
			}

			$taxonomy_xsd = array( $taxonomy_xsd );
		}

		$processXsd = function( $depth = 0 ) use( &$processXsd, &$taxonomy_xsd, &$context )
		{
			if ( ! count( $taxonomy_xsd ) ) return false;

			$taxonomyXsdFile = array_shift( $taxonomy_xsd );

			// Get the existing taxonomy for the file
			/**
			 * @var XBRL $taxonomy
			 */
			$taxonomy = $context->getTaxonomyForXSD( $taxonomyXsdFile );
			if ( ! $taxonomy )
			{
				XBRL_Log::getInstance()->warning( "The taxonomy for '$taxonomyXsdFile' cannot be found." );
				return;
			}

			$taxonomy->loadLinkbases( $depth + 1, $processXsd );

			return $taxonomy;
		};

		$taxonomy = $processXsd( $depth );

		if ( $taxonomy )
		{
			if ( XBRL::isValidating() )
			{
				// Look for circular references in each of the extended links
				foreach ( $taxonomy->context->presentationRoleRefs as $role => $roleRef )
				{
					// If there is no hierarchy there can be no circular references
					if ( ! isset( $roleRef['hierarchy'] ) ) continue;

					$taxonomy->validateDirectedCycles( 'presentation', $role, $roleRef['hierarchy'], array(),
						function( $role, $result, $linkbase ) {
							XBRL_Log::getInstance()->taxonomy_validation( "5.2.4.2", "The linkbase contains circular references which are not permitted",
								array(
									'role' => "'$role'",
									'node' => "'$result'",
									'linkbase' => "'$linkbase'",
									'error' => 'xbrldte:DRSDirectedCycleError',
								)
							);
						}
					);
				}
			}

			// Look at the linkbases to determine if there are any definition additions that need processing
			// if ( $taxonomy->linkbaseRefExists( XBRL_Constants::$DefinitionLinkbaseRef ) )
			{
				$taxonomy->validateDimensions( true );
			}
			// Look at the linkbases to determine if there are any definition additions that need processing
			if ( $taxonomy->linkbaseRefExists( XBRL_Constants::$DefinitionLinkbaseRef ) ||
				 $taxonomy->linkbaseRefExists( XBRL_Constants::$DefinitionLinkbaseRef ) )
			{
				$taxonomy->fixupPresentationHypercubes();
			}
			$taxonomy->afterMainTaxonomy();
		}

		return $taxonomy;
	}
132873
public static function getCategoryTreeIds($categoryId, $depth = 1)
    {
        $result = \is_array($categoryId) ? $categoryId : [ $categoryId ];

        if ($depth > 1) {
            $categories = self::create()
                ->filterByParent($categoryId, Criteria::IN)
                ->withColumn('id')
                ->find();

            foreach ($categories as $category) {
                $result = array_merge(
                    $result,
                    self::getCategoryTreeIds($category->getId(), $depth - 1)
                );
            }
        }

        return $result;
    }
395817
protected function loadSchema($schema_path)
    {
        $json = false;
        if (file_exists($schema_path)) {
            $contents = file_get_contents($schema_path);
            $json = json_decode($contents);
            if ($json == false) {
                $message = sprintf('Error decoding %s.', $schema_path);
                $this->logger->error($message);
            }
        } else {
            $message = sprintf('Could not load file %s.', $schema_path);
            $this->logger->error($message);
        }

        return $json;
    }
1188893
public function read($depth)
	{
		if($this->_state == self::STOP)
			return false;
		if($this->_state == self::GO_ON)
		{
			do
			{
				if(!@$this->r->read())
				{
					$this->_state = self::STOP;
					return false;
				}
			}
			while($this->r->nodeType != \XMLReader::ELEMENT);
		}
		if($this->r->depth > $depth)
		{
			$this->_state = self::GO_ON;
			return true;
		}
		else
		{
			$this->_state = self::DO_NOT_READ;
			return false;
		}
	}
615442
protected function getSchema()
    {
        if (file_exists(__DIR__.'/../all.json')) {
            return json_decode(file_get_contents(__DIR__.'/../all.json'), true);
        }

        echo "Getting schema\n";

        $schema = [
            'datatypes' => [],
            'properties' => [],
            'types' => [],
        ];

        $client = new Client(['base_uri' => 'https://schema.org']);
        $response = $client->get('/docs/full.html');
        $crawler = new Crawler($response->getBody()->__toString());

        $dataTypes = $crawler->filter('#datatype_tree a');
        foreach ($dataTypes as $index => $dataType) {
            echo '['.($index + 1).'/'.$dataTypes->count().'] ';
            if (strpos($dataType->getAttribute('class'), 'ext') !== false) {
                echo 'Skipping extension datatype: '.$dataType->textContent."\n";
                continue;
            }

            echo 'Getting datatype: '.$dataType->textContent."\n";
            $schema['datatypes'][$dataType->textContent] = $this->getDataType($client, $dataType->getAttribute('href'));
        }

        $types = $crawler->filter('#thing_tree a');
        foreach ($types as $index => $type) {
            if (!isset($schema['types'][$type->textContent]) && substr($type->getAttribute('href'), 0, 1) !== '#') {
                echo '['.($index + 1).'/'.$types->count().'] ';
                if (strpos($type->getAttribute('class'), 'ext') !== false) {
                    echo 'Skipping extension type: '.$type->textContent."\n";
                    continue;
                }

                echo 'Getting type: '.$type->textContent."\n";
                $schema['types'][$type->textContent] = $this->getType($client, $type->getAttribute('href'));
            }
        }

        $specificProperties = [];
        foreach ($schema['types'] as $type) {
            foreach ($type['specific_properties'] as $specificProperty) {
                if (!isset($schema['properties'][$specificProperty])) {
                    $specificProperties[$specificProperty] = $specificProperty;
                }
            }
        }

        $specificPropertiesCount = count($specificProperties);
        foreach (array_values($specificProperties) as $index => $specificProperty) {
            echo '['.($index + 1).'/'.$specificPropertiesCount.'] Getting property: '.$specificProperty."\n";
            try {
                $schema['properties'][$specificProperty] = $this->getProperty($client, '/'.$specificProperty);
            } catch (\InvalidArgumentException $exception) {
                echo '   Failed: '.$exception->getMessage()."\n";
                echo "   Skipping...\n";
            }
        }

        $enumerationMembers = [];
        foreach ($schema['types'] as $type) {
            foreach ($type['enumeration_members'] as $enumerationMember) {
                if (!isset($schema['types'][$enumerationMember])) {
                    $enumerationMembers[$enumerationMember] = $enumerationMember;
                }
            }
        }

        $enumerationMembersCount = count($enumerationMembers);
        foreach (array_values($enumerationMembers) as $index => $enumerationMember) {
            echo '['.($index + 1).'/'.$enumerationMembersCount.'] Getting extra enumeration member: '.$enumerationMember."\n";
            $schema['types'][$enumerationMember] = $this->getType($client, '/'.$enumerationMember);
        }

        echo "Getting schema done!\n\n";

        file_put_contents(__DIR__.'/../all.json', json_encode($schema));

        return $schema;
    }
1241311
public function build($includeRoot = false, $root = null, $depth = null)
    {
        $root = $root === null ? $this->getRoot() : $root;
        $depth = $depth === null ? $this->depth : $depth;

        $result = [];

        /** @var NodeInterface $childNode */
        foreach ($root->getChildNodes($this->nodeTypeFilter) as $childNode) {
            $hasChildNodes = $childNode->hasChildNodes($this->nodeTypeFilter);
            $shouldLoadChildNodes = $hasChildNodes && ($depth > 1 || $this->isInRootLine($this->active, $childNode));

            $result[$childNode->getName()] = [
                'label' => $childNode->getNodeType()->isOfType('Neos.Neos:Document') ?
                    $childNode->getProperty('title') : $childNode->getLabel(),
                'contextPath' => $childNode->getContextPath(),
                'nodeType' => $childNode->getNodeType()->getName(),
                'hasChildren' => $hasChildNodes,
                'isActive' => $this->active && ($childNode->getPath() === $this->active->getPath()),
                'isFocused' => $this->active && ($childNode->getPath() === $this->active->getPath()),
                'isCollapsed' => !$shouldLoadChildNodes,
                'isCollapsable' => $hasChildNodes
            ];

            if ($shouldLoadChildNodes) {
                $result[$childNode->getName()]['children'] =
                    $this->build(false, $childNode, $depth - 1);
            }

            if ($childNode->getNodeType()->isOfType('Neos.Neos:Document')) {
                $result[$childNode->getName()]['href'] = $this->linkingService->createNodeUri(
                    /* $controllerContext */ $this->controllerContext,
                    /* $node */ $childNode,
                    /* $baseNode */ null,
                    /* $format */ null,
                    /* $absolute */ true,
                    /* $arguments */ [],
                    /* $section */ '',
                    /* $addQueryString */ false,
                    /* $argumentsToBeExcludedFromQueryString */ [],
                    /* $resolveShortcuts */ false
                );
            }
        }

        if ($includeRoot) {
            return [
                $root->getName() => [
                    'label' => $root->getNodeType()->isOfType('Neos.Neos:Document') ?
                        $root->getProperty('title') : $root->getLabel(),
                    'icon' => 'globe',
                    'contextPath' => $root->getContextPath(),
                    'nodeType' => $root->getNodeType()->getName(),
                    'hasChildren' => count($result),
                    'isCollapsed' => false,
                    'isActive' => $this->active && ($root->getPath() === $this->active->getPath()),
                    'isFocused' => $this->active && ($root->getPath() === $this->active->getPath()),
                    'children' => $result
                ]
            ];
        }

        return $result;
    }
6250
public function listContents($depth = 0, $filter = null, $type = 'all', $asHandlers = false)
	{
		$pattern = $this->path.'/*';

		if (is_array($filter))
		{
			$filters = $filter;
			$filter = new Filter;

			foreach ($filters as $f => $type)
			{
				if ( ! is_int($f))
				{
					$f = $type;
					$type = null;
				}

				$expected = true;

				if (strpos($f, '!') === 0)
				{
					$f = substr($f, 1);
					$expected = false;
				}

				$filter->addFilter($f, $expected, $type);
			}
		}

		if ($filter instanceof \Closure)
		{
			$callback = $filter;
			$filter = new Filter();
			$callback($filter);
		}

		if ( ! $filter)
		{
			$filter = new Filter;
		}

		$flags = GLOB_MARK;

		if ($type === 'file' and ! pathinfo($pattern, PATHINFO_EXTENSION))
		{
			// Add an extension wildcard
			$pattern .= '.*';
		}
		elseif ($type === 'dir')
		{
			$flags = GLOB_MARK | GLOB_ONLYDIR;
		}

		$contents = glob($pattern, $flags);

		// Filter the content.
		$contents = $filter->filter($contents);

		// Lower the depth for a recursive call
		if ($depth and $depth !== true)
		{
			$depth--;
		}

		$formatted = array();

		foreach ($contents as $item)
		{
			if ($filter->isCorrectType('dir', $item))
			{
				$_contents = array();

				if (($depth === true or $depth === 0) and ! $asHandlers)
				{
					$dir = new Directory($item);

					$_contents = $dir->listContents($item, $filter, $depth, $type);
				}

				if ($asHandlers)
				{
					$formatted[] = new Directory($item);
				}
				else
				{
					$formatted[$item] = $_contents;
				}
			}
			elseif ($filter->isCorrectType('file', $item))
			{
				if ($asHandlers)
				{
					$item = new File($item);
				}

				$formatted[] = $item;
			}
		}

		return $formatted;
	}
784854
protected function parseRelationsFromSchema(array $schema, $path='')
    {
        $results = [];

        foreach ($schema as $key => $value) {
            if (! is_numeric($key)) {
                // join relation
                if (substr($key, 0, 3) != '...') {
                    $childPath = ($path)
                        ? $path.'.'.$key
                        : $key;
                    $results[$childPath] = (isset($this->constraints[$this->root.'.'.$childPath]))
                        ? $this->constraints[$this->root.'.'.$childPath]
                        : function () {};
                } else {
                    $childPath = $path;
                }

                // recursive call
                $results = array_merge($results, $this->parseRelationsFromSchema($value, $childPath));
            }
        }

        return $results;
    }
378120
public function populateTree($depth = null, $with = null)
    {
        /** @var ActiveRecord[]|static[] $nodes */
        $query = $this->getDescendants($depth);
        if ($with) {
            $query->with($with);
        }
        $nodes = $query->all();

        $key = $this->owner->getAttribute($this->leftAttribute);
        $relates = [];
        $parents = [$key];
        $prev = $this->owner->getAttribute($this->depthAttribute);
        foreach($nodes as $node)
        {
            $level = $node->getAttribute($this->depthAttribute);
            if ($level <= $prev) {
                $parents = array_slice($parents, 0, $level - $prev - 1);
            }

            $key = end($parents);
            if (!isset($relates[$key])) {
                $relates[$key] = [];
            }
            $relates[$key][] = $node;

            $parents[] = $node->getAttribute($this->leftAttribute);
            $prev = $level;
        }

        $ownerDepth = $this->owner->getAttribute($this->depthAttribute);
        $nodes[] = $this->owner;
        foreach ($nodes as $node) {
            $key = $node->getAttribute($this->leftAttribute);
            if (isset($relates[$key])) {
                $node->populateRelation('children', $relates[$key]);
            } elseif ($depth === null || $ownerDepth + $depth > $node->getAttribute($this->depthAttribute)) {
                $node->populateRelation('children', []);
            }
        }

        return $this->owner;
    }
1309701
private function normalizeObject($data, $depth) {
		if (is_object($data)) {
			if ($data instanceof \Exception) {
				return $this->normalizeException($data);
			}
			// We don't need to go too deep in the recursion
			$maxObjectRecursion = $this->maxRecursionDepth;
			$arrayObject = new \ArrayObject($data);
			$serializedObject = $arrayObject->getArrayCopy();
			if ($depth < $maxObjectRecursion) {
				$depth++;
				$response = $this->normalize($serializedObject, $depth);

				return [$this->getObjetName($data) => $response];
			}

			return $this->getObjetName($data);
		}

		return null;
	}
824572
public static function getTree(
        Bookboon $bookboon,
        array $blacklistedCategoryIds = [],
        int $depth = 2
    ) : BookboonResponse {
        $bResponse = $bookboon->rawRequest('/categories', ['depth' => $depth]);

        $categories = $bResponse->getReturnArray();

        if (count($blacklistedCategoryIds) !== 0) {
            self::recursiveBlacklist($categories, $blacklistedCategoryIds);
        }

        $bResponse->setEntityStore(
            new EntityStore(Category::getEntitiesFromArray($categories))
        );

        return $bResponse;
    }
820178
private function searchTree($depth = 0)
    {
        $this->depth = $depth;
        foreach ($this->children->getList() as $node) {
            if ($depth > count($this->treePath)) {
                break;
            }

            if ($this->treePath[$depth] != $node->key) {
                continue;
            }

            /**
             * @var $node TreeNode
             */
            if (count($this->treePath) > $depth && $this->allowedToDiveDeeper($depth)) {
                $node->setTreepath($this->treePath);

                return $node->searchTree(++$depth);
            }
        }

        return $this;
    }
120362
public static function saveSchemas($destinationFolder, $schemasFolder, $schemasUrl, $content)
    {
        if (($schemasFolder === null) || empty($schemasFolder)) {
            // if null or empty schemas folder was provided
            // default schemas folder will be wsdl
            $schemasFolder = 'wsdl';
        }
        $schemasPath = rtrim($destinationFolder, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . rtrim($schemasFolder, DIRECTORY_SEPARATOR);
        // Here we must cover all possible variants
        if ((mb_strpos(mb_strtolower($schemasUrl), '.wsdl') !== false) || (mb_strpos(mb_strtolower($schemasUrl), '.xsd') !== false) || (mb_strpos(mb_strtolower($schemasUrl), '.xml') !== false)) {
            $filename = basename($schemasUrl);
        } else {
            // if $url is like http://example.com/index.php?WSDL default filename will be schema.wsdl
            $filename = 'schema.wsdl';
        }
        self::createDirectory($schemasPath);
        file_put_contents($schemasPath . DIRECTORY_SEPARATOR . $filename, $content);
        return $schemasPath . DIRECTORY_SEPARATOR . $filename;
    }
432501
private function importSchemas( $depth = 0 )
	{
		$xsiAttributes = $this->xbrlDocument->attributes( SCHEMA_INSTANCE_NAMESPACE );

		// BMS 2018-06-09 Add this code to interpret any schema location atttibute
		//					because generics test 70012 failed because the generics
		//					was not being loaded otherwise.
		// Load any schemas specified in the schema location attribute.
		if ( isset( $xsiAttributes['schemaLocation'] ) )
		{
			$parts = array_filter( preg_split( "/\s/s",  (string)$xsiAttributes['schemaLocation'] ) );

			$key = "";
			foreach ( $parts as $part )
			{
				if ( empty( $key ) )
				{
					$key = $part;
				}
				else
				{
					// Only load the schema if it is not already loaded
					$schemaLocation = XBRL::resolve_path( $this->getSchemaLocation(), trim( $part ) );
					if ( ! isset( $this->context->schemaFileToNamespace[ $schemaLocation ] ) )
					{
						if ( ! isset( XBRL_Global::$taxonomiesToIgnore[ $schemaLocation ] ) )
						{
							$this->log()->info( str_repeat( "\t", $depth ) . "$schemaLocation" );

							$this->importSchema( $schemaLocation, $depth );
						}
					}

					$key = "";
				}
			}

		}

		foreach ( $this->xbrlDocument->children( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_SCHEMA ] )->import as $key => $node )
		{
			$attributes = $node->attributes();

			if ( ! isset( $attributes['schemaLocation'] ) )
			{
				continue;
			}

			if ( ! isset( $attributes['namespace'] ) )
			{
				continue;
			}

			$namespace = (string) $attributes['namespace'];

			// If this taxonomy already exists bail
			if ( isset( $this->context->importedSchemas[ $namespace ] ) )
			{
				continue;
			}

			// $schemaLocation = XBRL::resolve_path( pathinfo( $this->schemaLocation, PATHINFO_DIRNAME ), trim( (string) $attributes['schemaLocation'] ) );
			$schemaLocation = XBRL::resolve_path( $this->schemaLocation, trim( (string) $attributes['schemaLocation'] ) );

			// $taxonomiesToIgnore is a list of the XML and XBRL core taxonomies that are taken as read so do not need to be processed.
			if ( isset( XBRL_Global::$taxonomiesToIgnore[ $schemaLocation ] ) ) continue;

			$this->log()->info( str_repeat( "\t", $depth ) . "$schemaLocation" );

			$this->importSchema( $schemaLocation, $depth );
		}
	}
598201
protected function scanClasses($dir, $depth = 2) {

        // Don't recurse if we've hit out depth limit
        if ($depth < 0) {
            return [];
        }

        $paths = scandir($dir);

        $classes = [];
        foreach ($paths as $path) {
            if (in_array($path, ['.','..'])) {
                continue;
            }

            $full = paths($dir,$path);

            if (is_dir($full)) {
                if ($depth > 0) {
                    $classes = array_merge($classes, $this->scanClasses($full, $depth-1));
                }
            } else {

                // Only scan PHP files
                if (fnmatch('*.php', $path)) {

                    $declarations = $this->scanFile($full);

                    // Iterate over all namespaces
                    foreach ($declarations as $namespaceRow) {
                        if (isset($namespaceRow['namespace']) && $namespaceRow) {
                            $namespace = rtrim($namespaceRow['namespace'], '\\').'\\';
                            $namespaceClasses = $namespaceRow['classes'];
                        } else {
                            $namespace = '';
                            $namespaceClasses = $namespaceRow;
                        }

                        // Iterate over all classes within NS
                        foreach ($namespaceClasses as $classRow) {
                            $className = $namespace.$classRow['name'];
                            $classes[strtolower($className)] = [$className, $full];

                            // Special case for main addon file
                            if ($classRow['type'] == 'CLASS') {
                                if (preg_match('`^[\w\d]+Addon$`', $classRow['name'])) {
                                    $this->special['addon'] = $className;
                                }
                            }
                        }
                    }
                }

            }
        }

        return $classes;
    }
675486
public function toArrayRaw(Entity $entity, $depth=0) {
		$res = [];

		foreach($entity->getDefinition()->properties() as $name=>$property) {
			if($entity->getDefinition()->property($name) instanceof Property\EntityProperty) {
				if($depth < 1)
					$res[$name] = $entity->get($name, null, false);
				else {
					if($entity->getDefinition()->property($name)->get('many')) {
						foreach($entity->get($name, null, false) as $subentity)
							$res[$name][] = $subentity->toArrayRaw($depth-1);
					}
					else {
						if($subentity = $entity->get($name, null, false))
							$res[$name] = $subentity->toArrayRaw($depth-1);
						else
							$res[$name] = null;
					}
				}
			}
			elseif($entity->getDefinition()->property($name)->get('many'))
				$res[$name] = $entity->get($name)->all();
			else
				$res[$name] = $entity->get($name);
		}

		return $res;
	}
1200358
private function setChildren(\SimpleXMLElement $xml, $depth, $key, array $arrayXML) {
        $return = $arrayXML;
        if ($xml->children()->count() > 0) {
            foreach ($xml->children() as $childValue) {
                $child = $this->xml2array($childValue, $depth);
                if ($depth > 1 && ! empty($child)) {
                    $return = array_merge_recursive($return, [$key => $child]);
                } elseif (! empty($child)) {
                    $return = array_merge_recursive($return, $child);
                }
            }
        }
        return $return;
    }