/** * Iterates through the given files and builds the structure.xml file. * * @param DocBlox_Parser_Files $files A files container to parse. * * @api * * @return bool|string */ public function parseFiles(DocBlox_Parser_Files $files) { $timer = microtime(true); $dom = new DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $dom->loadXML('<project version="' . DocBlox_Core_Abstract::VERSION . '" ' . 'title="' . addslashes($this->getTitle()) . '"></project>'); $paths = $files->getFiles(); $this->log('Starting to process ' . count($paths) . ' files') . PHP_EOL; $this->log(' Project root is: ' . $files->getProjectRoot()) . PHP_EOL; $this->log(' Ignore paths are: ' . implode(', ', $files->getIgnorePatterns())) . PHP_EOL; if (count($paths) < 1) { throw new DocBlox_Parser_Exception('No files were found', DocBlox_Parser_Exception::NO_FILES_FOUND); } foreach ($paths as $file) { $xml = $this->parseFile($file); if ($xml === false) { continue; } $dom_file = new DOMDocument(); $dom_file->loadXML(trim($xml)); // merge generated XML document into the main document $xpath = new DOMXPath($dom_file); $qry = $xpath->query('/*'); for ($i = 0; $i < $qry->length; $i++) { $dom->documentElement->appendChild($dom->importNode($qry->item($i), true)); } } $this->buildPackageTree($dom); $this->buildNamespaceTree($dom); $this->buildMarkerList($dom); $xml = $dom->saveXML(); // Visibility rules $this->log('--'); $this->log('Applying visibility rules'); $dom = new DOMDocument(); $dom->loadXML($xml); $visibilityQry = '//*['; $accessQry = '//tag[@name=\'access\' and ('; foreach ($this->visibility as $key => $vis) { $visibilityQry .= '(@visibility!=\'' . $vis . '\')'; $accessQry .= '@description!=\'' . $vis . '\''; if ($key + 1 < count($this->visibility)) { $visibilityQry .= ' and '; $accessQry .= ' and '; } } $visibilityQry .= ']'; $accessQry .= ')]'; $qry = '(' . $visibilityQry . ') | (' . $accessQry . ')'; $xpath = new DOMXPath($dom); $nodes = $xpath->query($qry); foreach ($nodes as $node) { if ($node->nodeName == 'tag' && $node->parentNode->parentNode->parentNode) { $remove = $node->parentNode->parentNode; $node->parentNode->parentNode->parentNode->removeChild($remove); } else { $node->parentNode->removeChild($node); } } $xml = $dom->saveXML(); $this->log('--'); $this->log('Elapsed time to parse all files: ' . round(microtime(true) - $timer, 2) . 's'); $this->log('Peak memory usage: ' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'M'); return $xml; }