/** * Get the EditorConfig properties for the specified path. * * Returns a map containing all of the EditorConfig properties which apply * to the specified path. The following rules are applied when processing * EditorConfig files: * * - If a glob does not contain `/`, it can match a path in any subdirectory. * - If the first character of a glob is `/`, it will only match files in the * same directory as the `.editorconfig` file. * - Properties and values are case-insensitive. * - Unknown properties will be silently ignored. * - Values are not validated against the specification (this may change in * the future). * - Invalid glob patterns will be silently ignored. * * @param string * @return map<string, wild> */ public function getProperties($path) { $configs = $this->getEditorConfigs($path); $matches = array(); foreach ($configs as $config) { list($path_prefix, $editorconfig) = $config; foreach ($editorconfig as $glob => $properties) { if (!$glob) { continue; } if (strpos($glob, '/') === false) { $glob = '**/' . $glob; } else { if (strncmp($glob, '/', 0)) { $glob = substr($glob, 1); } } $glob = $path_prefix . '/' . $glob; try { if (!phutil_fnmatch($glob, $path)) { continue; } } catch (Exception $ex) { // Invalid glob pattern... ignore it. continue; } foreach ($properties as $property => $value) { $property = strtolower($property); if (!idx(self::$knownProperties, $property)) { // Unknown property... ignore it. continue; } if (is_string($value)) { $value = strtolower($value); } if ($value === '') { $value = null; } $matches[$property] = $value; } } } return $matches; }
public function testFnmatch() { $cases = array('' => array(array(''), array('.', '/')), '*' => array(array('file'), array('dir/', '/dir')), '**' => array(array('file', 'dir/', '/dir', 'dir/subdir/file'), array()), '**/file' => array(array('file', 'dir/file', 'dir/subdir/file', 'dir/subdir/subdir/file'), array('file/', 'file/dir')), 'file.*' => array(array('file.php', 'file.a', 'file.'), array('files.php', 'file.php/blah')), 'fo?' => array(array('foo', 'fot'), array('fooo', 'ffoo', 'fo/', 'foo/')), 'fo{o,t}' => array(array('foo', 'fot'), array('fob', 'fo/', 'foo/')), 'fo{o,\\,}' => array(array('foo', 'fo,'), array('foo/', 'fo,/')), 'fo{o,\\\\}' => array(array('foo', 'fo\\'), array('foo/', 'fo\\/')), '/foo' => array(array('/foo'), array('foo', '/foo/')), '*.txt' => array(array('file.txt', '.secret-file.txt'), array('dir/file.txt', 'file.TXT'), '\\*.txt' => array(array('*.txt'), array('file.txt')))); $invalid = array('{', 'asdf\\'); foreach ($cases as $input => $expect) { list($matches, $no_matches) = $expect; foreach ($matches as $match) { $this->assertTrue(phutil_fnmatch($input, $match), pht('Expecting "%s" to match "%s".', $input, $match)); } foreach ($no_matches as $no_match) { $this->assertFalse(phutil_fnmatch($input, $no_match), pht('Expecting "%s" not to match "%s".', $input, $no_match)); } } foreach ($invalid as $input) { $caught = null; try { phutil_fnmatch($input, ''); } catch (Exception $ex) { $caught = $ex; } $this->assertTrue($caught instanceof InvalidArgumentException); } }