You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							658 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							658 lines
						
					
					
						
							16 KiB
						
					
					
				| <?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], | |
| 				], | |
| 			], | |
| 		]; | |
| 	} | |
| }
 | |
| 
 |