methods() public static method

Returns various information on the methods of an object, in different formats.
public static methods ( mixed $class, string $format = null, array $options = [] ) : mixed
$class mixed A string class name or an object instance, from which to get methods.
$format string The type and format of data to return. Available options are: - `null`: Returns a `Collection` object containing a `ReflectionMethod` instance for each method. - `'extents'`: Returns a two-dimensional array with method names as keys, and an array with starting and ending line numbers as values. - `'ranges'`: Returns a two-dimensional array where each key is a method name, and each value is an array of line numbers which are contained in the method.
$options array Set of options applied directly (check `_items()` for more options): - `'methods'` _array_: An arbitrary list of methods to search, as a string (single method name) or array of method names. - `'group'`: If true (default) the array is grouped by context (ex.: method name), if false the results are sequentially appended to an array. -'self': If true (default), only returns properties defined in `$class`, excluding properties from inherited classes.
return mixed Return value depends on the $format given: - `null` on failure. - `lithium\util\Collection` if $format is `null` - `array` if $format is either `'extends'` or `'ranges'`.
Example #1
0
 /**
  * "Explain" methods step.
  *
  * @return void
  */
 public function explainExplainMethods()
 {
     $this->header("The Explain Methods");
     $this->out("The next step is to create your first `explain` method. When an exercise is run, each user-defined method that begins with 'explain' is run in the order it was defined.\n");
     $this->out("Let's start by defining a new method called `explainIntro`.");
     $this->halt();
     $methods = \lithium\analysis\Inspector::methods('\\li3_exercises\\extensions\\exercises\\Blog', 'extents');
     $this->assertTrue(isset($methods['explainIntro']), "Hmmm. I can't seem to find a method defined on your new Blog class named '{:purple}explainIntro{:end}'. {:error}Make sure it has public visibility!{:end}");
 }
Example #2
0
 /**
  * Creates step list for this exercise.
  * 
  * @return void
  */
 protected function _initSteps()
 {
     $methods = Inspector::methods($this)->to('array');
     foreach ($methods as $method) {
         if (substr($method['name'], 0, strlen($this->_methodPrefix)) === $this->_methodPrefix) {
             $this->_steps[] = $method['name'];
         }
     }
 }
Example #3
0
 protected static function _extractClassCode($ref)
 {
     $method = $ref['method'];
     $class = $ref['class'];
     $markers = Inspector::methods($class, 'extents', array('methods' => array($ref['method'])));
     $methodStart = $markers[$method][0];
     list($start, $end) = array_map('intval', explode('-', $ref['lines']));
     $code = Inspector::lines($class, range($start + $methodStart, $end + $methodStart));
     $pad = substr_count(current($code), "\t", 0);
     $lines = array_map('substr', $code, array_fill(0, count($code), $pad));
     return array("{$class}::{$method}({$start}-{$end})", join("\n", $lines));
 }
Example #4
0
 /**
  * Get the methods to test.
  *
  * @param string $request
  * @return string
  */
 protected function _methods($request)
 {
     $use = $this->_use($request);
     $path = Libraries::path($use);
     if (!file_exists($path)) {
         return "";
     }
     $methods = (array) Inspector::methods($use, 'extents');
     $testMethods = array();
     foreach (array_keys($methods) as $method) {
         $testMethods[] = "\tpublic function test" . ucwords($method) . "() {}";
     }
     return join("\n", $testMethods);
 }
Example #5
0
 /**
  * Takes an instance of an object (usually a Collection object) containing test
  * instances. Introspects the test subject classes to extract cyclomatic complexity data.
  *
  * @param object $report Instance of Report which is calling apply.
  * @param array $tests The test to apply this filter on
  * @param array $options Not used.
  * @return object|void Returns the instance of `$tests`.
  */
 public static function apply($report, $tests, array $options = array())
 {
     $results = array();
     foreach ($tests->invoke('subject') as $class) {
         $results[$class] = array();
         if (!($methods = Inspector::methods($class, 'ranges', array('public' => false)))) {
             continue;
         }
         foreach ($methods as $method => $lines) {
             $lines = Inspector::lines($class, $lines);
             $branches = Parser::tokenize(join("\n", (array) $lines), array('include' => static::$_include));
             $results[$class][$method] = count($branches) + 1;
             $report->collect(__CLASS__, $results);
         }
     }
     return $tests;
 }
Example #6
0
 /**
  * Generate test cases in the given namespace.
  * `li3 create test model Post`
  * `li3 create test --library=li3_plugin model Post`
  *
  * @param string $type namespace of the class (e.g. model, controller, some.name.space).
  * @param string $name Name of class to test.
  * @return void
  */
 public function run($type = null, $name = null)
 {
     $library = Libraries::get($this->library);
     if (empty($library['prefix'])) {
         return false;
     }
     $namespace = $this->_namespace($type);
     $use = "\\{$library['prefix']}{$namespace}\\{$name}";
     $methods = array();
     if (class_exists($use)) {
         $methods = array();
         foreach (array_keys(Inspector::methods($use, 'extents')) as $method) {
             $methods[] = "\tpublic function test" . ucwords($method) . "() {}";
         }
     }
     $params = array('namespace' => "{$library['prefix']}tests\\cases\\{$namespace}", 'use' => $use, 'class' => "{$name}Test", 'methods' => join("\n", $methods));
     if ($this->_save($this->template, $params)) {
         $this->out("{$params['class']} created for {$name} in {$params['namespace']}.");
         return true;
     }
     return false;
 }
Example #7
0
 /**
  * Helper method for caching closure function references to help the process of building the
  * stack trace.
  *
  * @param  array $frame Backtrace information.
  * @param  callable|string $function The method related to $frame information.
  * @return string Returns either the cached or the fetched closure function reference while
  *                writing its reference to the cache array `$_closureCache`.
  */
 protected static function _closureDef($frame, $function)
 {
     $reference = '::';
     $frame += array('file' => '??', 'line' => '??');
     $cacheKey = "{$frame['file']}@{$frame['line']}";
     if (isset(static::$_closureCache[$cacheKey])) {
         return static::$_closureCache[$cacheKey];
     }
     if ($class = Inspector::classes(array('file' => $frame['file']))) {
         foreach (Inspector::methods(key($class), 'extents') as $method => $extents) {
             $line = $frame['line'];
             if (!($extents[0] <= $line && $line <= $extents[1])) {
                 continue;
             }
             $class = key($class);
             $reference = "{$class}::{$method}";
             $function = "{$reference}()::{closure}";
             break;
         }
     } else {
         $reference = $frame['file'];
         $function = "{$reference}::{closure}";
     }
     $line = static::_definition($reference, $frame['line']) ?: '?';
     $function .= " @ {$line}";
     return static::$_closureCache[$cacheKey] = $function;
 }
Example #8
0
 protected static function _class(array $object, array $data, array $options = array())
 {
     $identifier = $object['identifier'];
     $proto = array('parent' => get_parent_class($identifier), 'methods' => Inspector::methods($identifier, null, array('public' => false)), 'properties' => Inspector::properties($identifier, array('public' => false)));
     $classes = Libraries::find($object['library'], array('recursive' => true));
     $proto['subClasses'] = array_filter($classes, function ($class) use($identifier) {
         if (preg_match('/\\\\(libraries)\\\\|\\\\(mocks)\\\\|\\\\(tests)\\\\/', $class)) {
             return false;
         }
         try {
             return get_parent_class($class) == $identifier;
         } catch (Exception $e) {
             return false;
         }
     });
     sort($proto['subClasses']);
     return $proto + $object + array('tags' => isset($data['tags']) ? $data['tags'] : array());
 }
Example #9
0
 /**
  * Get the methods for the class
  *
  * @param string $class
  * @param array $options
  * @return array
  */
 protected function _methods($class, $options = array())
 {
     $defaults = array('name' => null);
     $options += $defaults;
     $methods = Inspector::methods($class)->map(function ($item) {
         if ($item->name[0] === '_') {
             return;
         }
         $modifiers = array_values(Inspector::invokeMethod('_modifiers', array($item)));
         $setAccess = array_intersect($modifiers, array('private', 'protected')) != array();
         if ($setAccess) {
             $item->setAccessible(true);
         }
         $result = compact('modifiers') + array('docComment' => $item->getDocComment(), 'name' => $item->getName());
         if ($setAccess) {
             $item->setAccessible(false);
         }
         return $result;
     }, array('collect' => false));
     $results = array();
     foreach ($methods as $method) {
         $comment = Docblock::comment($method['docComment']);
         $name = $method['name'];
         $description = $comment['description'];
         $args = !isset($comment['tags']['params']) ? null : $comment['tags']['params'];
         $return = !isset($comment['tags']['return']) ? null : trim(strtok($comment['tags']['return'], ' '));
         $command = $name === 'run' ? null : $name;
         $command = !$command && !empty($args) ? '[ARGS]' : $command;
         $usage = "{$command} ";
         $usage .= empty($args) ? null : join(' ', array_map(function ($a) {
             return '[' . str_replace('$', '', trim($a)) . ']';
         }, array_keys($args)));
         $results[$name] = compact('name', 'description', 'return', 'args', 'usage');
         if ($name && $name == $options['name']) {
             return array($name => $results[$name]);
         }
     }
     return $results;
 }
Example #10
0
 /**
  * Tests that the range of executable lines of this test method is properly calculated.
  * Recursively meta.
  */
 public function testMethodRange()
 {
     $result = Inspector::methods(__CLASS__, 'ranges', array('methods' => __FUNCTION__));
     $expected = array(__FUNCTION__ => array(__LINE__ - 1, __LINE__, __LINE__ + 1));
     $this->assertEqual($expected, $result);
 }
Example #11
0
 /**
  * Get the methods for the class.
  *
  * @param string $class
  * @param array $options
  * @return array
  */
 protected function _methods($class, $options = array())
 {
     $defaults = array('name' => null);
     $options += $defaults;
     $map = function ($item) {
         if ($item->name[0] === '_') {
             return;
         }
         $modifiers = array_values(Inspector::invokeMethod('_modifiers', array($item)));
         $setAccess = array_intersect($modifiers, array('private', 'protected')) != array();
         if ($setAccess) {
             $item->setAccessible(true);
         }
         $args = array();
         foreach ($item->getParameters() as $arg) {
             $args[] = array('name' => $arg->getName(), 'optional' => $arg->isOptional(), 'description' => null);
         }
         $result = compact('modifiers', 'args') + array('docComment' => $item->getDocComment(), 'name' => $item->getName());
         if ($setAccess) {
             $item->setAccessible(false);
         }
         return $result;
     };
     $methods = Inspector::methods($class)->map($map, array('collect' => false));
     $results = array();
     foreach (array_filter($methods) as $method) {
         $comment = Docblock::comment($method['docComment']);
         $name = $method['name'];
         $description = trim($comment['description'] . PHP_EOL . $comment['text']);
         $args = $method['args'];
         $return = null;
         foreach ($args as &$arg) {
             if (isset($comment['tags']['params']['$' . $arg['name']])) {
                 $arg['description'] = $comment['tags']['params']['$' . $arg['name']]['text'];
             }
             $arg['usage'] = $arg['optional'] ? "[<{$arg['name']}>]" : "<{$arg['name']}>";
         }
         if (isset($comment['tags']['return'])) {
             $return = trim(strtok($comment['tags']['return'], ' '));
         }
         $results[$name] = compact('name', 'description', 'return', 'args');
         if ($name && $name == $options['name']) {
             return array($name => $results[$name]);
         }
     }
     return $results;
 }