,
- $this->texy->addHandler('beforeParse', function($texy, &$text, $singleLine) {
- $text = preg_replace('~(.+?)
~', '#code#\\1#/code#', $text);
- });
- $this->texy->registerLinePattern(
- function($parser, $matches, $name) use ($fshl) {
- return \TexyHtml::el('code', $fshl->highlight($matches[1]));
- },
- '~#code#(.+?)#/code#~',
- 'codeInlineSyntax'
- );
- $this->texy->registerBlockPattern(
- function($parser, $matches, $name) use ($fshl) {
- if ('code' === $matches[1]) {
- $lines = array_filter(explode("\n", $matches[2]));
- if (!empty($lines)) {
- $firstLine = array_shift($lines);
-
- $indent = '';
- $li = 0;
-
- while (isset($firstLine[$li]) && preg_match('~\s~', $firstLine[$li])) {
- foreach ($lines as $line) {
- if (!isset($line[$li]) || $firstLine[$li] !== $line[$li]) {
- break 2;
- }
- }
-
- $indent .= $firstLine[$li++];
- }
-
- if (!empty($indent)) {
- $matches[2] = str_replace(
- "\n" . $indent,
- "\n",
- 0 === strpos($matches[2], $indent) ? substr($matches[2], $li) : $matches[2]
- );
- }
- }
-
- $content = $fshl->highlight($matches[2]);
- } else {
- $content = htmlspecialchars($matches[2]);
- }
-
- $content = $parser->getTexy()->protect($content, \Texy::CONTENT_BLOCK);
- return \TexyHtml::el('pre', $content);
- },
- '~<(code|pre)>(.+?)\1>~s',
- 'codeBlockSyntax'
- );
-
- // Common operations
- $this->registerHelperLoader('Nette\Templating\Helpers::loader');
-
- // PHP source highlight
- $this->registerHelper('highlightPHP', function($source, $context) use ($that, $fshl) {
- return $that->resolveLink($that->getTypeName($source), $context) ?: $fshl->highlight((string) $source);
- });
- $this->registerHelper('highlightValue', function($definition, $context) use ($that) {
- return $that->highlightPHP(preg_replace('~^(?:[ ]{4}|\t)~m', '', $definition), $context);
- });
-
- // Urls
- $this->registerHelper('packageUrl', new Nette\Callback($this, 'getPackageUrl'));
- $this->registerHelper('namespaceUrl', new Nette\Callback($this, 'getNamespaceUrl'));
- $this->registerHelper('groupUrl', new Nette\Callback($this, 'getGroupUrl'));
- $this->registerHelper('classUrl', new Nette\Callback($this, 'getClassUrl'));
- $this->registerHelper('methodUrl', new Nette\Callback($this, 'getMethodUrl'));
- $this->registerHelper('propertyUrl', new Nette\Callback($this, 'getPropertyUrl'));
- $this->registerHelper('constantUrl', new Nette\Callback($this, 'getConstantUrl'));
- $this->registerHelper('functionUrl', new Nette\Callback($this, 'getFunctionUrl'));
- $this->registerHelper('elementUrl', new Nette\Callback($this, 'getElementUrl'));
- $this->registerHelper('sourceUrl', new Nette\Callback($this, 'getSourceUrl'));
- $this->registerHelper('manualUrl', new Nette\Callback($this, 'getManualUrl'));
-
- // Packages & namespaces
- $this->registerHelper('packageLinks', new Nette\Callback($this, 'getPackageLinks'));
- $this->registerHelper('namespaceLinks', new Nette\Callback($this, 'getNamespaceLinks'));
- $this->registerHelper('subgroupName', function($groupName) {
- if ($pos = strrpos($groupName, '\\')) {
- return substr($groupName, $pos + 1);
- }
- return $groupName;
- });
-
- // Types
- $this->registerHelper('typeLinks', new Nette\Callback($this, 'getTypeLinks'));
-
- // Docblock descriptions
- $this->registerHelper('description', function($annotation, $context) use ($that) {
- $description = trim(strpbrk($annotation, "\n\r\t $"));
-
- if ($context instanceof ReflectionParameter) {
- $description = preg_replace('~^(\\$' . $context->getName() . '(?:,\\.{3})?)(\s+|$)~i', '\\2', $description, 1);
- $context = $context->getDeclaringFunction();
- }
- return $that->doc($description, $context);
- });
- $this->registerHelper('shortDescription', function($element, $block = false) use ($that) {
- return $that->doc($element->getShortDescription(), $element, $block);
- });
- $this->registerHelper('longDescription', function($element) use ($that) {
- $long = $element->getLongDescription();
-
- // Merge lines
- $long = preg_replace_callback('~(?:<(code|pre)>.+?\1>)|([^<]*)~s', function($matches) {
- return !empty($matches[2])
- ? preg_replace('~\n(?:\t|[ ])+~', ' ', $matches[2])
- : $matches[0];
- }, $long);
-
- return $that->doc($long, $element, true);
- });
-
- // Individual annotations processing
- $this->registerHelper('annotation', function($value, $name, $context) use ($that, $generator) {
- switch ($name) {
- case 'param':
- case 'return':
- case 'throws':
- $description = $that->description($value, $context);
- return sprintf('%s
%s', $that->getTypeLinks($value, $context), $description ? '
' . $description : '');
- case 'license':
- list($url, $description) = $that->split($value);
- return $that->link($url, $description ?: $url);
- case 'link':
- list($url, $description) = $that->split($value);
- if (Nette\Utils\Validators::isUrl($url)) {
- return $that->link($url, $description ?: $url);
- }
- break;
- case 'see':
- $doc = array();
- foreach (preg_split('~\\s*,\\s*~', $value) as $link) {
- if (null !== $generator->resolveElement($link, $context)) {
- $doc[] = sprintf('%s
', $that->getTypeLinks($link, $context));
- } else {
- $doc[] = $that->doc($link, $context);
- }
- }
- return implode(', ', $doc);
- case 'uses':
- case 'usedby':
- list($link, $description) = $that->split($value);
- $separator = $context instanceof ReflectionClass || !$description ? ' ' : '
';
- if (null !== $generator->resolveElement($link, $context)) {
- return sprintf('%s
%s%s', $that->getTypeLinks($link, $context), $separator, $description);
- }
- break;
- default:
- break;
- }
-
- // Default
- return $that->doc($value, $context);
- });
-
- $todo = $this->config->todo;
- $internal = $this->config->internal;
- $this->registerHelper('annotationFilter', function(array $annotations, array $filter = array()) use ($todo, $internal) {
- // Filtered, unsupported or deprecated annotations
- static $filtered = array(
- 'package', 'subpackage', 'property', 'property-read', 'property-write', 'method', 'abstract',
- 'access', 'final', 'filesource', 'global', 'name', 'static', 'staticvar'
- );
- foreach ($filtered as $annotation) {
- unset($annotations[$annotation]);
- }
-
- // Custom filter
- foreach ($filter as $annotation) {
- unset($annotations[$annotation]);
- }
-
- // Show/hide internal
- if (!$internal) {
- unset($annotations['internal']);
- }
-
- // Show/hide tasks
- if (!$todo) {
- unset($annotations['todo']);
- }
-
- return $annotations;
- });
-
- $this->registerHelper('annotationSort', function(array $annotations) {
- uksort($annotations, function($one, $two) {
- static $order = array(
- 'deprecated' => 0, 'category' => 1, 'copyright' => 2, 'license' => 3, 'author' => 4, 'version' => 5,
- 'since' => 6, 'see' => 7, 'uses' => 8, 'usedby' => 9, 'link' => 10, 'internal' => 11,
- 'example' => 12, 'tutorial' => 13, 'todo' => 14
- );
-
- if (isset($order[$one], $order[$two])) {
- return $order[$one] - $order[$two];
- } elseif (isset($order[$one])) {
- return -1;
- } elseif (isset($order[$two])) {
- return 1;
- } else {
- return strcasecmp($one, $two);
- }
- });
- return $annotations;
- });
-
- $this->registerHelper('annotationBeautify', function($annotation) {
- static $names = array(
- 'usedby' => 'Used by'
- );
-
- if (isset($names[$annotation])) {
- return $names[$annotation];
- }
-
- return Nette\Utils\Strings::firstUpper($annotation);
- });
-
- // Static files versioning
- $destination = $this->config->destination;
- $this->registerHelper('staticFile', function($name) use ($destination) {
- static $versions = array();
-
- $filename = $destination . DIRECTORY_SEPARATOR . $name;
- if (!isset($versions[$filename]) && is_file($filename)) {
- $versions[$filename] = sprintf('%u', crc32(file_get_contents($filename)));
- }
- if (isset($versions[$filename])) {
- $name .= '?' . $versions[$filename];
- }
- return $name;
- });
-
- // Source anchors
- $this->registerHelper('sourceAnchors', function($source) {
- // Classes, interfaces, traits and exceptions
- $source = preg_replace_callback('~((?:class|interface|trait)\\s+)(\\w+)~i', function($matches) {
- $link = sprintf('%1$s', $matches[2]);
- return $matches[1] . $link;
- }, $source);
-
- // Methods and functions
- $source = preg_replace_callback('~(function\\s+)(\\w+)~i', function($matches) {
- $link = sprintf('%1$s', $matches[2]);
- return $matches[1] . $link;
- }, $source);
-
- // Constants
- $source = preg_replace_callback('~(const)(.*?)(;)~is', function($matches) {
- $links = preg_replace_callback('~(\\s|,)([A-Z_]+)(\\s+=)~', function($matches) {
- return $matches[1] . sprintf('%1$s', $matches[2]) . $matches[3];
- }, $matches[2]);
- return $matches[1] . $links . $matches[3];
- }, $source);
-
- // Properties
- $source = preg_replace_callback('~((?:private|protected|public|var|static)\\s+)(.*?)(;)~is', function($matches) {
- $links = preg_replace_callback('~()(\\$\\w+)~i', function($matches) {
- return $matches[1] . sprintf('%1$s', $matches[2]);
- }, $matches[2]);
- return $matches[1] . $links . $matches[3];
- }, $source);
-
- return $source;
- });
-
- $this->registerHelper('urlize', array($this, 'urlize'));
-
- $this->registerHelper('relativePath', array($generator, 'getRelativePath'));
- $this->registerHelper('resolveElement', array($generator, 'resolveElement'));
- $this->registerHelper('getClass', array($generator, 'getClass'));
- }
-
- /**
- * Returns unified type value definition (class name or member data type).
- *
- * @param string $name
- * @param boolean $trimNamespaceSeparator
- * @return string
- */
- public function getTypeName($name, $trimNamespaceSeparator = true)
- {
- static $names = array(
- 'int' => 'integer',
- 'bool' => 'boolean',
- 'double' => 'float',
- 'void' => '',
- 'FALSE' => 'false',
- 'TRUE' => 'true',
- 'NULL' => 'null',
- 'callback' => 'callable'
- );
-
- // Simple type
- if (isset($names[$name])) {
- return $names[$name];
- }
-
- // Class, constant or function
- return $trimNamespaceSeparator ? ltrim($name, '\\') : $name;
- }
-
- /**
- * Returns links for types.
- *
- * @param string $annotation
- * @param \ApiGen\ReflectionElement $context
- * @return string
- */
- public function getTypeLinks($annotation, ReflectionElement $context)
- {
- $links = array();
-
- list($types) = $this->split($annotation);
- if (!empty($types) && '$' === $types{0}) {
- $types = null;
- }
-
- if (empty($types)) {
- $types = 'mixed';
- }
-
- foreach (explode('|', $types) as $type) {
- $type = $this->getTypeName($type, false);
- $links[] = $this->resolveLink($type, $context) ?: $this->escapeHtml(ltrim($type, '\\'));
- }
-
- return implode('|', $links);
- }
-
- /**
- * Returns links for package/namespace and its parent packages.
- *
- * @param string $package
- * @param boolean $last
- * @return string
- */
- public function getPackageLinks($package, $last = true)
- {
- if (empty($this->packages)) {
- return $package;
- }
-
- $links = array();
-
- $parent = '';
- foreach (explode('\\', $package) as $part) {
- $parent = ltrim($parent . '\\' . $part, '\\');
- $links[] = $last || $parent !== $package
- ? $this->link($this->getPackageUrl($parent), $part)
- : $this->escapeHtml($part);
- }
-
- return implode('\\', $links);
- }
-
- /**
- * Returns links for namespace and its parent namespaces.
- *
- * @param string $namespace
- * @param boolean $last
- * @return string
- */
- public function getNamespaceLinks($namespace, $last = true)
- {
- if (empty($this->namespaces)) {
- return $namespace;
- }
-
- $links = array();
-
- $parent = '';
- foreach (explode('\\', $namespace) as $part) {
- $parent = ltrim($parent . '\\' . $part, '\\');
- $links[] = $last || $parent !== $namespace
- ? $this->link($this->getNamespaceUrl($parent), $part)
- : $this->escapeHtml($part);
- }
-
- return implode('\\', $links);
- }
-
- /**
- * Returns a link to a namespace summary file.
- *
- * @param string $namespaceName Namespace name
- * @return string
- */
- public function getNamespaceUrl($namespaceName)
- {
- return sprintf($this->config->template['templates']['main']['namespace']['filename'], $this->urlize($namespaceName));
- }
-
- /**
- * Returns a link to a package summary file.
- *
- * @param string $packageName Package name
- * @return string
- */
- public function getPackageUrl($packageName)
- {
- return sprintf($this->config->template['templates']['main']['package']['filename'], $this->urlize($packageName));
- }
-
- /**
- * Returns a link to a group summary file.
- *
- * @param string $groupName Group name
- * @return string
- */
- public function getGroupUrl($groupName)
- {
- if (!empty($this->packages)) {
- return $this->getPackageUrl($groupName);
- }
-
- return $this->getNamespaceUrl($groupName);
- }
-
- /**
- * Returns a link to class summary file.
- *
- * @param string|\ApiGen\ReflectionClass $class Class reflection or name
- * @return string
- */
- public function getClassUrl($class)
- {
- $className = $class instanceof ReflectionClass ? $class->getName() : $class;
- return sprintf($this->config->template['templates']['main']['class']['filename'], $this->urlize($className));
- }
-
- /**
- * Returns a link to method in class summary file.
- *
- * @param \ApiGen\ReflectionMethod $method Method reflection
- * @param \ApiGen\ReflectionClass $class Method declaring class
- * @return string
- */
- public function getMethodUrl(ReflectionMethod $method, ReflectionClass $class = null)
- {
- $className = null !== $class ? $class->getName() : $method->getDeclaringClassName();
- return $this->getClassUrl($className) . '#' . ($method->isMagic() ? 'm' : '') . '_' . ($method->getOriginalName() ?: $method->getName());
- }
-
- /**
- * Returns a link to property in class summary file.
- *
- * @param \ApiGen\ReflectionProperty $property Property reflection
- * @param \ApiGen\ReflectionClass $class Property declaring class
- * @return string
- */
- public function getPropertyUrl(ReflectionProperty $property, ReflectionClass $class = null)
- {
- $className = null !== $class ? $class->getName() : $property->getDeclaringClassName();
- return $this->getClassUrl($className) . '#' . ($property->isMagic() ? 'm' : '') . '$' . $property->getName();
- }
-
- /**
- * Returns a link to constant in class summary file or to constant summary file.
- *
- * @param \ApiGen\ReflectionConstant $constant Constant reflection
- * @return string
- */
- public function getConstantUrl(ReflectionConstant $constant)
- {
- // Class constant
- if ($className = $constant->getDeclaringClassName()) {
- return $this->getClassUrl($className) . '#' . $constant->getName();
- }
- // Constant in namespace or global space
- return sprintf($this->config->template['templates']['main']['constant']['filename'], $this->urlize($constant->getName()));
- }
-
- /**
- * Returns a link to function summary file.
- *
- * @param \ApiGen\ReflectionFunction $function Function reflection
- * @return string
- */
- public function getFunctionUrl(ReflectionFunction $function)
- {
- return sprintf($this->config->template['templates']['main']['function']['filename'], $this->urlize($function->getName()));
- }
-
- /**
- * Returns a link to element summary file.
- *
- * @param \ApiGen\ReflectionElement $element Element reflection
- * @return string
- */
- public function getElementUrl(ReflectionElement $element)
- {
- if ($element instanceof ReflectionClass) {
- return $this->getClassUrl($element);
- } elseif ($element instanceof ReflectionMethod) {
- return $this->getMethodUrl($element);
- } elseif ($element instanceof ReflectionProperty) {
- return $this->getPropertyUrl($element);
- } elseif ($element instanceof ReflectionConstant) {
- return $this->getConstantUrl($element);
- } elseif ($element instanceof ReflectionFunction) {
- return $this->getFunctionUrl($element);
- }
- }
-
- /**
- * Returns a link to a element source code.
- *
- * @param \ApiGen\ReflectionElement $element Element reflection
- * @param boolean $withLine Include file line number into the link
- * @return string
- */
- public function getSourceUrl(ReflectionElement $element, $withLine = true)
- {
- if ($element instanceof ReflectionClass || $element instanceof ReflectionFunction || ($element instanceof ReflectionConstant && null === $element->getDeclaringClassName())) {
- $elementName = $element->getName();
-
- if ($element instanceof ReflectionClass) {
- $file = 'class-';
- } elseif ($element instanceof ReflectionConstant) {
- $file = 'constant-';
- } elseif ($element instanceof ReflectionFunction) {
- $file = 'function-';
- }
- } else {
- $elementName = $element->getDeclaringClassName();
- $file = 'class-';
- }
-
- $file .= $this->urlize($elementName);
-
- $lines = null;
- if ($withLine) {
- $lines = $element->getStartLine() !== $element->getEndLine() ? sprintf('%s-%s', $element->getStartLine(), $element->getEndLine()) : $element->getStartLine();
- }
-
- return sprintf($this->config->template['templates']['main']['source']['filename'], $file) . (null !== $lines ? '#' . $lines : '');
- }
-
- /**
- * Returns a link to a element documentation at php.net.
- *
- * @param \ApiGen\ReflectionBase $element Element reflection
- * @return string
- */
- public function getManualUrl(ReflectionBase $element)
- {
- static $manual = 'http://php.net/manual';
- static $reservedClasses = array('stdClass', 'Closure', 'Directory');
-
- // Extension
- if ($element instanceof ReflectionExtension) {
- $extensionName = strtolower($element->getName());
- if ('core' === $extensionName) {
- return $manual;
- }
-
- if ('date' === $extensionName) {
- $extensionName = 'datetime';
- }
-
- return sprintf('%s/book.%s.php', $manual, $extensionName);
- }
-
- // Class and its members
- $class = $element instanceof ReflectionClass ? $element : $element->getDeclaringClass();
-
- if (in_array($class->getName(), $reservedClasses)) {
- return $manual . '/reserved.classes.php';
- }
-
- $className = strtolower($class->getName());
- $classUrl = sprintf('%s/class.%s.php', $manual, $className);
- $elementName = strtolower(strtr(ltrim($element->getName(), '_'), '_', '-'));
-
- if ($element instanceof ReflectionClass) {
- return $classUrl;
- } elseif ($element instanceof ReflectionMethod) {
- return sprintf('%s/%s.%s.php', $manual, $className, $elementName);
- } elseif ($element instanceof ReflectionProperty) {
- return sprintf('%s#%s.props.%s', $classUrl, $className, $elementName);
- } elseif ($element instanceof ReflectionConstant) {
- return sprintf('%s#%s.constants.%s', $classUrl, $className, $elementName);
- }
- }
-
- /**
- * Tries to parse a definition of a class/method/property/constant/function and returns the appropriate link if successful.
- *
- * @param string $definition Definition
- * @param \ApiGen\ReflectionElement $context Link context
- * @return string|null
- */
- public function resolveLink($definition, ReflectionElement $context)
- {
- if (empty($definition)) {
- return null;
- }
-
- $suffix = '';
- if ('[]' === substr($definition, -2)) {
- $definition = substr($definition, 0, -2);
- $suffix = '[]';
- }
-
- $element = $this->generator->resolveElement($definition, $context, $expectedName);
- if (null === $element) {
- return $expectedName;
- }
-
- $classes = array();
- if ($element->isDeprecated()) {
- $classes[] = 'deprecated';
- }
- if (!$element->isValid()) {
- $classes[] = 'invalid';
- }
-
- if ($element instanceof ReflectionClass) {
- $link = $this->link($this->getClassUrl($element), $element->getName(), true, $classes);
- } elseif ($element instanceof ReflectionConstant && null === $element->getDeclaringClassName()) {
- $text = $element->inNamespace()
- ? $this->escapeHtml($element->getNamespaceName()) . '\\' . $this->escapeHtml($element->getShortName()) . ''
- : '' . $this->escapeHtml($element->getName()) . '';
- $link = $this->link($this->getConstantUrl($element), $text, false, $classes);
- } elseif ($element instanceof ReflectionFunction) {
- $link = $this->link($this->getFunctionUrl($element), $element->getName() . '()', true, $classes);
- } else {
- $text = $this->escapeHtml($element->getDeclaringClassName());
- if ($element instanceof ReflectionProperty) {
- $url = $this->propertyUrl($element);
- $text .= '::$' . $this->escapeHtml($element->getName()) . '';
- } elseif ($element instanceof ReflectionMethod) {
- $url = $this->methodUrl($element);
- $text .= '::' . $this->escapeHtml($element->getName()) . '()';
- } elseif ($element instanceof ReflectionConstant) {
- $url = $this->constantUrl($element);
- $text .= '::' . $this->escapeHtml($element->getName()) . '';
- }
-
- $link = $this->link($url, $text, false, $classes);
- }
-
- return sprintf('%s
', $link . $suffix);
- }
-
- /**
- * Resolves links in documentation.
- *
- * @param string $text Processed documentation text
- * @param \ApiGen\ReflectionElement $context Reflection object
- * @return string
- */
- private function resolveLinks($text, ReflectionElement $context)
- {
- $that = $this;
- return preg_replace_callback('~{@(?:link|see)\\s+([^}]+)}~', function ($matches) use ($context, $that) {
- // Texy already added so it has to be stripped
- list($url, $description) = $that->split(strip_tags($matches[1]));
- if (Nette\Utils\Validators::isUrl($url)) {
- return $that->link($url, $description ?: $url);
- }
- return $that->resolveLink($matches[1], $context) ?: $matches[1];
- }, $text);
- }
-
- /**
- * Resolves internal annotation.
- *
- * @param string $text
- * @return string
- */
- private function resolveInternal($text)
- {
- $internal = $this->config->internal;
- return preg_replace_callback('~\\{@(\\w+)(?:(?:\\s+((?>(?R)|[^{}]+)*)\\})|\\})~', function($matches) use ($internal) {
- // Replace only internal
- if ('internal' !== $matches[1]) {
- return $matches[0];
- }
- return $internal && isset($matches[2]) ? $matches[2] : '';
- }, $text);
- }
-
- /**
- * Formats text as documentation block or line.
- *
- * @param string $text Text
- * @param \ApiGen\ReflectionElement $context Reflection object
- * @param boolean $block Parse text as block
- * @return string
- */
- public function doc($text, ReflectionElement $context, $block = false)
- {
- return $this->resolveLinks($this->texy->process($this->resolveInternal($text), !$block), $context);
- }
-
- /**
- * Parses annotation value.
- *
- * @param string $value
- * @return array
- */
- public function split($value)
- {
- return preg_split('~\s+|$~', $value, 2);
- }
-
- /**
- * Returns link.
- *
- * @param string $url
- * @param string $text
- * @param boolean $escape If the text should be escaped
- * @param array $classes List of classes
- * @return string
- */
- public function link($url, $text, $escape = true, array $classes = array())
- {
- $class = !empty($classes) ? sprintf(' class="%s"', implode(' ', $classes)) : '';
- return sprintf('%s', $url, $class, $escape ? $this->escapeHtml($text) : $text);
- }
-
- /**
- * Converts string to url safe characters.
- *
- * @param string $string
- * @return string
- */
- public function urlize($string)
- {
- return preg_replace('~[^\w]~', '.', $string);
- }
-}
diff --git a/apigen/ApiGen/Tree.php b/apigen/ApiGen/Tree.php
deleted file mode 100644
index 01f47b6b76b..00000000000
--- a/apigen/ApiGen/Tree.php
+++ /dev/null
@@ -1,90 +0,0 @@
-setPrefixPart(RecursiveTreeIterator::PREFIX_END_HAS_NEXT, self::HAS_NEXT);
- $this->setPrefixPart(RecursiveTreeIterator::PREFIX_END_LAST, self::LAST);
- $this->rewind();
-
- $this->reflections = $reflections;
- }
-
- /**
- * Returns if the current item has a sibling on the same level.
- *
- * @return boolean
- */
- public function hasSibling()
- {
- $prefix = $this->getPrefix();
- return !empty($prefix) && self::HAS_NEXT === substr($prefix, -1);
- }
-
- /**
- * Returns the current reflection.
- *
- * @return \ApiGen\Reflection
- * @throws \UnexpectedValueException If current is not reflection array.
- */
- public function current()
- {
- $className = $this->key();
- if (!isset($this->reflections[$className])) {
- throw new RuntimeException(sprintf('Class "%s" is not in the reflection array', $className));
- }
-
- return $this->reflections[$className];
- }
-}
diff --git a/apigen/CHANGELOG.md b/apigen/CHANGELOG.md
deleted file mode 100644
index a836e552830..00000000000
--- a/apigen/CHANGELOG.md
+++ /dev/null
@@ -1,128 +0,0 @@
-## ApiGen 2.8.0 (2012-09-08) ##
-
-* Added support for @property and @method annotations
-* Added support for variable length parameters
-* Enabled selection of more rows in source code
-* Templates can specify minimum and maximum required ApiGen version
-* Added template for 404 page
-* Improved support for malformed @param annotations
-* Fixed excluding files and directories and detecting non accessible files and directories
-* Fixed internal error when no timezone is specified in php.ini
-* Fixed autocomplate in Opera browser
-* Nette framework updated to version 2.0.5
-* TokenReflection library updated to version 1.3.1
-* FSHL library updated to version 2.1.0
-
-## ApiGen 2.7.0 (2012-07-15) ##
-
-* Support of custom template macros and helpers
-* Information about overridden methods in class method list
-* Template UX fixes
-* Fixed bugs causing ApiGen to crash
-* TokenReflection library updated to version 1.3.0
-* Bootstrap2 based template
-* Removed template with frames
-
-## ApiGen 2.6.1 (2012-03-27) ##
-
-* Fixed resolving element names in annotations
-* Nette framework updated to version 2.0.1
-* TokenReflection library updated to version 1.2.2
-
-## ApiGen 2.6.0 (2012-03-11) ##
-
-* Better error reporting, especially about duplicate classes, functions and constants
-* Character set autodetection is on by default
-* Changed visualization of deprecated elements
-* Improved packages parsing and visualization
-* Improved @license and @link visualization
-* Improved `````` parsing
-* Added option ```--extensions``` to specify file extensions of parsed files
-* Minor visualization improvements
-* Fixed autocomplete for classes in namespaces
-* TokenReflection library updated to version 1.2.0
-
-## ApiGen 2.5.0 (2012-02-12) ##
-
-* Added option ```--groups``` for grouping classes, interfaces, traits and exceptions in the menu
-* Added option ```--autocomplete``` for choosing elements in the search autocomplete
-* Inheriting some annotations from the file-level docblock
-* @uses annotations create a @usedby annotation in the target documentation
-* Added warning for unknown options
-* Added support of comma-separated values for @see
-* Changed all path options to be relative to the configuration file
-* Fixed dependencies check
-* Nette framework updated to 2.0.0 stable version
-* TokenReflection library updated to version 1.1.0
-
-## ApiGen 2.4.1 (2012-01-25) ##
-
-* TokenReflection library updated to version 1.0.2
-* Nette framework updated to version 2.0.0RC1
-
-## ApiGen 2.4.0 (2011-12-24) ##
-
-* TokenReflection library updated to version 1.0.0
-* Fixed support for older PHP versions of the 5.3 branch
-* Option ```templateConfig``` is relative to the config file (was relative to cwd)
-
-## ApiGen 2.3.0 (2011-11-13) ##
-
-* Added support for default configuration file
-* Added link to download documentation as ZIP archive
-* Added option ```--charset``` and autodetection of charsets
-* Added support for @ignore annotation
-* Added PHAR support
-* Added support for ClassName[]
-* Added memory usage reporting in progressbar
-* Improved templates for small screens
-* Changed option name ```--undocumented``` to ```--report```
-* FSHL library updated to version 2.0.1
-
-## ApiGen 2.2.1 (2011-10-26) ##
-
-* Fixed processing of magic constants
-* Fixed resize.png
-* TokenReflection library updated to version 1.0.0RC2
-
-## ApiGen 2.2.0 (2011-10-16) ##
-
-* Added an option to check for updates
-* Added an option to initially display elements in alphabetical order
-* Added an option to generate the robots.txt file
-* Added required extensions check
-* Changed reporting of undocumented elements to the checkstyle format
-* Improved deprecated elements highlighting
-* Highlighting the linked source code line
-* Unknown annotations are sorted alphabetically
-* Fixed class parameter description parsing
-* Fixed command line options parsing
-* Fixed include path setting of the GitHub version
-* Fixed frames template
-
-## ApiGen 2.1.0 (2011-09-04) ##
-
-* Experimental support of PHP 5.4 traits
-* Added option ```--colors```
-* Added template with frames
-* Added templates option to make element details expanded by default
-
-## ApiGen 2.0.3 (2011-08-22) ##
-
-* @param, @return and @throw annotations are inherited
-
-## ApiGen 2.0.2 (2011-07-21) ##
-
-* Fixed inherited methods listing
-* Interfaces are not labeled "Abstract interface"
-* Fixed Google CSE ID validation
-* Fixed filtering by ```--exclude``` and ```--skip-doc-path```
-* Fixed exception output when using ```--debug```
-
-## ApiGen 2.0.1 (2011-07-17) ##
-
-* Updated TokenReflection library to 1.0.0beta5
-* Requires FSHL 2.0.0RC
-* Fixed url in footer
-
-## ApiGen 2.0.0 (2011-06-28) ##
diff --git a/apigen/LICENSE.md b/apigen/LICENSE.md
deleted file mode 100644
index afe8631e4e6..00000000000
--- a/apigen/LICENSE.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licenses #
-
-You may use ApiGen under the terms of either the New BSD License or the GNU General Public License (GPL) version 2 or 3.
-
-The BSD License is recommended for most projects. It is easy to understand and it places almost no restrictions on what you can do with the framework. If the GPL fits better to your project, you can use the framework under this license.
-
-You don't have to notify anyone which license you are using. You can freely use ApiGen in commercial projects as long as the copyright header remains intact.
-
-## New BSD License ##
-
-Copyright (c) 2010 [David Grudl](http://davidgrudl.com)
-Copyright (c) 2011-2012 [Jaroslav Hanslík](https://github.com/kukulich)
-Copyright (c) 2011-2012 [Ondřej Nešpor](https://github.com/Andrewsville)
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
-* Neither the name of "ApiGen" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-## GNU General Public License ##
-
-GPL licenses are very very long, so instead of including them here we offer you URLs with full text:
-
-* [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
-* [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/apigen/README.md b/apigen/README.md
deleted file mode 100644
index 14634f8959b..00000000000
--- a/apigen/README.md
+++ /dev/null
@@ -1,285 +0,0 @@
-# Welcome to ApiGen #
-
-ApiGen is the tool for creating professional API documentation from PHP source code, similar to discontinued phpDocumentor/phpDoc.
-
-ApiGen has support for PHP 5.3 namespaces, packages, linking between documentation, cross referencing to PHP standard classes and general documentation, creation of highlighted source code and experimental support for PHP 5.4 **traits**.
-
-## Support & Bug Reports ##
-
-For all support questions please use our [mailing list](https://groups.google.com/group/apigen). For bug reports and issues the [issue tracker](https://github.com/apigen/apigen/issues) is available. Changes between versions are described in the [change log](https://github.com/apigen/apigen/blob/master/CHANGELOG.md).
-
-## Features ##
-
-* Our own [TokenReflection library](https://github.com/Andrewsville/PHP-Token-Reflection) is used to describe the source code. It is **safe** (documented source code does not get included and thus parsed) and **simple** (you do not need to include or autoload all libraries you use in your source code).
-* Detailed documentation of classes, functions and constants.
-* Highlighted source code.
-* Support of namespaces and packages with subpackages.
-* Experimental support of traits.
-* A page with trees of classes, interfaces, traits and exceptions.
-* A page with a list of deprecated elements.
-* A page with Todo tasks.
-* Link to download documentation as ZIP archive.
-* Checkstyle report of poorly documented elements.
-* Support for docblock templates.
-* Support for @inheritdoc.
-* Support for {@link}.
-* Active links in @see and @uses tags.
-* Documentation of used internal PHP classes.
-* Links to the start line in the highlighted source code for every described element.
-* List of direct and indirect known subclasses, implementers and users for every class/interface/trait/exception.
-* Check for a new version.
-* Google CSE support with suggest.
-* Google Analytics support.
-* Support for multiple/custom templates.
-* Sitemap and opensearch support.
-* Support for different charsets and line endings.
-* Lots of configuration options (see below).
-
-## Installation ##
-
-The preferred installation way is using the PEAR package but there are three more ways how to install ApiGen.
-
-
-### PEAR ###
-
-PEAR is a distribution system for PHP packages. It is bundled with PHP since the 4.3 version and it is easy to use.
-
-The PEAR package contains only ApiGen itself. Its dependencies (Nette, Texy, FSHL and TokenReflection) have to be installed separately. But do not panic, the PEAR installer can take care of it.
-
-The easiest way is to use the PEAR auto discovery feature. In that case all you have to do is to type two commands.
-
-```
- pear config-set auto_discover 1
- pear install pear.apigen.org/apigen
-```
-
-If you don't want to use the auto discovery, you have to add PEAR channels of all ApiGen libraries manually. In this case you can install ApiGen by typing these commands.
-
-```
- pear channel-discover pear.apigen.org
- pear channel-discover pear.nette.org
- pear channel-discover pear.texy.info
- pear channel-discover pear.kukulich.cz
- pear channel-discover pear.andrewsville.cz
-
- pear install apigen/ApiGen
-```
-
-If you encounter a message like `WARNING: channel "pear.apigen.org" has updated its protocols, use "pear channel-update pear.apigen.org" to update`, you need to tell PEAR to update its information about the ApiGen channel using the suggested command.
-
-```
-pear channel-update pear.apigen.org
-```
-
-### Standalone package ###
-
-Using the standalone package is even easier than using the PEAR installer but it does not handle updates automatically.
-
-To download the actual release visit the [Downloads section](https://github.com/apigen/apigen/downloads). There you find separate packages for each release in two formats - zip and tar.gz. These packages are prepared by the ApiGen team and are truly standalone; they contain all required libraries in appropriate versions. You just need to extract the contents of an archive and you can start using ApiGen.
-
-### GitHub built archive ###
-
-GitHub allows you to download any repository as a zip or tar.gz archive. You can use this feature to download an archive with the current version of ApiGen. However this approach has one disadvantage. Such archive (in contrast to the standalone packages) does not contain required libraries. They are included as git submodules in the repository and GitHub simply ignores them when generating the archive. It means that you will have to obtain required libraries manually.
-
-### Cloning the repository ###
-
-The last way how to install ApiGen is simply to clone our repository. If you do so, remember to fetch and rebase to get new versions and do not forget to update submodules in the libs directory.
-
-## Usage ##
-
-```
- apigen --config [options]
- apigen --source --destination [options]
-```
-
-As you can see, you can use ApiGen either by providing individual parameters via the command line or using a config file. Moreover you can combine the two methods and the command line parameters will have precedence over those in the config file.
-
-Every configuration option has to be followed by its value. And it is exactly the same to write ```--config=file.conf``` and ```--config file.conf```. The only exceptions are boolean options (those with yes|no values). When using these options on the command line you do not have to provide the "yes" value explicitly. If ommited, it is assumed that you wanted to turn the option on. So using ```--debug=yes``` and ```--debug``` does exactly the same (and the opposite is ```--debug=no```).
-
-Some options can have multiple values. To do so, you can either use them multiple times or separate their values by a comma. It means that ```--source=file1.php --source=file2.php``` and ```--source=file1.php,file2.php``` is exactly the same.
-
-### Options ###
-
-```--config|-c ```
-
-Path to the config file.
-
-```--source|-s ``` **required**
-
-Path to the directory or file to be processed. You can use the parameter multiple times to provide a list of directories or files. All types of PHAR archives are supported (requires the PHAR extension). To process gz/bz2 compressed archives you need the appropriate extension (see requirements).
-
-```--destination|-d ``` **required**
-
-Documentation will be generated into this directory.
-
-```--extensions ```
-
-List of allowed file extensions, default is "php".
-
-```--exclude ```
-
-Directories and files matching this file mask will not be parsed. You can exclude for example tests from processing this way. This parameter is case sensitive and can be used multiple times.
-
-```--skip-doc-path ```
-```--skip-doc-prefix ```
-
-Using this parameters you can tell ApiGen not to generate documentation for elements from certain files or with certain name prefix. Such classes will appear in class trees, but will not create a link to their documentation. These parameters are case sensitive and can be used multiple times.
-
-```--charset ```
-
-Character set of source files, default is "auto" that lets ApiGen choose from all supported character sets. However if you use only one characters set across your source files you should set it explicitly to avoid autodetection because it can be tricky (and is not completely realiable). Moreover autodetection slows down the process of generating documentation. You can also use the parameter multiple times to provide a list of all used character sets in your documentation. In that case ApiGen will choose one of provided character sets for each file.
-
-```--main ```
-
-Elements with this name prefix will be considered as the "main project" (the rest will be considered as libraries).
-
-```--title ```
-
-Title of the generated documentation.
-
-```--base-url ```
-
-Documentation base URL used in the sitemap. Only needed if you plan to make your documentation public.
-
-```--google-cse-id ```
-
-If you have a Google CSE ID, the search box will use it when you do not enter an exact class, constant or function name.
-
-```--google-cse-label ```
-
-This will be the default label when using Google CSE.
-
-```--google-analytics ```
-
-A Google Analytics tracking code. If provided, an ansynchronous tracking code will be placed into every generated page.
-
-```--template-config ```
-
-Template config file, default is the config file of ApiGen default template.
-
-```--allowed-html ```
-
-List of allowed HTML tags in documentation separated by comma. Default value is "b,i,a,ul,ol,li,p,br,var,samp,kbd,tt".
-
-```--groups ```
-
-How should elements be grouped in the menu. Possible options are "auto", "namespaces", "packages" and "none". Default value is "auto" (namespaces are used if the source code uses them, packages otherwise).
-
-```--autocomplete ```
-
-List of element types that will appear in the search input autocomplete. Possible values are "classes", "constants", "functions", "methods", "properties" and "classconstants". Default value is "classes,constants,functions".
-
-```--access-levels ```
-
-Access levels of methods and properties that should get their documentation parsed. Default value is "public,protected" (don't generate private class members).
-
-```--internal ```
-
-Generate documentation for elements marked as internal (```@internal``` without description) and display parts of the documentation that are marked as internal (```@internal with description ...``` or inline ```{@internal ...}```), default is "No".
-
-```--php ```
-
-Generate documentation for PHP internal classes, default is "Yes".
-
-```--tree ```
-
-Generate tree view of classes, interfaces, traits and exceptions, default is "Yes".
-
-```--deprecated ```
-
-Generate documentation for deprecated elements, default is "No".
-
-```--todo ```
-
-Generate a list of tasks, default is "No".
-
-```--source-code ```
-
-Generate highlighted source code for user defined elements, default is "Yes".
-
-```--download ```
-
-Add a link to download documentation as a ZIP archive, default is "No".
-
-```--report ```
-
-Save a checkstyle report of poorly documented elements into a file.
-
-```--wipeout ```
-
-Delete files generated in the previous run, default is "Yes".
-
-```--quiet ```
-
-Do not print any messages to the console, default is "No".
-
-```--progressbar ```
-
-Display progressbars, default is "Yes".
-
-```--colors ```
-
-Use colors, default "No" on Windows, "Yes" on other systems. Windows doesn't support colors in console however you can enable it with [Ansicon](http://adoxa.110mb.com/ansicon/).
-
-```--update-check ```
-
-Check for a new version of ApiGen, default is "Yes".
-
-```--debug ```
-
-Display additional information (exception trace) in case of an error, default is "No".
-
-```--help|-h ```
-
-Display the list of possible options.
-
-Only ```--source``` and ```--destination``` parameters are required. You can provide them via command line or a configuration file.
-
-### Config files ###
-
-Instead of providing individual parameters via the command line, you can prepare a config file for later use. You can use all the above listed parameters (with one exception: the ```--config``` option) only without dashes and with an uppercase letter after each dash (so ```--access-level``` becomes ```accessLevel```).
-
-ApiGen uses the [NEON file format](http://ne-on.org) for all its config files. You can try the [online parser](http://ne-on.org) to debug your config files and see how they get parsed.
-
-Then you can call ApiGen with a single parameter ```--config``` specifying the config file to load.
-
-```
- apigen --config [options]
-```
-
-Even when using a config file, you can still provide additional parameters via the command line. Such parameters will have precedence over parameters from the config file.
-
-Keep in mind, that any values in the config file will be **overwritten** by values from the command line. That means that providing the ```--source``` parameter values both in the config file and via the command line will not result in using all the provided values but only those from the command line.
-
-If you provide no command line parameters at all, ApiGen will try to load a default config file called ```apigen.neon``` in the current working directory. If found it will work as if you used the ```--config``` option. Note that when using any command line option, you have to specify the config file if you have one. ApiGen will try to load one automatically only when no command line parameters are used. Option names have to be in camelCase in config files (```--template-config``` on the command line becomes ```templateConfig``` in a config file). You can see a full list of configuration options with short descriptions in the example config file [apigen.neon.example](https://github.com/apigen/apigen/blob/master/apigen.neon.example).
-
-### Example ###
-
-We are generating documentation for the Nella Framework. We want Nette and Doctrine to be parsed as well because we want their classes to appear in class trees, lists of parent classes and their members in lists of inherited properties, methods and constants. However we do not want to generate their full documentation along with highlighted source codes. And we do not want to process any "test" directories, because there might be classes that do not belong to the project actually.
-
-```
- apigen --source ~/nella/Nella --source ~/doctrine2/lib/Doctrine --source ~/doctrine2/lib/vendor --source ~/nette/Nette --skip-doc-path "~/doctrine2/*" --skip-doc-prefix Nette --exclude "*/tests/*" --destination ~/docs/ --title "Nella Framework"
-```
-
-## Requirements ##
-
-ApiGen requires PHP 5.3 or later. Four libraries it uses ([Nette](https://github.com/nette/nette), [Texy](https://github.com/dg/texy), [TokenReflection](https://github.com/Andrewsville/PHP-Token-Reflection) and [FSHL](https://github.com/kukulich/fshl)) require four additional PHP extensions: [tokenizer](http://php.net/manual/book.tokenizer.php), [mbstring](http://php.net/manual/book.mbstring.php), [iconv](http://php.net/manual/book.iconv.php) and [json](http://php.net/manual/book.json.php). For documenting PHAR archives you need the [phar extension](http://php.net/manual/book.phar.php) and for documenting gz or bz2 compressed PHARs, you need the [zlib](http://php.net/manual/book.zlib.php) or [bz2](http://php.net/manual/book.bzip2.php) extension respectively. To generate the ZIP file with documentation you need the [zip extension](http://php.net/manual/book.zip.php).
-
-When generating documentation of large libraries (Zend Framework for example) we recommend not to have the Xdebug PHP extension loaded (it does not need to be used, it significantly slows down the generating process even when only loaded).
-
-## Authors ##
-
-* [Jaroslav Hanslík](https://github.com/kukulich)
-* [Ondřej Nešpor](https://github.com/Andrewsville)
-* [David Grudl](https://github.com/dg)
-
-## Usage examples ##
-
-* [Doctrine](http://www.doctrine-project.org/api/orm/2.2/index.html)
-* [Nette Framework](http://api.nette.org/2.0/)
-* [TokenReflection library](http://andrewsville.github.com/PHP-Token-Reflection/)
-* [FSHL library](http://fshl.kukulich.cz/api/)
-* [Nella Framework](http://api.nellafw.org/)
-* Jyxo PHP Libraries, both [namespaced](http://jyxo.github.com/php/) and [non-namespaced](http://jyxo.github.com/php-no-namespace/)
-
-Besides from these publicly visible examples there are companies that use ApiGen to generate their inhouse documentation: [Medio Interactive](http://www.medio.cz/), [Wikidi](http://wikidi.com/).
\ No newline at end of file
diff --git a/apigen/apigen.bat b/apigen/apigen.bat
deleted file mode 100755
index 9be5228e5dc..00000000000
--- a/apigen/apigen.bat
+++ /dev/null
@@ -1,16 +0,0 @@
-@echo off
-REM ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-REM
-REM Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-REM Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-REM Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-REM
-REM For the full copyright and license information, please view
-REM the file LICENCE.md that was distributed with this source code.
-REM
-
-IF EXIST "@php_bin@" (
- "@php_bin@" "@bin_dir@\apigen" %*
-) ELSE (
- "php.exe" "%~dp0apigen.php" %*
-)
diff --git a/apigen/apigen.neon.example b/apigen/apigen.neon.example
deleted file mode 100644
index e5e0de7f2f4..00000000000
--- a/apigen/apigen.neon.example
+++ /dev/null
@@ -1,67 +0,0 @@
-# Source file or directory to parse
-source:
-# Directory where to save the generated documentation
-destination:
-# List of allowed file extensions
-extensions: [php]
-# Mask to exclude file or directory from processing
-exclude:
-# Don't generate documentation for classes from file or directory with this mask
-skipDocPath:
-# Don't generate documentation for classes with this name prefix
-skipDocPrefix:
-# Character set of source files
-charset: auto
-# Main project name prefix
-main:
-
-# Title of generated documentation
-title:
-# Documentation base URL
-baseUrl:
-# Google Custom Search ID
-googleCseId:
-# Google Custom Search label
-googleCseLabel:
-# Google Analytics tracking code
-googleAnalytics:
-# Template config file
-templateConfig: './templates/default/config.neon'
-# Grouping of classes
-groups: auto
-# List of allowed HTML tags in documentation
-allowedHtml: [b, i, a, ul, ol, li, p, br, var, samp, kbd, tt]
-# Element types for search input autocomplete
-autocomplete: [classes, constants, functions]
-
-# Generate documentation for methods and properties with given access level
-accessLevels: [public, protected]
-# Generate documentation for elements marked as internal and display internal documentation parts
-internal: No
-# Generate documentation for PHP internal classes
-php: Yes
-# Generate tree view of classes, interfaces and exceptions
-tree: Yes
-# Generate documentation for deprecated classes, methods, properties and constants
-deprecated: No
-# Generate documentation of tasks
-todo: No
-# Generate highlighted source code files
-sourceCode: Yes
-# Add a link to download documentation as a ZIP archive
-download: No
-# Save a checkstyle report of poorly documented elements into a file
-report:
-
-# Wipe out the destination directory first
-wipeout: Yes
-# Don't display scanning and generating messages
-quiet: No
-# Display progressbars
-progressbar: Yes
-# Use colors
-colors: No
-# Check for update
-updateCheck: Yes
-# Display additional information in case of an error
-debug: No
diff --git a/apigen/apigen.php b/apigen/apigen.php
deleted file mode 100644
index 2b4aacd0310..00000000000
--- a/apigen/apigen.php
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/env php
-processCliOptions($options);
- $generator = new Generator($config);
-
- // Help
- if ($config->isHelpRequested()) {
- echo $generator->colorize($generator->getHeader());
- echo $generator->colorize($config->getHelp());
- die();
- }
-
- // Prepare configuration
- $config->prepare();
-
- if ($config->debug) {
- Debugger::$onFatalError = array();
- Debugger::enable(Debugger::DEVELOPMENT, false);
- }
-
- $generator->output($generator->getHeader());
-
- // Check for update (only in production mode)
- if ($config->updateCheck && !$config->debug) {
- ini_set('default_socket_timeout', 5);
- $latestVersion = @file_get_contents('http://pear.apigen.org/rest/r/apigen/latest.txt');
- if (false !== $latestVersion && version_compare(trim($latestVersion), Generator::VERSION, '>')) {
- $generator->output(sprintf("New version @header@%s@c available\n\n", $latestVersion));
- }
- }
-
- // Scan
- if (count($config->source) > 1) {
- $generator->output(sprintf("Scanning\n @value@%s@c\n", implode("\n ", $config->source)));
- } else {
- $generator->output(sprintf("Scanning @value@%s@c\n", $config->source[0]));
- }
- if (count($config->exclude) > 1) {
- $generator->output(sprintf("Excluding\n @value@%s@c\n", implode("\n ", $config->exclude)));
- } elseif (!empty($config->exclude)) {
- $generator->output(sprintf("Excluding @value@%s@c\n", $config->exclude[0]));
- }
-
- $parsed = $generator->parse();
-
- if (count($parsed->errors) > 1) {
- $generator->output(sprintf("@error@Found %d errors@c\n\n", count($parsed->errors)));
-
- $no = 1;
- foreach ($parsed->errors as $e) {
-
- if ($e instanceof TokenReflection\Exception\ParseException) {
- $generator->output(sprintf("@error@%d.@c The TokenReflection library threw an exception while parsing the file @value@%s@c.\n", $no, $e->getFileName()));
- if ($config->debug) {
- $generator->output("\nThis can have two reasons: a) the source code in the file is not valid or b) you have just found a bug in the TokenReflection library.\n\n");
- $generator->output("If the license allows it please send the whole file or at least the following fragment describing where exacly is the problem along with the backtrace to apigen@apigen.org. Thank you!\n\n");
-
- $token = $e->getToken();
- $sender = $e->getSender();
- if (!empty($token)) {
- $generator->output(
- sprintf(
- "The cause of the exception \"%s\" was the @value@%s@c token (line @count@%d@c) in following part of %s source code:\n\n",
- $e->getMessage(),
- $e->getTokenName(),
- $e->getExceptionLine(),
- $sender && $sender->getName() ? '@value@' . $sender->getPrettyName() . '@c' : 'the'
- )
- );
- } else {
- $generator->output(
- sprintf(
- "The exception \"%s\" was thrown when processing %s source code:\n\n",
- $e->getMessage(),
- $sender && $sender->getName() ? '@value@' . $sender->getPrettyName() . '@c' : 'the'
- )
- );
- }
-
- $generator->output($e->getSourcePart(true) . "\n\nThe exception backtrace is following:\n\n" . $e->getTraceAsString() . "\n\n");
- }
- } elseif ($e instanceof TokenReflection\Exception\FileProcessingException) {
- $generator->output(sprintf("@error@%d.@c %s\n", $no, $e->getMessage()));
- if ($config->debug) {
- $generator->output("\n" . $e->getDetail() . "\n\n");
- }
- } else {
- $generator->output(sprintf("@error@%d.@c %s\n", $no, $e->getMessage()));
- if ($config->debug) {
- $trace = $e->getTraceAsString();
- while ($e = $e->getPrevious()) {
- $generator->output(sprintf("\n%s", $e->getMessage()));
- $trace = $e->getTraceAsString();
- }
- $generator->output(sprintf("\n%s\n\n", $trace));
- }
- }
-
- $no++;
- }
-
- if (!$config->debug) {
- $generator->output("\nEnable the debug mode (@option@--debug@c) to see more details.\n\n");
- }
- }
-
- $generator->output(sprintf("Found @count@%d@c classes, @count@%d@c constants, @count@%d@c functions and other @count@%d@c used PHP internal classes\n", $parsed->classes, $parsed->constants, $parsed->functions, $parsed->internalClasses));
- $generator->output(sprintf("Documentation for @count@%d@c classes, @count@%d@c constants, @count@%d@c functions and other @count@%d@c used PHP internal classes will be generated\n", $parsed->documentedClasses, $parsed->documentedConstants, $parsed->documentedFunctions, $parsed->documentedInternalClasses));
-
- // Generating
- $generator->output(sprintf("Using template config file @value@%s@c\n", $config->templateConfig));
-
- if ($config->wipeout && is_dir($config->destination)) {
- $generator->output("Wiping out destination directory\n");
- if (!$generator->wipeOutDestination()) {
- throw new \RuntimeException('Cannot wipe out destination directory');
- }
- }
-
- $generator->output(sprintf("Generating to directory @value@%s@c\n", $config->destination));
- $skipping = array_merge($config->skipDocPath, $config->skipDocPrefix);
- if (count($skipping) > 1) {
- $generator->output(sprintf("Will not generate documentation for\n @value@%s@c\n", implode("\n ", $skipping)));
- } elseif (!empty($skipping)) {
- $generator->output(sprintf("Will not generate documentation for @value@%s@c\n", $skipping[0]));
- }
- $generator->generate();
-
- // End
- $end = new \DateTime();
- $interval = $end->diff($start);
- $parts = array();
- if ($interval->h > 0) {
- $parts[] = sprintf('@count@%d@c hours', $interval->h);
- }
- if ($interval->i > 0) {
- $parts[] = sprintf('@count@%d@c min', $interval->i);
- }
- if ($interval->s > 0) {
- $parts[] = sprintf('@count@%d@c sec', $interval->s);
- }
- if (empty($parts)) {
- $parts[] = sprintf('@count@%d@c sec', 1);
- }
-
- $duration = implode(' ', $parts);
- $generator->output(sprintf("Done. Total time: %s, used: @count@%d@c MB RAM\n", $duration, round(memory_get_peak_usage(true) / 1024 / 1024)));
-
-} catch (ConfigException $e) {
- // Configuration error
- echo $generator->colorize($generator->getHeader() . sprintf("\n@error@%s@c\n\n", $e->getMessage()) . $config->getHelp());
-
- die(2);
-} catch (\Exception $e) {
- // Everything else
- if ($config->debug) {
- do {
- echo $generator->colorize(sprintf("\n%s(%d): @error@%s@c", $e->getFile(), $e->getLine(), $e->getMessage()));
- $trace = $e->getTraceAsString();
- } while ($e = $e->getPrevious());
-
- printf("\n\n%s\n", $trace);
- } else {
- echo $generator->colorize(sprintf("\n@error@%s@c\n", $e->getMessage()));
- }
-
- die(1);
-}
\ No newline at end of file
diff --git a/apigen/hook-docs.php b/apigen/hook-docs.php
new file mode 100644
index 00000000000..7de5461a75d
--- /dev/null
+++ b/apigen/hook-docs.php
@@ -0,0 +1,225 @@
+' . $hook . '';
+ }
+
+ public static function process_hooks() {
+ // If we have one, get the PHP files from it.
+ $template_files = self::get_files( '*.php', GLOB_MARK, '../templates/' );
+ $template_files[] = '../includes/wc-template-functions.php';
+ $template_files[] = '../includes/wc-template-hooks.php';
+
+ $shortcode_files = self::get_files( '*.php', GLOB_MARK, '../includes/shortcodes/' );
+ $widget_files = self::get_files( '*.php', GLOB_MARK, '../includes/widgets/' );
+ $admin_files = self::get_files( '*.php', GLOB_MARK, '../includes/admin/' );
+ $class_files = self::get_files( '*.php', GLOB_MARK, '../includes/' );
+ $other_files = array(
+ '../woocommerce.php'
+ );
+
+ self::$files_to_scan = array(
+ 'Template Hooks' => $template_files,
+ 'Shortcode Hooks' => $shortcode_files,
+ 'Widget Hooks' => $widget_files,
+ 'Class Hooks' => $class_files,
+ 'Admin Hooks' => $admin_files,
+ 'Other Hooks' => $other_files,
+ );
+
+ $scanned = array();
+
+ ob_start();
+
+ echo '';
+ echo '
Action and Filter Hook Reference
';
+
+ foreach ( self::$files_to_scan as $heading => $files ) {
+ self::$custom_hooks_found = array();
+
+ foreach ( $files as $f ) {
+ self::$current_file = basename( $f );
+ $tokens = token_get_all( file_get_contents( $f ) );
+ $token_type = false;
+ $current_class = '';
+ $current_function = '';
+
+ if ( in_array( self::$current_file, $scanned ) ) {
+ continue;
+ }
+
+ $scanned[] = self::$current_file;
+
+ foreach ( $tokens as $index => $token ) {
+ if ( is_array( $token ) ) {
+ $trimmed_token_1 = trim( $token[1] );
+ if ( T_CLASS == $token[0] ) {
+ $token_type = 'class';
+ } elseif ( T_FUNCTION == $token[0] ) {
+ $token_type = 'function';
+ } elseif ( 'do_action' === $token[1] ) {
+ $token_type = 'action';
+ } elseif ( 'apply_filters' === $token[1] ) {
+ $token_type = 'filter';
+ } elseif ( $token_type && ! empty( $trimmed_token_1 ) ) {
+ switch ( $token_type ) {
+ case 'class' :
+ $current_class = $token[1];
+ break;
+ case 'function' :
+ $current_function = $token[1];
+ break;
+ case 'filter' :
+ case 'action' :
+ $hook = trim( $token[1], "'" );
+ $loop = 0;
+
+ if ( '_' === substr( $hook, '-1', 1 ) ) {
+ $hook .= '{';
+ $open = true;
+ // Keep adding to hook until we find a comma or colon
+ while ( 1 ) {
+ $loop ++;
+ $next_hook = trim( trim( is_string( $tokens[ $index + $loop ] ) ? $tokens[ $index + $loop ] : $tokens[ $index + $loop ][1], '"' ), "'" );
+
+ if ( in_array( $next_hook, array( '.', '{', '}', '"', "'", ' ' ) ) ) {
+ continue;
+ }
+
+ $hook_first = substr( $next_hook, 0, 1 );
+ $hook_last = substr( $next_hook, -1, 1 );
+
+ if ( in_array( $next_hook, array( ',', ';' ) ) ) {
+ if ( $open ) {
+ $hook .= '}';
+ $open = false;
+ }
+ break;
+ }
+
+ if ( '_' === $hook_first ) {
+ $next_hook = '}' . $next_hook;
+ $open = false;
+ }
+
+ if ( '_' === $hook_last ) {
+ $next_hook .= '{';
+ $open = true;
+ }
+
+ $hook .= $next_hook;
+ }
+ }
+
+ if ( isset( self::$custom_hooks_found[ $hook ] ) ) {
+ self::$custom_hooks_found[ $hook ]['file'][] = self::$current_file;
+ } else {
+ self::$custom_hooks_found[ $hook ] = array(
+ 'line' => $token[2],
+ 'class' => $current_class,
+ 'function' => $current_function,
+ 'file' => array( self::$current_file ),
+ 'type' => $token_type,
+ );
+ }
+ break;
+ }
+ $token_type = false;
+ }
+ }
+ }
+ }
+
+ foreach ( self::$custom_hooks_found as $hook => $details ) {
+ if ( ! strstr( $hook, 'woocommerce' ) && ! strstr( $hook, 'product' ) && ! strstr( $hook, 'wc_' ) ) {
+ unset( self::$custom_hooks_found[ $hook ] );
+ }
+ }
+
+ ksort( self::$custom_hooks_found );
+
+ if ( ! empty( self::$custom_hooks_found ) ) {
+ echo '
' . $heading . '
';
+
+ echo '
Hook | Type | File(s) |
';
+
+ foreach ( self::$custom_hooks_found as $hook => $details ) {
+ echo '
+ ' . self::get_hook_link( $hook, $details ) . ' |
+ ' . $details['type'] . ' |
+ ' . implode( ', ', array_unique( $details['file'] ) ) . ' |
+
' . "\n";
+ }
+
+ echo '
';
+ }
+ }
+
+ echo '