|  |  |  | <?php
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace yiiunit\framework\web;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use yii\web\UrlManager;
 | 
					
						
							|  |  |  | use yii\web\UrlRule;
 | 
					
						
							|  |  |  | use yii\web\Request;
 | 
					
						
							|  |  |  | use yiiunit\TestCase;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @group web
 | 
					
						
							|  |  |  |  */
 | 
					
						
							|  |  |  | class UrlRuleTest extends TestCase
 | 
					
						
							|  |  |  | {
 | 
					
						
							|  |  |  | 	public function testCreateUrl()
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		$manager = new UrlManager(['cache' => null]);
 | 
					
						
							|  |  |  | 		$suites = $this->getTestsForCreateUrl();
 | 
					
						
							|  |  |  | 		foreach ($suites as $i => $suite) {
 | 
					
						
							|  |  |  | 			list ($name, $config, $tests) = $suite;
 | 
					
						
							|  |  |  | 			$rule = new UrlRule($config);
 | 
					
						
							|  |  |  | 			foreach ($tests as $j => $test) {
 | 
					
						
							|  |  |  | 				list ($route, $params, $expected) = $test;
 | 
					
						
							|  |  |  | 				$url = $rule->createUrl($manager, $route, $params);
 | 
					
						
							|  |  |  | 				$this->assertEquals($expected, $url, "Test#$i-$j: $name");
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public function testParseRequest()
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		$manager = new UrlManager(['cache' => null]);
 | 
					
						
							|  |  |  | 		$request = new Request(['hostInfo' => 'http://en.example.com']);
 | 
					
						
							|  |  |  | 		$suites = $this->getTestsForParseRequest();
 | 
					
						
							|  |  |  | 		foreach ($suites as $i => $suite) {
 | 
					
						
							|  |  |  | 			list ($name, $config, $tests) = $suite;
 | 
					
						
							|  |  |  | 			$rule = new UrlRule($config);
 | 
					
						
							|  |  |  | 			foreach ($tests as $j => $test) {
 | 
					
						
							|  |  |  | 				$request->pathInfo = $test[0];
 | 
					
						
							|  |  |  | 				$route = $test[1];
 | 
					
						
							|  |  |  | 				$params = isset($test[2]) ? $test[2] : [];
 | 
					
						
							|  |  |  | 				$result = $rule->parseRequest($manager, $request);
 | 
					
						
							|  |  |  | 				if ($route === false) {
 | 
					
						
							|  |  |  | 					$this->assertFalse($result, "Test#$i-$j: $name");
 | 
					
						
							|  |  |  | 				} else {
 | 
					
						
							|  |  |  | 					$this->assertEquals([$route, $params], $result, "Test#$i-$j: $name");
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	protected function getTestsForCreateUrl()
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		// structure of each test
 | 
					
						
							|  |  |  | 		//   message for the test
 | 
					
						
							|  |  |  | 		//   config for the URL rule
 | 
					
						
							|  |  |  | 		//   list of inputs and outputs
 | 
					
						
							|  |  |  | 		//     route
 | 
					
						
							|  |  |  | 		//     params
 | 
					
						
							|  |  |  | 		//     expected output
 | 
					
						
							|  |  |  | 		return [
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], ''],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], '?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'without param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], 'posts'],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'posts?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'parsing only',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'mode' => UrlRule::PARSING_ONLY,
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], false],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'post/1'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1?tag=a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with param requirement',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 'abc'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'post/1'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1?tag=a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with multiple params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1-a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with optional param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2/a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with optional param not in pattern',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'multiple optional params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'sort' => 'yes'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'YES'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'yes'], 'post/a'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a', 'sort' => 'yes'], 'post/2/a'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a', 'sort' => 'no'], 'post/2/a/no'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'no'], 'post/a/no'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'optional param and required param separated by dashes',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/-a'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2-a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'optional param at the end',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<tag>/<page:\d+>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], 'post/a/2'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'consecutive optional params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'tag' => 'a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'b'], 'post/b'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'b'], 'post/2/b'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'consecutive optional params separated by dash',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'tag' => 'a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => '1abc', 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], 'post/-'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'b'], 'post/-b'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2-'],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 2, 'tag' => 'b'], 'post/2-b'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has parameters',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => [],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'post/index?page=1'],
 | 
					
						
							|  |  |  | 					['module/post/index', [], false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has parameters with regex',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller:post|comment>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => [],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'post/index?page=1'],
 | 
					
						
							|  |  |  | 					['comment/index', ['page' => 1], 'comment/index?page=1'],
 | 
					
						
							|  |  |  | 					['test/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post', [], false],
 | 
					
						
							|  |  |  | 					['module/post/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['controller' => 'comment'], 'post/index?controller=comment'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has default parameter',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller:post|comment>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => ['action' => 'index'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/view', ['page' => 1], 'post/view?page=1'],
 | 
					
						
							|  |  |  | 					['comment/view', ['page' => 1], 'comment/view?page=1'],
 | 
					
						
							|  |  |  | 					['test/view', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['test/index', ['page' => 1], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'post?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern with suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '.html',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], ''],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], '?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'regular pattern with suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '.html',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], 'posts.html'],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'posts.html?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern with slash suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '/',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], ''],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], '?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'regular pattern with slash suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '/',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', [], 'posts/'],
 | 
					
						
							|  |  |  | 					['comment/index', [], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1], 'posts/?page=1'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with host info',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 					'host' => 'http://<lang:en|fr>.example.com',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a'], false],
 | 
					
						
							|  |  |  | 					['post/index', ['page' => 1, 'tag' => 'a', 'lang' => 'en'], 'http://en.example.com/post/a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 		];
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	protected function getTestsForParseRequest()
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		// structure of each test
 | 
					
						
							|  |  |  | 		//   message for the test
 | 
					
						
							|  |  |  | 		//   config for the URL rule
 | 
					
						
							|  |  |  | 		//   list of inputs and outputs
 | 
					
						
							|  |  |  | 		//     pathInfo
 | 
					
						
							|  |  |  | 		//     expected route, or false if the rule doesn't apply
 | 
					
						
							|  |  |  | 		//     expected params, or not set if empty
 | 
					
						
							|  |  |  | 		return [
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['', 'post/index'],
 | 
					
						
							|  |  |  | 					['a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'without param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['posts', 'post/index'],
 | 
					
						
							|  |  |  | 					['a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with dot', // https://github.com/yiisoft/yii/issues/2945
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts.html',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['posts.html', 'post/index'],
 | 
					
						
							|  |  |  | 					['postsahtml', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'creation only',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'mode' => UrlRule::CREATION_ONLY,
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['posts', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1', 'post/index', ['page' => '1']],
 | 
					
						
							|  |  |  | 					['post/a', 'post/index', ['page' => 'a']],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 					['posts', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with param requirement',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1', 'post/index', ['page' => '1']],
 | 
					
						
							|  |  |  | 					['post/a', false],
 | 
					
						
							|  |  |  | 					['post/1/a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with multiple params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1-a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/a', false],
 | 
					
						
							|  |  |  | 					['post/1', false],
 | 
					
						
							|  |  |  | 					['post/1/a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with optional param',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1/a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/2/a', 'post/index', ['page' => '2', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/1', 'post/index', ['page' => '1', 'tag' => '1']],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with optional param not in pattern',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/1', 'post/index', ['page' => '1', 'tag' => '1']],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'multiple optional params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'sort' => 'yes'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1/a/yes', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'yes']],
 | 
					
						
							|  |  |  | 					['post/1/a/no', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'no']],
 | 
					
						
							|  |  |  | 					['post/2/a/no', 'post/index', ['page' => '2', 'tag' => 'a', 'sort' => 'no']],
 | 
					
						
							|  |  |  | 					['post/2/a', 'post/index', ['page' => '2', 'tag' => 'a', 'sort' => 'yes']],
 | 
					
						
							|  |  |  | 					['post/a/no', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'no']],
 | 
					
						
							|  |  |  | 					['post/a', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'yes']],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'optional param and required param separated by dashes',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1-a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/2-a', 'post/index', ['page' => '2', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/-a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/a', false],
 | 
					
						
							|  |  |  | 					['post-a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'optional param at the end',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<tag>/<page:\d+>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/a/1', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/a/2', 'post/index', ['page' => '2', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/2', 'post/index', ['page' => '1', 'tag' => '2']],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'consecutive optional params',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>/<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'tag' => 'a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/2/b', 'post/index', ['page' => '2', 'tag' => 'b']],
 | 
					
						
							|  |  |  | 					['post/2', 'post/index', ['page' => '2', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/b', 'post/index', ['page' => '1', 'tag' => 'b']],
 | 
					
						
							|  |  |  | 					['post//b', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'consecutive optional params separated by dash',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>-<tag>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'defaults' => ['page' => 1, 'tag' => 'a'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/2-b', 'post/index', ['page' => '2', 'tag' => 'b']],
 | 
					
						
							|  |  |  | 					['post/2-', 'post/index', ['page' => '2', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post/-b', 'post/index', ['page' => '1', 'tag' => 'b']],
 | 
					
						
							|  |  |  | 					['post/-', 'post/index', ['page' => '1', 'tag' => 'a']],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has parameters',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => [],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', 'post/index'],
 | 
					
						
							|  |  |  | 					['module/post/index', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has parameters with regex',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller:post|comment>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => [],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/index', 'post/index'],
 | 
					
						
							|  |  |  | 					['comment/index', 'comment/index'],
 | 
					
						
							|  |  |  | 					['test/index', false],
 | 
					
						
							|  |  |  | 					['post', false],
 | 
					
						
							|  |  |  | 					['module/post/index', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'route has default parameter',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '<controller:post|comment>/<action>',
 | 
					
						
							|  |  |  | 					'route' => '<controller>/<action>',
 | 
					
						
							|  |  |  | 					'defaults' => ['action' => 'index'],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/view', 'post/view'],
 | 
					
						
							|  |  |  | 					['comment/view', 'comment/view'],
 | 
					
						
							|  |  |  | 					['test/view', false],
 | 
					
						
							|  |  |  | 					['post', 'post/index'],
 | 
					
						
							|  |  |  | 					['posts', false],
 | 
					
						
							|  |  |  | 					['test', false],
 | 
					
						
							|  |  |  | 					['index', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern with suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '.html',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['', 'post/index'],
 | 
					
						
							|  |  |  | 					['.html', false],
 | 
					
						
							|  |  |  | 					['a.html', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'regular pattern with suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '.html',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['posts.html', 'post/index'],
 | 
					
						
							|  |  |  | 					['posts', false],
 | 
					
						
							|  |  |  | 					['posts.HTML', false],
 | 
					
						
							|  |  |  | 					['a.html', false],
 | 
					
						
							|  |  |  | 					['a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'empty pattern with slash suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => '',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '/',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['', 'post/index'],
 | 
					
						
							|  |  |  | 					['a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'regular pattern with slash suffix',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'posts',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'suffix' => '/',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['posts/', 'post/index'],
 | 
					
						
							|  |  |  | 					['posts', false],
 | 
					
						
							|  |  |  | 					['a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'with host info',
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					'pattern' => 'post/<page:\d+>',
 | 
					
						
							|  |  |  | 					'route' => 'post/index',
 | 
					
						
							|  |  |  | 					'host' => 'http://<lang:en|fr>.example.com',
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 				[
 | 
					
						
							|  |  |  | 					['post/1', 'post/index', ['page' => '1', 'lang' => 'en']],
 | 
					
						
							|  |  |  | 					['post/a', false],
 | 
					
						
							|  |  |  | 					['post/1/a', false],
 | 
					
						
							|  |  |  | 				],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 		];
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 |