diff --git a/core/core.services.yml b/core/core.services.yml index 92b5f7c..98bba46 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -173,6 +173,9 @@ services: path.alias_manager: class: Drupal\Core\Path\AliasManager arguments: ['@path.alias_storage', '@path.alias_whitelist', '@language_manager'] + path.matcher: + class: Drupal\Core\Path\PathMatcher + arguments: ['@config.factory'] http_client: class: Drupal\Core\Http\Client tags: diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index b00d23b..7108d24 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -322,6 +322,9 @@ function install_begin_request(&$install_state) { $container ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager') ->addArgument(new Reference('language_manager')); + $container + ->register('path.matcher', 'Drupal\Core\Path\PathMatcher') + ->addArgument(new Reference('config.factory')); \Drupal::setContainer($container); diff --git a/core/includes/path.inc b/core/includes/path.inc index 6043749..3898d15 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -41,27 +41,13 @@ function drupal_is_front_page() { * * @return * Boolean value: TRUE if the path matches a pattern, FALSE otherwise. + * + * @deprecated as of Drupal 8.0. Use + * \Drupal\Core\Path\PathMatcherInterface::matchPath() instead. */ function drupal_match_path($path, $patterns) { - $regexps = &drupal_static(__FUNCTION__); - - if (!isset($regexps[$patterns])) { - // Convert path settings to a regular expression. - // Therefore replace newlines with a logical or, /* with asterisks and the with the frontpage. - $to_replace = array( - '/(\r\n?|\n)/', // newlines - '/\\\\\*/', // asterisks - '/(^|\|)\\\\($|\|)/' // - ); - $replacements = array( - '|', - '.*', - '\1' . preg_quote(\Drupal::config('system.site')->get('page.front'), '/') . '\2' - ); - $patterns_quoted = preg_quote($patterns, '/'); - $regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/'; - } - return (bool)preg_match($regexps[$patterns], $path); + $patterns_array = preg_split('/(\r\n?|\n)/', $patterns); + return \Drupal::service('path.matcher')->matchPath($path, $patterns_array); } /** diff --git a/core/lib/Drupal/Core/Path/PathMatcher.php b/core/lib/Drupal/Core/Path/PathMatcher.php new file mode 100644 index 0000000..ea760c2 --- /dev/null +++ b/core/lib/Drupal/Core/Path/PathMatcher.php @@ -0,0 +1,69 @@ +frontPage = $config_factory->get('system.site')->get('page.front'); + } + + /** + * {@inheritdoc} + */ + public function matchPath($path, array $patterns) { + // Convert array to a string for easier find and replace. + $pattern_string = implode("\n", $patterns); + if (!isset($this->regexes[$pattern_string])) { + // Convert path settings to a regular expression. + // Therefore replace newlines with a logical or, /* with asterisks and the + // with the frontpage. + $to_replace = array( + // newlines. + '/(\r\n?|\n)/', + // asterisks. + '/\\\\\*/', + // . + '/(^|\|)\\\\($|\|)/', + ); + $replacements = array( + '|', + '.*', + '\1' . preg_quote($this->frontPage, '/') . '\2', + ); + $patterns_quoted = preg_quote($pattern_string, '/'); + $this->regexes[$pattern_string] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/'; + } + return (bool) preg_match($this->regexes[$pattern_string], $path); + } +} diff --git a/core/lib/Drupal/Core/Path/PathMatcherInterface.php b/core/lib/Drupal/Core/Path/PathMatcherInterface.php new file mode 100644 index 0000000..091ef8f --- /dev/null +++ b/core/lib/Drupal/Core/Path/PathMatcherInterface.php @@ -0,0 +1,28 @@ + 'Path Matcher tests', + 'description' => 'Tests that path matching is working properly.', + 'group' => 'Path', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + // Create a stub config factory with all config settings that will be + // checked during this test. + $config_factory_stub = $this->getConfigFactoryStub( + array( + 'system.site' => array( + 'page.front' => 'user', + ), + ) + ); + $this->pathMatcher = new PathMatcher($config_factory_stub); + $this->patterns = "my/pass/page\r\nmy/pass/page2\r\nfoo"; + } + + /** + * Test that standard paths works with multiple patterns. + */ + public function testPathsMultiplePatterns() { + $patterns = array('my/pass/page', 'my/pass/page2', 'foo'); + $this->assertTrue($this->pathMatcher->matchPath('my/pass/page', $patterns), 'The path my/pass/page matches.'); + $this->assertTrue($this->pathMatcher->matchPath('my/pass/page2', $patterns), 'The path my/pass/page2 matches.'); + } + + /** + * Test paths match against wildcards. + */ + public function testWildcardPath() { + $patterns = array('my/pass/*'); + $this->assertTrue($this->pathMatcher->matchPath('my/pass/page3', $patterns), 'The path my/pass/page3 matches.'); + } + + /** + * Test a missing path does not match. + */ + public function testNoMatchPath() { + $patterns = array('my/pass/page', 'my/pass/page2', 'foo'); + $this->assertFalse($this->pathMatcher->matchPath('my/pass/page4', $patterns), 'The path my/pass/page4 does not match.'); + } + +}