Get the corresponding physical file path for a class or namespace name.
public static path ( string $class, array $options = [] ) : string | ||
$class | string | The class name to locate the physical file for. If `$options['dirs']` is set to `true`, `$class` may also be a namespace name, in which case the corresponding directory will be located. |
$options | array | Options for converting `$class` to a physical path: - `'dirs'`: Defaults to `false`. If `true`, will attempt to case-sensitively look up directories in addition to files (in which case `$class` is assumed to actually be a namespace). |
return | string | Returns the absolute path to the file containing `$class`, or `null` if the file cannot be found. |
public static function get($library, $identifier, array $options = array()) { static::_ensureIndexedLibrary($library); $defaults = array('namespaceDoc' => array(), 'language' => 'en'); $options += $defaults; $options['namespaceDoc'] = (array) $options['namespaceDoc']; $config = Libraries::get('li3_docs'); if (isset($config['namespaceDoc'])) { $options['namespaceDoc'] = array_merge($options['namespaceDoc'], (array) $config['namespaceDoc']); } $path = Libraries::path($identifier); static::_ensurePathInBase($path); if (file_exists($path) && !static::_isClassFile($path)) { return static::_file(compact('library', 'path', 'identifier'), $options); } $data = Inspector::info($identifier); $proto = compact('identifier', 'library') + array('name' => null, 'type' => Inspector::type($identifier), 'info' => array(), 'classes' => null, 'methods' => null, 'properties' => null, 'parent' => null, 'children' => null, 'source' => null, 'subClasses' => array(), 'description' => isset($data['description']) ? $data['description'] : null, 'text' => isset($data['text']) ? $data['text'] : null); $format = "_{$proto['type']}"; $data = static::$format($proto, (array) $data, $options); if (!$data) { return false; } foreach (array('text', 'description') as $key) { $data[$key] = Code::embed($data[$key], compact('library')); } return $data; }
public function run($library = 'lithium') { $libs = Libraries::find($library, array('recursive' => true)); $files = array(); foreach ((array) $libs as $lib) { $file = Libraries::path($lib); $this->_display($file); } }
public function skip() { $this->skipIf(!is_object($this->_location), 'Adapter not initialized'); $this->skipIf($this->_location->_config['adapter'] !== 'FileSystem', 'Adapter should be `FileSystem`.'); $this->skipIf($this->_location->_config['location'] !== $this->_tmp_dir, "Location should be `li3_filemanage/resources/tmp/{$this->_timestamp}_test`."); $this->skipIf(!is_writable(Libraries::path('li3_filemanager\\', array('dirs' => true)) . '/resources'), 'Test location not writable!<br />' . 'Check does `li3_filemanager/resources/tmp` directorty exists if not create it.<br />' . 'On *nix OS-es you should <code>$ chmod -R 0777 libraries/li3_filemanager/resources</code>'); $this->skipIf(!mkdir($this->_tmp_dir), 'Couldn\'t create directory for further testing!'); $this->skipIf(!file_put_contents("{$this->_tmp_dir}/test.txt", "This is test data\n"), 'Couldn\'t write test file!'); }
/** * Skip the test if no allowed database connection available. */ public function skip() { parent::connect($this->_connection); if (!class_exists('li3_fixtures\\test\\Fixtures')) { $this->skipIf(true, "These tests need `'li3_fixtures'` to be runned."); } $this->skipIf(!$this->with(array('MySql', 'PostgreSql', 'Sqlite3'))); $this->_export = Libraries::path('lithium\\tests\\fixture\\model\\gallery\\export', array('dirs' => true)); }
public function run() { $classes = Libraries::find(true, array('exclude' => "/webroot|index\$|^app\\\\config|^app\\\\views/", 'recursive' => true)); foreach ($classes as $class) { $path = Libraries::path($class); $contents = explode("\n", file_get_contents($path)); $contents = $this->_header($contents); if (file_put_contents($path, implode("\n", $contents))) { $this->out($path . ' written'); } } }
/** * 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); }
public static function apply($report, $tests, array $options = array()) { $rules = new Rules(); $file = Libraries::get('li3_quality', 'path') . '/config/syntax.json'; $config = json_decode(file_get_contents($file), true) + array('name' => null, 'rules' => array(), 'options' => array()); foreach ($config['rules'] as $ruleName) { $class = Libraries::locate('rules.syntax', $ruleName); $rules->add(new $class()); } if ($config['options']) { $rules->options($config['options']); } foreach ($tests->invoke('subject') as $class) { $report->collect(__CLASS__, array($class => $rules->apply(new Testable(array('path' => Libraries::path($class)))))); } return $tests; }
public function testFindingTokenPatterns() { $code = file_get_contents(Libraries::path('lithium\\analysis\\Parser')); $expected = array('tokenize', 'matchToken', '_prepareMatchParams', 'token'); $results = array_values(array_unique(array_map(function ($i) { return $i[0]; }, Parser::find($code, 'static::_(*)', array('capture' => array('T_STRING'), 'return' => 'content'))))); $this->assertEqual($expected, $results); $expected = array('lithium\\util\\Set', 'lithium\\util\\Collection'); $results = array_map(function ($i) { return join('', $i); }, $results = Parser::find($code, 'use *;', array('return' => 'content', 'lineBreaks' => true, 'startOfLine' => true, 'capture' => array('T_STRING', 'T_NS_SEPARATOR')))); $this->assertEqual($expected, $results); $code = 'function test($options) { return function($foo) use ($options) {'; $code .= ' ClassName::method($options); ' . "\n" . ' $foo->method($options); }; }'; list($results) = Parser::find($code, '_::_(', array('capture' => array('T_STRING'), 'return' => 'content')); $expected = array('ClassName', 'method'); $this->assertEqual($expected, $results); }
/** * Add a tests to the group. * * @param string $test The test to be added. * @param array $options Method options. Currently not used in this method. * @return array Updated list of tests contained within this collection. */ public function add($test = null, array $options = array()) { $resolve = function ($self, $test) { switch (true) { case !$test: return array(); case is_object($test) && $test instanceof Unit: return array(get_class($test)); case is_string($test) && !file_exists(Libraries::path($test)): return $self->invokeMethod('_resolve', array($test)); default: return (array) $test; } }; if (is_array($test)) { foreach ($test as $t) { $this->_data = array_filter(array_merge($this->_data, $resolve($this, $t))); } return $this->_data; } return $this->_data = array_merge($this->_data, $resolve($this, $test)); }
/** * Gets the static and dynamic dependencies for a class or group of classes. * * @param mixed $classes Either a string specifying a class, or a numerically indexed array * of classes * @param array $options * @return array An array of the static and dynamic class dependencies * @todo Document valid options */ public static function dependencies($classes, array $options = array()) { $defaults = array('type' => null); $options += $defaults; $static = $dynamic = array(); $trim = function ($c) { return trim(trim($c, '\\')); }; $join = function ($i) { return join('', $i); }; foreach ((array) $classes as $class) { $data = explode("\n", file_get_contents(Libraries::path($class))); $data = "<?php \n" . join("\n", preg_grep('/^\\s*use /', $data)) . "\n ?>"; $classes = array_map($join, Parser::find($data, 'use *;', array('return' => 'content', 'lineBreaks' => true, 'startOfLine' => true, 'capture' => array('T_STRING', 'T_NS_SEPARATOR')))); if ($classes) { $static = array_unique(array_merge($static, array_map($trim, $classes))); } $classes = static::info($class . '::$_classes', array('value')); if (isset($classes['value'])) { $dynamic = array_merge($dynamic, array_map($trim, array_values($classes['value']))); } } if (empty($options['type'])) { return array_unique(array_merge($static, $dynamic)); } $type = $options['type']; return isset(${$type}) ? ${$type} : null; }
/** * Performs service location lookups by library, based on the library's `'defer'` flag. * Libraries with `'defer'` set to `true` will be searched last when looking up services. * * @see lithium\core\Libraries::$_paths * @see lithium\core\Libraries::locate() * @param boolean $defer A boolean flag indicating which libraries to search, either the ones * with the `'defer'` flag set, or the ones without. * @param array $paths List of paths to be searched for the given service (class). These are * defined in `lithium\core\Libraries::$_paths`, and are organized by class type. * @param array $params The list of insert parameters to be injected into each path format * string when searching for classes. * @param array $options * @return string Returns a class path as a string if a given class is found, or null if no * class in any path matching any of the parameters is located. */ protected static function _locateDeferred($defer, $paths, $params, array $options = array()) { $libraries = static::$_configurations; if (isset($options['library'])) { $libraries = static::get((array) $options['library']); } foreach ($libraries as $library => $config) { if ($config['defer'] !== $defer && $defer !== null) { continue; } foreach (static::_searchPaths($paths, $library, $params) as $tpl) { $params['library'] = $library; $class = str_replace('\\*', '', String::insert($tpl, $params)); if (file_exists($file = Libraries::path($class, $options))) { return $options['type'] === 'file' ? $file : $class; } } } }
/** * Gets a unit test class (or classes) from a class or namespace path string. * * @param string $test The path string in which to find the test case(s). This may be a * namespace, a Lithium package name, or a fully-namespaced class reference. * @return array Returns an array containing one or more fully-namespaced class references to * unit tests. */ protected function _unitClass($test) { if ($test[0] != '\\' && strpos($test, 'lithium\\') === false) { if (file_exists(Libraries::path($test = "lithium\\tests\\cases\\{$test}"))) { return array($test); } } if (preg_match("/Test/", $test)) { return array($test); } if (!($test = trim($test, '\\'))) { return array(); } list($library, $path) = explode('\\', $test, 2) + array($test, null); return (array) Libraries::find($library, array('recursive' => true, 'path' => '/' . str_replace('\\', '/', $path), 'filter' => '/cases|integration|functional/')); }
/** * Performs service location lookups by library, based on the library's `'defer'` flag. * Libraries with `'defer'` set to `true` will be searched last when looking up services. * * @param boolean $defer A boolean flag indicating which libraries to search, either the ones * with the `'defer'` flag set, or the ones without. * @param array $paths List of paths to be searched for the given service (class). These are * defined in `lithium\core\Libraries::$_paths`, and are organized by class type. * @param array $params The list of insert parameters to be injected into each path format * string when searching for classes. * @param array $options * @return string Returns a class path as a string if a given class is found, or null if no * class in any path matching any of the parameters is located. * @see lithium\core\Libraries::$_paths * @see lithium\core\Libraries::locate() */ protected static function _locateDeferred($defer, $paths, $params, $options = array()) { if (isset($options['library'])) { $libraries = (array) $options['library']; $libraries = array_intersect_key(static::$_configurations, array_combine($libraries, array_fill(0, count($libraries), null))); } else { $libraries = static::$_configurations; } foreach ($libraries as $library => $config) { if ($config['defer'] !== $defer && $defer !== null) { continue; } foreach ($paths as $pathTemplate => $pathOptions) { if (is_int($pathTemplate)) { $pathTemplate = $pathOptions; $pathOptions = array(); } $opts = $options + $pathOptions; if (isset($opts['libraries']) && !in_array($library, (array) $opts['libraries'])) { unset($opts['libraries']); continue; } $params['library'] = $library; $class = str_replace('\\*', '', String::insert($pathTemplate, $params)); if (file_exists($file = Libraries::path($class, $opts))) { return $options['type'] === 'file' ? $file : $class; } } } }
/** * Takes the raw line numbers and returns results with the code from * uncovered lines included. * * @param array $result The raw line number results * @return array */ protected static function collectLines($result) { $output = null; $aggregate = array('covered' => 0, 'executable' => 0); foreach ($result as $class => $coverage) { $out = array(); $file = Libraries::path($class); $aggregate['covered'] += count($coverage['covered']); $aggregate['executable'] += count($coverage['executable']); $uncovered = array_flip($coverage['uncovered']); $contents = explode("\n", file_get_contents($file)); array_unshift($contents, ' '); $count = count($contents); for ($i = 1; $i <= $count; $i++) { if (isset($uncovered[$i])) { if (!isset($out[$i - 2])) { $out[$i - 2] = array('class' => 'ignored', 'data' => '...'); } if (!isset($out[$i - 1])) { $out[$i - 1] = array('class' => 'covered', 'data' => $contents[$i - 1]); } $out[$i] = array('class' => 'uncovered', 'data' => $contents[$i]); if (!isset($uncovered[$i + 1])) { $out[$i + 1] = array('class' => 'covered', 'data' => $contents[$i + 1]); } } elseif (isset($out[$i - 1]) && $out[$i - 1]['data'] !== '...' && !isset($out[$i]) && !isset($out[$i + 1])) { $out[$i] = array('class' => 'ignored', 'data' => '...'); } } $result[$class]['output'][$file] = $out; } return $result; }
public function testAdding() { $location = Locations::add('test', array('adapter' => 'FileSystem', 'location' => Libraries::path('li3_filemanager\\', array('dirs' => true)) . '/resources/tmp')); $this->assertTrue(is_array($location)); }
/** * Tests that `Libraries::map()` and `Libraries::unmap()` * */ public function testMapUnmap() { $testApp = Libraries::get(true, 'resources') . '/tmp/tests/test_app'; mkdir($testApp, 0777, true); Libraries::add('test_app', array('path' => $testApp)); mkdir($testApp . '/lib', 0777); mkdir($testApp . '/_patch', 0777); file_put_contents($testApp . '/lib/LibTest.php', "<?php namespace test_app\\lib;\n\n\t\t\tclass LibTest{ public function testMe() {\n\t\t\t\treturn 'core class';\n\t\t\t}}"); file_put_contents($testApp . '/_patch/PatchedLibTest.php', "<?php namespace test_app\\lib;\n\n\t\t\tclass LibTest{ public function testMe() {\n\t\t\t\treturn 'patched class';\n\t\t\t}}"); $expected = $result = Libraries::realPath($testApp . '/lib/LibTest.php'); $result = Libraries::path('test_app\\lib\\LibTest'); $this->assertEqual($expected, $result); Libraries::map(array('test_app\\lib\\LibTest' => $testApp . '/_patch/PatchedLibTest.php')); $expected = $result = Libraries::realPath($testApp . '/_patch/PatchedLibTest.php'); $result = Libraries::path('test_app\\lib\\LibTest'); Libraries::unmap(array('test_app\\lib\\LibTest')); $expected = $result = Libraries::realPath($testApp . '/lib/LibTest.php'); $result = Libraries::path('test_app\\lib\\LibTest'); $this->assertEqual($expected, $result); Libraries::map(array('test_app\\lib\\LibTest' => $testApp . '/_patch/PatchedLibTest.php')); Libraries::unmap('test_app\\lib\\LibTest'); $expected = $result = Libraries::realPath($testApp . '/lib/LibTest.php'); $result = Libraries::path('test_app\\lib\\LibTest'); Libraries::map(array('test_app\\lib\\LibTest' => $testApp . '/_patch/PatchedLibTest.php')); $object = new \test_app\lib\LibTest(); $result = $object->testMe(); $this->assertEqual('patched class', $result); $this->_cleanUp(); }
/** * Returns data to be output by a reporter. * * @param string $format I.e. `'html'` or `'text'`. * @param array $analysis The results of the analysis. * @return string|void */ public static function output($format, $analysis) { if (empty($analysis)) { return null; } $output = null; $aggregate = array('covered' => 0, 'executable' => 0); foreach ($analysis as $class => $coverage) { $out = array(); $file = Libraries::path($class); $output .= static::stats($format, $class, $coverage); $aggregate['covered'] += count($coverage['covered']); $aggregate['executable'] += count($coverage['executable']); $uncovered = array_flip($coverage['uncovered']); $contents = explode("\n", file_get_contents($file)); array_unshift($contents, ' '); $count = count($contents); for ($i = 1; $i <= $count; $i++) { if (isset($uncovered[$i])) { if (!isset($out[$i - 2])) { $out[$i - 2] = array('class' => 'ignored', 'data' => '...'); } if (!isset($out[$i - 1])) { $out[$i - 1] = array('class' => 'covered', 'data' => $contents[$i - 1]); } $out[$i] = array('class' => 'uncovered', 'data' => $contents[$i]); if (!isset($uncovered[$i + 1])) { $out[$i + 1] = array('class' => 'covered', 'data' => $contents[$i + 1]); } } elseif (isset($out[$i - 1]) && $out[$i - 1]['data'] !== '...' && !isset($out[$i]) && !isset($out[$i + 1])) { $out[$i] = array('class' => 'ignored', 'data' => '...'); } } $data = array(); foreach ($out as $line => $row) { $row['line'] = $line; $data[] = static::_format($format, 'row', $row); } if (!empty($data)) { $output .= static::_format($format, 'file', compact('file', 'data')); } } return $output; }
public function testPathDirectoryLookups() { $library = Libraries::get('lithium'); $base = $library['path'] . '/'; $result = Libraries::path('lithium\\template\\View', array('dirs' => true)); $expected = $base . 'template/View.php'; $this->assertEqual($expected, $result); $result = Libraries::path('lithium\\template\\views', array('dirs' => true)); $this->assertNull($result); }