Example #1
0
 /**
  * {@inheritdoc}
  */
 public function process($elongate = false)
 {
     $return = parent::process(true);
     if (isset($return['type'])) {
         $return['entity'] = $return['type'];
         unset($return['type']);
     }
     // Property
     if (preg_match('/(\\w+::)?\\$\\w+/', $return['entity'])) {
         $return['entity_hint'] = 'property';
     } elseif (preg_match('/(\\w+::)?[\\w_]+(\\(\\))/', $return['entity'])) {
         $return['entity_hint'] = 'method';
     } elseif (preg_match('/[\\w_]+/', $return['entity'])) {
         $return['entity_hint'] = 'class';
     } elseif (preg_match('/https?:/', $return['entity'])) {
         // Used @see when @link was more appropriate
         $formatter = ConsoleUtil::formatters();
         Inconsistency::add('Used @' . $this->tag . ' when @link was more appropriate. => ' . $formatter->gold->apply(SystemStore::get('_.current')));
         $return['entity_hint'] = 'uri';
     }
     // Do we need to resolve?
     if (strpos($return['entity'], '::') !== false) {
         list($class, $entity) = explode('::', $return['entity']);
         $class = $this->ancestry->resolveNamespace($class);
         $return['entity'] = implode('::', array($class, $entity));
     } elseif ($return['entity_hint'] === 'method' || $return['entity_hint'] === 'property') {
         $class = $this->ancestry->getClass();
         $return['entity'] = implode('::', array($class, $return['entity']));
     }
     return $return;
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function determine()
 {
     // Where are we?
     SystemStore::add('_.current', preg_replace('/\\[@([^\\]]*)\\]/', ' [@' . $this->tag->getName() . ']', SystemStore::get('_.current')));
     $tag = strtolower($this->tag->getName());
     $this->triggerEvent("vanity.parse.user.description.{$tag}.pre", new EventStore(array('tag' => &$tag, 'ancestry' => $this->ancestry)));
     switch ($tag) {
         case 'example':
             $processed = new ExampleHandler($this->tag, $this->ancestry);
             break;
         case 'inheritdoc':
             $processed = new InheritdocHandler($this->tag, $this->ancestry);
             break;
         case 'internal':
             $processed = new InternalHandler($this->tag, $this->ancestry);
             break;
         case 'link':
             $processed = new LinkHandler($this->tag, $this->ancestry);
             break;
         case 'see':
             $processed = new SeeHandler($this->tag, $this->ancestry);
             break;
         default:
             $processed = new DefaultHandler($this->tag, $this->ancestry);
             break;
     }
     $this->triggerEvent("vanity.parse.user.description.{$tag}.post", new EventStore(array('tag' => &$tag, 'ancestry' => $this->ancestry)));
     return $processed;
 }
Example #3
0
 /**
  * {@inheritdoc}
  */
 public function process($elongate = false)
 {
     // Used @var, which is deprecated
     if (strtolower($this->tag) === 'var') {
         $formatter = ConsoleUtil::formatters();
         Inconsistency::add('The @var keyword is deprecated. Use @type instead. => ' . $formatter->gold->apply(SystemStore::get('_.current')));
     }
     return parent::process(true);
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 public function determine()
 {
     // Where are we?
     SystemStore::add('_.current', preg_replace('/\\[@([^\\]]*)\\]/', ' [@' . $this->tag->getName() . ']', SystemStore::get('_.current')));
     $tag = strtolower($this->tag->getName());
     $this->triggerEvent("vanity.parse.user.tag.{$tag}.pre", new EventStore(array('tag' => &$tag, 'ancestry' => $this->ancestry)));
     switch ($tag) {
         case 'api':
             $processed = new ApiHandler($this->tag, $this->ancestry);
             break;
         case 'author':
             $processed = new AuthorHandler($this->tag, $this->ancestry);
             break;
         case 'copyright':
             $processed = new CopyrightHandler($this->tag, $this->ancestry);
             break;
         case 'deprecated':
         case 'depreciated':
             $processed = new DeprecatedHandler($this->tag, $this->ancestry);
             break;
         case 'dispatches':
         case 'event':
             $processed = new EventHandler($this->tag, $this->ancestry);
             break;
         case 'example':
             $processed = new ExampleHandler($this->tag, $this->ancestry);
             break;
         case 'global':
             $processed = new GlobalHandler($this->tag, $this->ancestry);
             break;
         case 'internal':
             $processed = new InternalHandler($this->tag, $this->ancestry);
             break;
         case 'license':
             $processed = new LicenseHandler($this->tag, $this->ancestry);
             break;
         case 'link':
             $processed = new LinkHandler($this->tag, $this->ancestry);
             break;
         case 'method':
             $processed = new MethodHandler($this->tag, $this->ancestry);
             break;
         case 'package':
             $processed = new PackageHandler($this->tag, $this->ancestry);
             break;
         case 'param':
             $processed = new ParamHandler($this->tag, $this->ancestry);
             break;
         case 'property':
         case 'property-read':
         case 'property-write':
             $processed = new PropertyHandler($this->tag, $this->ancestry);
             break;
         case 'return':
         case 'returns':
             $processed = new ReturnHandler($this->tag, $this->ancestry);
             break;
         case 'alias':
         case 'see':
             $processed = new SeeHandler($this->tag, $this->ancestry);
             break;
         case 'since':
         case 'available':
             $processed = new SinceHandler($this->tag, $this->ancestry);
             break;
         case 'throw':
         case 'throws':
             $processed = new ThrowHandler($this->tag, $this->ancestry);
             break;
         case 'todo':
         case 'fixme':
             $processed = new TodoHandler($this->tag, $this->ancestry);
             break;
         case 'type':
         case 'var':
             $processed = new TypeHandler($this->tag, $this->ancestry);
             break;
         case 'uses':
         case 'used-by':
             $processed = new UsesHandler($this->tag, $this->ancestry);
             break;
         case 'version':
             $processed = new VersionHandler($this->tag, $this->ancestry);
             break;
         default:
             $processed = new DefaultHandler($this->tag, $this->ancestry);
             break;
     }
     $this->triggerEvent("vanity.parse.user.tag.{$tag}.post", new EventStore(array('tag' => &$tag, 'ancestry' => $this->ancestry)));
     return $processed;
 }
Example #5
0
 public static function resolve($reflected)
 {
     $is_method = false;
     $is_property = false;
     // Are we working with a property or a method?
     if ($reflected instanceof ReflectionMethod) {
         $is_method = true;
     } elseif ($reflected instanceof ReflectionProperty) {
         $is_property = true;
     } else {
         throw new Exception('Only methods and properties can be reflected with ' . get_called_class());
     }
     // Parse the docblock
     $docblock = new DocBlock($reflected->getDocComment());
     $found_description = false;
     $return = $reflected;
     // Save these for messaging
     $__class = $reflected->getDeclaringClass()->getName();
     $__kind = $reflected->getName();
     // Can we just do a straight-up inherit?
     // @todo: Do a better job of handling {@inheritdoc} according to the spec.
     try {
         while (!$found_description && strpos($docblock->getShortDescription(), '{@inheritdoc}') !== false) {
             // Start over...
             $found_description = false;
             // Log that we're starting...
             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Starting resolution:', array(sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : '')));
             // Grab a reference to the class containing the entity with the {@inheritdoc} tag
             $klass = $reflected->getDeclaringClass();
             // Is this an Interface?
             if ($klass->isInterface()) {
                 throw new InheritdocInInterfaceException('The {@inheritdoc} tag is not resolvable from within Interfaces. Methods and properties should ' . 'be fully-documented.');
             } elseif (SystemStore::get('_.php54') && $klass->isTrait()) {
                 throw new InheritdocInTraitException('The {@inheritdoc} tag is not resolvable from within Traits. Methods and properties should ' . 'be fully-documented.');
             }
             // Are we using Interfaces?
             if (!$found_description && ($interface_count = count($klass->getInterfaces())) > 0) {
                 $count = 1;
                 foreach ($klass->getInterfaces() as $rinterface) {
                     Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking Interface {$count}/{$interface_count}:", array($rinterface->getName()));
                     try {
                         $return = $rinterface->getMethod($reflected->getName());
                         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rinterface->getName(), $reflected->getName(), 'Method'));
                         $found_description = true;
                         break 2;
                     } catch (Exception $e) {
                         try {
                             $return = $rinterface->getProperty($reflected->getName());
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rinterface->getName(), $reflected->getName(), 'Property'));
                             $found_description = true;
                             break 2;
                         } catch (Exception $e) {
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($rinterface->getName(), $reflected->getName()));
                         }
                     }
                     $count++;
                 }
             }
             // Are we using Traits?
             if (!$found_description && SystemStore::get('_.php54') && ($trait_count = count($klass->getTraits())) > 0) {
                 $count = 1;
                 foreach ($klass->getTraits() as $rtrait) {
                     Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking Trait {$count}/{$trait_count}:", array($rtrait->getName()));
                     try {
                         $return = $rtrait->getMethod($reflected->getName());
                         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rtrait->getName(), $reflected->getName(), 'Method'));
                         $found_description = true;
                         break 2;
                     } catch (Exception $e) {
                         try {
                             $return = $rtrait->getProperty($reflected->getName());
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rtrait->getName(), $reflected->getName(), 'Property'));
                             $found_description = true;
                             break 2;
                         } catch (Exception $e) {
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($rtrait->getName(), $reflected->getName()));
                         }
                     }
                     $count++;
                 }
             }
             // Are we extending a class?
             if ($klass->getParentClass()) {
                 // Continue climbing up the ancestry as necessary
                 while (!$found_description && $klass->getParentClass()) {
                     // Rewrite the reference to $klass
                     $klass = $klass->getParentClass();
                     Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking the parent class:", array($klass->getName()));
                     try {
                         $return = $klass->getMethod($reflected->getName());
                         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($klass->getName(), $reflected->getName(), 'Method'));
                         $found_description = true;
                         break 2;
                     } catch (Exception $e) {
                         try {
                             $return = $klass->getProperty($reflected->getName());
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($klass->getName(), $reflected->getName(), 'Property'));
                             $found_description = true;
                             break 2;
                         } catch (Exception $e) {
                             Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($klass->getName(), $reflected->getName()));
                         }
                     }
                 }
             }
             // We couldn't find anything
             throw new CouldNotResolveInheritdocException('Leaving as-is. The tag will be viewable in the ' . 'resulting documentation.');
         }
     } catch (InheritdocInInterfaceException $e) {
         $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : '');
         // Log that we're starting...
         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message));
         $formatter = ConsoleUtil::formatters();
         Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage()));
     } catch (InheritdocInTraitException $e) {
         $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : '');
         // Log that we're starting...
         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message));
         $formatter = ConsoleUtil::formatters();
         Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage()));
     } catch (CouldNotResolveInheritdocException $e) {
         $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : '');
         // Log that we're starting...
         Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message));
         $formatter = ConsoleUtil::formatters();
         Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage()));
     } catch (VanityException $e) {
     } catch (Exception $e) {
     }
     return $return;
 }
Example #6
0
/**
 * Copyright (c) 2009-2012 [Ryan Parman](http://ryanparman.com)
 * Copyright (c) 2011-2012 [Amazon Web Services, Inc.](http://aws.amazon.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * <http://www.opensource.org/licenses/mit-license.php>
 */
/********************************************************/
// AVAILABLE CONFIGURATION-RELATED OPTIONS
use Symfony\Component\Console\Input\InputOption;
use Vanity\System\Store as SystemStore;
return array('vanity' => array('view_config' => array(InputOption::VALUE_NONE, 'Display Vanity\'s configuration settings, and stop.', null), 'config_dir' => array(InputOption::VALUE_OPTIONAL, 'The directory which contains the project\'s Vanity configuration. Vanity will use this for resolving default paths.', SystemStore::get('_.project_config_dir')), 'bootstrap' => array(InputOption::VALUE_OPTIONAL, 'This file is loaded first. Useful for telling Vanity how to load project classes, settings constants, or other things.', '%VANITY.CONFIG_DIR%/bootstrap.php'), 'name' => array(InputOption::VALUE_OPTIONAL, 'The name of the product.', pathinfo(VANITY_PROJECT_WORKING_DIR, PATHINFO_FILENAME)), 'stage' => array(InputOption::VALUE_OPTIONAL, 'The stage that the project is currently in. Can be any ASCII value. (e.g., development, alpha, beta, rc, production).', 'development'), 'version' => array(InputOption::VALUE_OPTIONAL, 'The version number we should use.', 'latest'), 'reports' => array(InputOption::VALUE_OPTIONAL, 'The location to use for writing various reports that have been enabled.', '%VANITY.CONFIG_DIR%/reports')), 'log' => array('aliases' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Alias/Ancestry Resolution messages have?', 'debug'), 'commands' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Command begin/end messages have?', 'debug'), 'error' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Error messages have?', 'error'), 'events' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Event Trigger messages have?', 'debug'), 'info' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Notice messages have?', 'info'), 'warn' => array(InputOption::VALUE_OPTIONAL, 'Which severity should Warning messages have?', 'warn')), 'report' => array('dependencies' => array(InputOption::VALUE_OPTIONAL, 'Write a report if there are environment dependencies for the project.', false), 'inconsistencies' => array(InputOption::VALUE_OPTIONAL, 'Write a report if there are documentation inconsistencies.', false), 'todo' => array(InputOption::VALUE_OPTIONAL, 'Write a report if there are TODOs.', false), 'ungrouped' => array(InputOption::VALUE_OPTIONAL, 'Write a report if there are ungrouped methods.', false)), 'warn' => array('dependencies' => array(InputOption::VALUE_OPTIONAL, 'Warn on the console if there are environment dependencies for the project.', false), 'inconsistencies' => array(InputOption::VALUE_OPTIONAL, 'Warn on the console if there are documentation inconsistencies.', false), 'todo' => array(InputOption::VALUE_OPTIONAL, 'Warn on the console if there are TODOs.', false), 'ungrouped' => array(InputOption::VALUE_OPTIONAL, 'Warn on the console if there are ungrouped methods.', false)));
Example #7
0
 /**
  * Resolves a namespace alias into a fully-qualified namespace.
  *
  * @param  string $short A shortened namespace alias.
  * @return string        The fully-qualified namespace, if available.
  */
 public function resolveNamespace($short)
 {
     if (isset($this->aliases[$short])) {
         Logger::get()->{ConfigStore::get('log.aliases')}('Aliases: Matched in the list of known aliases.', array($short, $this->aliases[$short]));
         return $this->aliases[$short];
     } else {
         // Handle implicit aliases in the same namespace.
         try {
             $namespace = $this->class->getNamespaceName() . '\\' . $short;
             new ReflectionClass($namespace);
             Logger::get()->{ConfigStore::get('log.aliases')}('Aliases: Matched in the current namespace.', array($short, $namespace));
             // If we didn't throw an exception, we're good.
             return $namespace;
         } catch (ReflectionException $e) {
             // Handle implicit namespaces in an extended/implemented namespace.
             try {
                 foreach ($this->namespaces as $ns) {
                     try {
                         $namespace = $ns . '\\' . $short;
                         new ReflectionClass($namespace);
                         Logger::get()->{ConfigStore::get('log.aliases')}('Aliases: Matched in an extended/implemented namespace.', array($short, $namespace));
                         // If we didn't throw an exception, we're good.
                         return $namespace;
                     } catch (ReflectionException $e) {
                     }
                 }
                 throw new ReflectionException();
             } catch (ReflectionException $e) {
                 // Try removing the beginning '\' to see if we find a match.
                 try {
                     $class = preg_replace('/^\\\\/', '', $short);
                     new ReflectionClass($class);
                     Logger::get()->{ConfigStore::get('log.aliases')}('Aliases: Matched by stripping the \\ prefix.', array($short, $class));
                     // If we didn't throw an exception, we're good.
                     return $class;
                 } catch (ReflectionException $e) {
                     $formatter = ConsoleUtil::formatters();
                     Inconsistency::add($class . $formatter->gold->apply(' => No match found for ' . $short . ' (' . SystemStore::get('_.current') . ')'));
                     Logger::get()->{ConfigStore::get('log.aliases')}('Aliases: No match found.', array($short));
                     // No match. Return it as-is (without any starting backslash).
                     return $class;
                 }
             }
         }
     }
 }
Example #8
0
 /**
  * Retrieve the properties for the class.
  *
  * @return array A list of properties.
  */
 public function getProperties()
 {
     $rproperties = $this->class->getProperties();
     foreach ($rproperties as $rproperty) {
         if (!isset($this->properties['count'])) {
             $this->properties['count'] = count($rproperties);
         }
         if (!isset($this->properties['property'])) {
             $this->properties['property'] = array();
         }
         $rproperty = InheritdocHandler::resolve($rproperty);
         $_tags = new TagHandler($rproperty->getDocComment(), $this->ancestry);
         $property_docblock = new DocBlock($rproperty->getDocComment());
         // Property-specific data
         $entry = array();
         $entry['name'] = $rproperty->getName();
         $entry['visibility'] = $this->access($rproperty);
         // Where are we?
         SystemStore::add('_.current', $this->class->getName() . '::$' . $rproperty->getName());
         if ($description = $_tags->getDescription()) {
             $entry['description'] = $description;
         }
         // Property inheritance
         if (($declaring_class = $rproperty->getDeclaringClass()->getName()) !== $this->class->getName()) {
             if (!isset($entry['inheritance'])) {
                 $entry['inheritance'] = array();
             }
             if (!isset($entry['inheritance']['class'])) {
                 $entry['inheritance']['class'] = array();
             }
             $declaring_class = $rproperty->getDeclaringClass();
             $subentry = array();
             $subentry['name'] = $declaring_class->getName();
             if ($declaring_class->getFileName()) {
                 $subentry['path'] = str_replace(VANITY_PROJECT_WORKING_DIR . '/', '', $declaring_class->getFileName());
             }
             $entry['inheritance']['class'][] = $subentry;
         }
         // Default value, if accessible
         if ($rproperty->isPublic()) {
             $rvalue = $rproperty->getValue($this->class);
             $adjusted_rvalue = null;
             switch (strtolower(gettype($rvalue))) {
                 case 'boolean':
                     $adjusted_rvalue = $rvalue == 1 ? 'true' : 'false';
                     break;
                 case 'null':
                     $adjusted_rvalue = 'null';
                     break;
                 case 'string':
                     $adjusted_rvalue = $rvalue;
                     break;
                 case 'integer':
                     $adjusted_rvalue = (int) $rvalue;
                     break;
                 case 'array':
                     $adjusted_rvalue = ParseUtil::unwrapArray($rvalue);
                     break;
             }
             $entry['initializer'] = array();
             $entry['initializer']['type'] = gettype($rvalue);
             $entry['initializer']['value'] = $adjusted_rvalue;
         }
         // Property tags
         if ($t = $_tags->getTags()) {
             $entry['metadata'] = $t;
         }
         $this->properties['property'][] = $entry;
     }
     return $this->properties;
 }
Example #9
0
 /**
  * Retrieve the properties for the class.
  *
  * @return array A list of properties.
  */
 public function getMethods()
 {
     $rclass_methods = $this->class->getMethods();
     // Add methods and parameters
     $rclass_methods = array_values(array_filter($rclass_methods, function ($rmethod) {
         if ($exclusions = ConfigStore::get('source.exclude.methods')) {
             return !preg_match($exclusions, $rmethod->getName());
         }
         return true;
     }));
     foreach ($rclass_methods as $rmethod) {
         $documentThis = true;
         if (!isset($this->methods['count'])) {
             $this->methods['count'] = count($rclass_methods);
         }
         if (!isset($this->methods['method'])) {
             $this->methods['method'] = array();
         }
         $rmethod = InheritdocHandler::resolve($rmethod);
         $_tags = new TagHandler($rmethod->getDocComment(), $this->ancestry);
         $method_docblock = new DocBlock($rmethod->getDocComment());
         $entry = array();
         $entry['name'] = $rmethod->getName();
         $entry['visibility'] = $this->methodAccess($rmethod);
         if ($extension = $rmethod->getExtensionName()) {
             $entry['extension'] = $extension;
             DependencyCollector::add($extension);
         }
         if ($rmethod->getFileName()) {
             $entry['path'] = str_replace(array(VANITY_SYSTEM . '/', VANITY_PROJECT_WORKING_DIR . '/'), '', $rmethod->getFileName());
             $entry['lines'] = array('start' => $rmethod->getStartLine(), 'end' => $rmethod->getEndLine());
             if ($viewsource = ConfigStore::get('source.viewsource')) {
                 $entry['viewsource'] = str_replace(array('%PATH%', '%LINE%'), array($entry['path'], $entry['lines']['start']), $viewsource);
             }
         }
         if ($description = $_tags->getDescription()) {
             $entry['description'] = $description;
         }
         // Method inheritance
         if (($declaring_class = $rmethod->getDeclaringClass()->getName()) !== $this->class->getName()) {
             if (!isset($entry['inheritance'])) {
                 $entry['inheritance'] = array();
             }
             if (!isset($entry['inheritance']['class'])) {
                 $entry['inheritance']['class'] = array();
             }
             $declaring_class = new ReflectionClass($declaring_class);
             $subentry = array();
             $subentry['name'] = $declaring_class->getName();
             if ($declaring_class->getFileName()) {
                 $subentry['path'] = str_replace(VANITY_PROJECT_WORKING_DIR . '/', '', $declaring_class->getFileName());
             }
             $entry['inheritance']['class'][] = $subentry;
         }
         // Method tags
         if (count($method_docblock->getTags())) {
             if (!isset($entry['metadata'])) {
                 $entry['metadata'] = array();
             }
             if (!isset($entry['metadata']['tag'])) {
                 $entry['metadata']['tag'] = array();
             }
             foreach ($method_docblock->getTags() as $rtag) {
                 $dtag = new Tag($rtag, $this->ancestry);
                 $tagData = $dtag->determine()->process(ConfigStore::get('source.resolve_aliases'));
                 if ($tagData['name'] === 'alias') {
                     SystemStore::add('alias.' . $tagData['entity'], $this->class->getName() . '::' . $rmethod->getName());
                     $documentThis = false;
                 }
                 $entry['metadata']['tag'][] = $tagData;
             }
         }
         // Method parameters
         if ($count = count($rmethod->getParameters())) {
             if (!isset($entry['parameters'])) {
                 $entry['parameters'] = array();
             }
             if (!isset($entry['parameters']['count'])) {
                 $entry['parameters']['count'] = $count;
             }
             if (!isset($entry['parameters']['parameter'])) {
                 $entry['parameters']['parameter'] = array();
             }
             foreach ($rmethod->getParameters() as $rparameter) {
                 $tag_finder = new TagFinder($entry);
                 $param = array();
                 $param['name'] = $rparameter->getName();
                 $param['required'] = !$rparameter->isOptional();
                 $param['passed_by_reference'] = $rparameter->isPassedByReference();
                 if ($rparameter->isDefaultValueAvailable()) {
                     $param['default'] = $rparameter->getDefaultValue();
                 }
                 // Pull-in from @tags
                 if ($_description = $tag_finder->find('description', $param['name'])) {
                     $param['description'] = $_description;
                 }
                 if ($_type = $tag_finder->find('type', $param['name'])) {
                     $param['type'] = $this->ancestry->resolveNamespace($_type);
                 }
                 if ($_types = $tag_finder->find('types', $param['name'])) {
                     $param['types'] = $_types;
                 }
                 // Clean-up parameter metadata tags
                 if (isset($entry['metadata']) && isset($entry['metadata']['tag'])) {
                     foreach ($entry['metadata']['tag'] as $index => $tag) {
                         if ($tag['name'] === 'param' && $tag['variable'] === $param['name']) {
                             unset($entry['metadata']['tag'][$index]);
                         }
                     }
                 }
                 // Type hinting trumps docblock
                 if ($rparameter->getClass()) {
                     if (isset($param['type']) && $param['type'] !== $rparameter->getClass()->getName()) {
                         // @todo: Resolve namespace of declaring class.
                         Inconsistency::add($this->class->getName() . '::' . $rmethod->getName() . '($' . $rparameter->getName() . ') [' . $param['type'] . ' => ' . $rparameter->getClass()->getName() . ']');
                     }
                     $param['type'] = $rparameter->getClass()->getName();
                     if (isset($param['types'])) {
                         unset($param['types']);
                     }
                 }
                 $entry['parameters']['parameter'][] = $param;
             }
         }
         // Return value
         $entry['return'] = array('type' => 'void');
         if (isset($entry['metadata']) && isset($entry['metadata']['tag'])) {
             foreach ($entry['metadata']['tag'] as $index => $tag) {
                 if ($tag['name'] === 'return') {
                     $entry['return'] = $tag;
                     unset($entry['return']['name']);
                     // Clean-up return metadata tags
                     unset($entry['metadata']['tag'][$index]);
                 }
             }
         }
         if ($documentThis) {
             $this->methods['method'][] = $entry;
         }
     }
     return $this->methods;
 }
Example #10
0
 /**
  * An array of file paths retrieved from {@see files()}.
  *
  * @param  array  $files A list of file paths.
  * @return array         A list of classes.
  */
 public static function classes(array $files)
 {
     $loader = new UniversalClassLoader();
     // Support PSR-0 autoloading with a composer.json file
     // @todo: Add support for Composer's classmap autoloading.
     if (file_exists(VANITY_PROJECT_WORKING_DIR . '/vendor/composer/autoload_namespaces.php')) {
         // Register namespaces with the class loader
         $loader->registerNamespaces(include VANITY_PROJECT_WORKING_DIR . '/vendor/composer/autoload_namespaces.php');
     } elseif (file_exists(VANITY_PROJECT_WORKING_DIR . '/composer.json')) {
         // Register namespaces with the class loader
         $composer = json_decode(file_get_contents(VANITY_PROJECT_WORKING_DIR . '/composer.json'), true);
         if (isset($composer['autoload']) && isset($composer['autoload']['psr-0'])) {
             $loader->registerNamespaces($composer['autoload']['psr-0']);
         }
     }
     $loader->register();
     $class_list = array();
     // Collect all current classes, interfaces and traits
     if (SystemStore::get('_.php54')) {
         $before = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits());
     } else {
         $before = array_merge(get_declared_classes(), get_declared_interfaces());
     }
     foreach ($files as $file) {
         include_once $file;
     }
     // Handle traits if this version of PHP supports them.
     if (SystemStore::get('_.php54')) {
         $after = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits());
     } else {
         $after = array_merge(get_declared_classes(), get_declared_interfaces());
     }
     // We should be able to document ourselves
     if (defined('VANITY_AM_I')) {
         $after = array_filter($after, function ($class) {
             return substr($class, 0, 7) !== 'Vanity\\';
         });
     }
     $class_list = array_values(array_unique(array_diff($after, $before)));
     sort($class_list);
     return $class_list;
 }
Example #11
0
 /**
  * Retrieve the constants for the class.
  *
  * @return array A list of constants.
  */
 public function getConstants()
 {
     $rclass_constants = $this->class->getConstants();
     ksort($rclass_constants);
     // Add constants
     foreach ($rclass_constants as $rconstant_name => $rconstant_value) {
         if (!isset($this->constants['count'])) {
             $this->constants['count'] = count($rclass_constants);
         }
         if (!isset($this->constants['constant'])) {
             $this->constants['constant'] = array();
         }
         $entry = array();
         $entry['name'] = $rconstant_name;
         $entry['value'] = $rconstant_value;
         $entry['type'] = gettype($rconstant_value);
         // Where are we?
         SystemStore::add('_.current', $this->class->getName() . '::' . $rconstant_name);
         $this->constants['constant'][] = $entry;
     }
     return $this->constants;
 }
Example #12
0
 /**
  * Trigger an event containing the log path.
  *
  * @return void
  */
 public function triggerLogMessageEvent()
 {
     $this->triggerEvent('vanity.command.log_path', new EventStore(array('log_path' => SystemStore::get('_.log_dir'), 'time' => SystemStore::get('_.run_time'))));
 }
Example #13
0
 /**
  * Reflects over the given class and produces an associative array
  * containing all relevant class data.
  *
  * @event  EventStore vanity.parse.user.reflect.pre
  * @event  EventStore vanity.parse.user.reflect.post
  * @return array      An associative array containing all relevant class data.
  */
 public function process()
 {
     // REFLECT ALL THE THINGS!
     $rclass_methods = $this->rclass->getMethods();
     $long_filename = $this->rclass->getFileName();
     $short_filename = str_replace(array(VANITY_SYSTEM . '/', VANITY_PROJECT_WORKING_DIR . '/'), '', $long_filename);
     $this->triggerEvent("vanity.parse.user.reflect.pre", new EventStore(array('data' => &$this->data)));
     $this->data['name'] = $this->rclass->getShortName();
     $this->data['namespace'] = $this->rclass->getNamespaceName();
     $this->data['full_name'] = $this->class_name;
     $this->data['namespace_as_path'] = str_replace('\\', '/', $this->class_name);
     $this->data['path'] = $short_filename;
     if (SystemStore::get('_.php54') && $this->rclass->isTrait()) {
         $this->data['kind'] = 'Trait';
     } elseif ($this->rclass->isInterface()) {
         $this->data['kind'] = 'Interface';
     } elseif ($this->rclass->isSubClassOf('Exception')) {
         $this->data['kind'] = 'Exception';
     } else {
         $this->data['kind'] = 'Class';
     }
     SystemStore::add('_.current', $this->class_name);
     #--------------------------------------------------------------------------#
     // Enable GitHub lookups for author data
     if (ConfigStore::get('source.github.user') && ConfigStore::get('source.github.pass')) {
         $github = new GitHub(ConfigStore::get('source.github.user'), ConfigStore::get('source.github.pass'));
         $github->setRepository(ConfigStore::get('source.github.repo_owner'), ConfigStore::get('source.github.repo_name'));
         $this->data['github'] = $github->getAuthorsForFile($this->data['path']);
     }
     #--------------------------------------------------------------------------#
     // Add description
     if ($description = $this->class_tags->getDescription()) {
         $this->data['description'] = $description;
     }
     // Add inheritance chain
     if ($this->inheritance) {
         $this->data['inheritance'] = $this->inheritance;
     }
     // Add implemented interfaces
     if ($this->implements) {
         $this->data['implements'] = $this->implements;
     }
     // Add used traits
     if ($this->traits) {
         $this->data['traits'] = $this->traits;
     }
     // Add class tags
     if ($tags = $this->class_tags->getTags()) {
         $this->data['metadata'] = $tags;
     }
     // Add constants
     if ($constants = $this->constants->getConstants()) {
         $this->data['constants'] = $constants;
     }
     // Add properties
     if ($properties = $this->properties->getProperties()) {
         $this->data['properties'] = $properties;
     }
     // Add meta-properties
     if (isset($this->data['metadata']) && isset($this->data['properties'])) {
         $new = $this->formatMetaProperties($this->data['metadata']);
         $this->data['properties']['property'] = array_merge($this->data['properties']['property'], $new);
         $this->data['properties']['count'] += count($new);
     } elseif (isset($this->data['metadata'])) {
         $new = $this->formatMetaProperties($this->data['metadata']);
         $this->data['properties']['property'] = $new;
         $this->data['properties']['count'] = count($new);
     }
     // Sort the properties alphabetically
     if (isset($this->data['properties']) && isset($this->data['properties']['property']) && is_array($this->data['properties']['property'])) {
         usort($this->data['properties']['property'], function ($a, $b) {
             $a = $a['name'];
             $b = $b['name'];
             if ($a === $b) {
                 return 0;
             }
             return $a < $b ? -1 : 1;
         });
     }
     // Add methods
     if ($methods = $this->methods->getMethods()) {
         $this->data['methods'] = $methods;
     }
     // Add meta-methods
     if (isset($this->data['metadata']) && isset($this->data['methods'])) {
         $new = $this->formatMetaMethods($this->data['metadata']);
         $this->data['methods']['method'] = array_merge($this->data['methods']['method'], $new);
         $this->data['methods']['count'] += count($new);
     } elseif (isset($this->data['metadata'])) {
         $new = $this->formatMetaMethods($this->data['metadata']);
         $this->data['methods']['method'] = $new;
         $this->data['methods']['count'] = count($new);
     }
     // Sort the methods alphabetically
     if (isset($this->data['methods']) && isset($this->data['methods']['method']) && is_array($this->data['methods']['method'])) {
         usort($this->data['methods']['method'], function ($a, $b) {
             $a = $a['name'];
             $b = $b['name'];
             if ($a === $b) {
                 return 0;
             }
             return $a < $b ? -1 : 1;
         });
     }
     // Sort the metadata tags, post-edit from @method, @property and @return
     if (isset($this->data['metadata'])) {
         $this->data['metadata']['tag'] = array_values($this->data['metadata']['tag']);
         // Sort the tags alphabetically
         usort($this->data['metadata']['tag'], function ($a, $b) {
             $a = $a['name'];
             $b = $b['name'];
             if ($a === $b) {
                 return 0;
             }
             return $a < $b ? -1 : 1;
         });
     }
     // Handle alias tags
     $this->triggerEvent("vanity.parse.user.reflect.post", new EventStore(array('data' => &$this->data)));
 }
Example #14
0
 /**
  * Return the config values passed in the config.yml file.
  *
  * @return array The config values passed in the config.yml file.
  */
 private function fileValues()
 {
     // Use the config directory passed to the CLI
     $config_dir = $this->cliValues(true) ?: SystemStore::get('_.project_config_dir');
     if (file_exists($config_dir . '/config.yml')) {
         ConfigStore::$messages[] = 'Merged configuration options from ' . $this->formatter->info->apply(' ' . $config_dir . '/config.yml ');
         $options = YAML::parse($config_dir . '/config.yml');
         $config = ConfigStore::convert($options);
         $config = array_filter($config);
         return $config;
     }
     return array();
 }