RegexTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Controller
  17. * @subpackage UnitTests
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /** Zend_Controller_Router_Route_Regex */
  23. require_once 'Zend/Controller/Router/Route/Regex.php';
  24. /**
  25. * @category Zend
  26. * @package Zend_Controller
  27. * @subpackage UnitTests
  28. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. * @group Zend_Controller
  31. * @group Zend_Controller_Router
  32. */
  33. class Zend_Controller_Router_Route_RegexTest extends PHPUnit_Framework_TestCase
  34. {
  35. public function testStaticMatch()
  36. {
  37. $route = new Zend_Controller_Router_Route_Regex('users/all');
  38. $values = $route->match('users/all');
  39. $this->assertSame(array(), $values);
  40. }
  41. public function testStaticUTFMatch()
  42. {
  43. $route = new Zend_Controller_Router_Route_Regex('żółć');
  44. $values = $route->match('żółć');
  45. $this->assertSame(array(), $values);
  46. }
  47. public function testURLDecode()
  48. {
  49. $route = new Zend_Controller_Router_Route_Regex('żółć');
  50. $values = $route->match('%C5%BC%C3%B3%C5%82%C4%87');
  51. $this->assertSame(array(), $values);
  52. }
  53. public function testStaticNoMatch()
  54. {
  55. $route = new Zend_Controller_Router_Route_Regex('users/a/martel');
  56. $values = $route->match('users/a');
  57. $this->assertSame(false, $values);
  58. }
  59. public function testStaticMatchWithDefaults()
  60. {
  61. $route = new Zend_Controller_Router_Route_Regex('users/all', array('controller' => 'ctrl'));
  62. $values = $route->match('users/all');
  63. $this->assertSame(1, count($values));
  64. $this->assertSame('ctrl', $values['controller']);
  65. }
  66. public function testRootRoute()
  67. {
  68. $route = new Zend_Controller_Router_Route_Regex('');
  69. $values = $route->match('/');
  70. $this->assertSame(array(), $values);
  71. }
  72. public function testVariableMatch()
  73. {
  74. $route = new Zend_Controller_Router_Route_Regex('users/(.+)');
  75. $values = $route->match('users/martel');
  76. $this->assertSame(1, count($values));
  77. $this->assertSame('martel', $values[1]);
  78. }
  79. public function testDoubleMatch()
  80. {
  81. $route = new Zend_Controller_Router_Route_Regex('users/(user_(\d+).html)');
  82. $values = $route->match('users/user_1354.html');
  83. $this->assertSame(2, count($values));
  84. $this->assertSame('user_1354.html', $values[1]);
  85. $this->assertSame('1354', $values[2]);
  86. }
  87. public function testNegativeMatch()
  88. {
  89. $route = new Zend_Controller_Router_Route_Regex('((?!admin|moderator).+)',
  90. array('module' => 'index', 'controller' => 'index'),
  91. array(1 => 'action')
  92. );
  93. $values = $route->match('users');
  94. $this->assertSame(3, count($values));
  95. $this->assertSame('index', $values['module']);
  96. $this->assertSame('index', $values['controller']);
  97. $this->assertSame('users', $values['action']);
  98. }
  99. public function testNumericDefault()
  100. {
  101. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array(1 => 'martel'));
  102. $values = $route->match('users');
  103. $this->assertSame(1, count($values));
  104. $this->assertSame('martel', $values[1]);
  105. }
  106. public function testVariableMatchWithNumericDefault()
  107. {
  108. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array(1 => 'martel'));
  109. $values = $route->match('users/vicki');
  110. $this->assertSame(1, count($values));
  111. $this->assertSame('vicki', $values[1]);
  112. }
  113. public function testNamedVariableMatch()
  114. {
  115. $route = new Zend_Controller_Router_Route_Regex('users/(?P<username>.+)');
  116. $values = $route->match('users/martel');
  117. $this->assertSame(1, count($values));
  118. $this->assertSame('martel', $values[1]);
  119. }
  120. public function testMappedVariableMatch()
  121. {
  122. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, array(1 => 'username'));
  123. $values = $route->match('users/martel');
  124. $this->assertSame(1, count($values));
  125. $this->assertSame('martel', $values['username']);
  126. }
  127. public function testMappedVariableWithDefault()
  128. {
  129. $route = new Zend_Controller_Router_Route_Regex('users(?:/(.+))?', array('username' => 'martel'), array(1 => 'username'));
  130. $values = $route->match('users');
  131. $this->assertSame(1, count($values));
  132. $this->assertSame('martel', $values['username']);
  133. }
  134. public function testMappedVariableWithNamedSubpattern()
  135. {
  136. $route = new Zend_Controller_Router_Route_Regex('users/(?P<name>.+)', null, array(1 => 'username'));
  137. $values = $route->match('users/martel');
  138. $this->assertSame(1, count($values));
  139. $this->assertSame('martel', $values['username']);
  140. }
  141. public function testOptionalVar()
  142. {
  143. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', null, array(1 => 'username', 2 => 'page'));
  144. $values = $route->match('users/martel/p/1');
  145. $this->assertSame(2, count($values));
  146. $this->assertSame('martel', $values['username']);
  147. $this->assertSame('1', $values['page']);
  148. }
  149. public function testEmptyOptionalVar()
  150. {
  151. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', null, array(1 => 'username', 2 => 'page'));
  152. $values = $route->match('users/martel');
  153. $this->assertSame(1, count($values));
  154. $this->assertSame('martel', $values['username']);
  155. }
  156. public function testMixedMap()
  157. {
  158. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', null, array(1 => 'username'));
  159. $values = $route->match('users/martel/p/1');
  160. $this->assertSame(2, count($values));
  161. $this->assertSame('martel', $values['username']);
  162. $this->assertSame('1', $values[2]);
  163. }
  164. public function testNumericDefaultWithMap()
  165. {
  166. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array(1 => 'martel'), array(1 => 'username'));
  167. $values = $route->match('users');
  168. $this->assertSame(1, count($values));
  169. $this->assertSame('martel', $values['username']);
  170. }
  171. public function testMixedMapWithDefault()
  172. {
  173. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', array(2 => '1'), array(1 => 'username'));
  174. $values = $route->match('users/martel/p/10');
  175. $this->assertSame(2, count($values));
  176. $this->assertSame('martel', $values['username']);
  177. $this->assertSame('10', $values[2]);
  178. }
  179. public function testMixedMapWithDefaults2()
  180. {
  181. $route = new Zend_Controller_Router_Route_Regex('users/?(\w+)?/?(?:p/(\d+))?', array(2 => '1', 'username' => 'martel'), array(1 => 'username'));
  182. $values = $route->match('users');
  183. $this->assertSame(2, count($values));
  184. $this->assertSame('martel', $values['username']);
  185. $this->assertSame('1', $values[2]);
  186. }
  187. public function testOptionalVarWithMapAndDefault()
  188. {
  189. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', array('page' => '1', 'username' => 'martel'), array(1 => 'username', 2 => 'page'));
  190. $values = $route->match('users/martel');
  191. $this->assertSame(2, count($values));
  192. $this->assertSame('martel', $values['username']);
  193. $this->assertSame('1', $values['page']);
  194. }
  195. public function testOptionalVarWithMapAndNumericDefault()
  196. {
  197. $route = new Zend_Controller_Router_Route_Regex('users/(\w+)/?(?:p/(\d+))?', array(2 => '1'), array(2 => 'page'));
  198. $values = $route->match('users/martel');
  199. $this->assertSame(2, count($values));
  200. $this->assertSame('martel', $values[1]);
  201. $this->assertSame('1', $values['page']);
  202. }
  203. public function testMappedAndNumericDefault()
  204. {
  205. $route = new Zend_Controller_Router_Route_Regex('users/?(\w+)?', array(1 => 'martel', 'username' => 'vicki'), array(1 => 'username'));
  206. $values = $route->match('users');
  207. // Matches both defaults but the one defined last is used
  208. $this->assertSame(1, count($values));
  209. $this->assertSame('vicki', $values['username']);
  210. }
  211. public function testAssemble()
  212. {
  213. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, array(1 => 'username'), 'users/%s');
  214. $values = $route->match('users/martel');
  215. $url = $route->assemble();
  216. $this->assertSame('users/martel', $url);
  217. }
  218. public function testAssembleWithDefault()
  219. {
  220. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array(1 => 'martel'), null, 'users/%s');
  221. $values = $route->match('users');
  222. $url = $route->assemble();
  223. $this->assertSame('users/martel', $url);
  224. }
  225. public function testAssembleWithMappedDefault()
  226. {
  227. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array('username' => 'martel'), array(1 => 'username'), 'users/%s');
  228. $values = $route->match('users');
  229. $url = $route->assemble();
  230. $this->assertSame('users/martel', $url);
  231. }
  232. public function testAssembleWithData()
  233. {
  234. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, null, 'users/%s');
  235. $values = $route->match('users/martel');
  236. $url = $route->assemble(array(1 => 'vicki'));
  237. $this->assertSame('users/vicki', $url);
  238. }
  239. public function testAssembleWithMappedVariable()
  240. {
  241. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, array(1 => 'username'), 'users/%s');
  242. $values = $route->match('users/martel');
  243. $url = $route->assemble(array('username' => 'vicki'));
  244. $this->assertSame('users/vicki', $url);
  245. }
  246. public function testAssembleWithMappedVariableAndNumericKey()
  247. {
  248. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, array(1 => 'username'), 'users/%s');
  249. $values = $route->match('users/martel');
  250. $url = $route->assemble(array(1 => 'vicki'));
  251. $this->assertSame('users/vicki', $url);
  252. }
  253. public function testAssembleWithoutMatch()
  254. {
  255. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, null, 'users/%s');
  256. try {
  257. $url = $route->assemble();
  258. $this->fail();
  259. } catch (Exception $e) {}
  260. }
  261. public function testAssembleWithDefaultWithoutMatch()
  262. {
  263. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array(1 => 'martel'), null, 'users/%s');
  264. $url = $route->assemble();
  265. $this->assertSame('users/martel', $url);
  266. }
  267. public function testAssembleWithMappedDefaultWithoutMatch()
  268. {
  269. $route = new Zend_Controller_Router_Route_Regex('users/?(.+)?', array('username' => 'martel'), array(1 => 'username'), 'users/%s');
  270. $url = $route->assemble();
  271. $this->assertSame('users/martel', $url);
  272. }
  273. public function testAssembleWithDataWithoutMatch()
  274. {
  275. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, null, 'users/%s');
  276. $url = $route->assemble(array(1 => 'vicki'));
  277. $this->assertSame('users/vicki', $url);
  278. }
  279. public function testAssembleWithMappedVariableWithoutMatch()
  280. {
  281. $route = new Zend_Controller_Router_Route_Regex('users/(.+)', null, array(1 => 'username'), 'users/%s');
  282. $url = $route->assemble(array('username' => 'vicki'));
  283. $this->assertSame('users/vicki', $url);
  284. }
  285. public function testAssembleZF1332()
  286. {
  287. $route = new Zend_Controller_Router_Route_Regex(
  288. '(.+)\.([0-9]+)-([0-9]+)\.html',
  289. array('module' => 'default', 'controller' => 'content.item', 'action' => 'forward'),
  290. array(1 => 'name', 2 => 'id', 3 => 'class'),
  291. '%s.%s-%s.html'
  292. );
  293. $route->match('uml-explained-composition.72-3.html');
  294. $url = $route->assemble();
  295. $this->assertSame('uml-explained-composition.72-3.html', $url);
  296. $url = $route->assemble(array('name' => 'post_name', 'id' => '12', 'class' => 5));
  297. $this->assertSame('post_name.12-5.html', $url);
  298. }
  299. public function testGetInstance()
  300. {
  301. require_once 'Zend/Config.php';
  302. $routeConf = array(
  303. 'route' => 'forum/(\d+)',
  304. 'reverse' => 'forum/%d',
  305. 'defaults' => array(
  306. 'controller' => 'ctrl'
  307. )
  308. );
  309. /* numeric Zend_Config indexes don't work at the moment
  310. 'map' => array(
  311. '1' => 'forum_id'
  312. )
  313. */
  314. $config = new Zend_Config($routeConf);
  315. $route = Zend_Controller_Router_Route_Regex::getInstance($config);
  316. $this->assertTrue($route instanceof Zend_Controller_Router_Route_Regex);
  317. $values = $route->match('forum/1');
  318. $this->assertSame('ctrl', $values['controller']);
  319. }
  320. /**
  321. * @group ZF-2301
  322. */
  323. public function testAssemblyOfRouteWithMergedMatchedParts()
  324. {
  325. $route = new Zend_Controller_Router_Route_Regex(
  326. 'itemlist(?:/(\d+))?',
  327. array('page' => 1), // Defaults
  328. array(1 => 'page'), // Parameter map
  329. 'itemlist/%d'
  330. );
  331. // make sure defaults work
  332. $this->assertEquals(array('page' => 1), $route->match('/itemlist/'));
  333. // make sure default assembly work
  334. $this->assertEquals('itemlist/1', $route->assemble());
  335. // make sure the route is parsed correctly
  336. $this->assertEquals(array('page' => 2), $route->match('/itemlist/2'));
  337. // check to make sure that the default assembly will return with default 1 (previously defined)
  338. $this->assertEquals('itemlist/2', $route->assemble());
  339. // check to make sure that the assembly will return with provided page=3 in the correct place
  340. $this->assertEquals('itemlist/3', $route->assemble(array('page' => 3)));
  341. // check to make sure that the assembly can reset a single parameter
  342. $this->assertEquals('itemlist/1', $route->assemble(array('page' => null)));
  343. }
  344. /**
  345. * @group ZF-4335
  346. */
  347. public function testAssembleMethodShouldNotIgnoreEncodeParam()
  348. {
  349. $route = new Zend_Controller_Router_Route_Regex(
  350. 'blog/archive/(.+)-(.+)\.html',
  351. array(
  352. 'controller' => 'blog',
  353. 'action' => 'view'
  354. ),
  355. array(
  356. 1 => 'name',
  357. 2 => 'description'
  358. ),
  359. 'blog/archive/%s-%s.html'
  360. );
  361. $data = array('string.that&has=some>', 'characters<that;need+to$be*encoded');
  362. $url = $route->assemble($data, false, true);
  363. $expectedUrl = 'blog/archive/string.that%26has%3Dsome%3E-characters%3Cthat%3Bneed%2Bto%24be%2Aencoded.html';
  364. $this->assertEquals($url, $expectedUrl, 'Assembled url isn\'t encoded properly when using the encode parameter.');
  365. }
  366. /**
  367. * Allow using <lang>1</lang> instead of invalid <1>lang</1> for xml router
  368. * config.
  369. *
  370. * <zend-config>
  371. * <routes>
  372. * <page>
  373. * <type>Zend_Controller_Router_Route_Regex</type>
  374. * <route>([a-z]{2})/page/(.*)</route>
  375. * <defaults>
  376. * <controller>index</controller>
  377. * <action>showpage</action>
  378. * </defaults>
  379. * <map>
  380. * <lang>1</lang>
  381. * <title>2</title>
  382. * </map>
  383. * <reverse>%s/page/%s</reverse>
  384. * </page>
  385. * </routes>
  386. * </zend-config>
  387. *
  388. *
  389. * @group ZF-7658
  390. */
  391. public function testAssembleWithFlippedMappedVariables()
  392. {
  393. $route = new Zend_Controller_Router_Route_Regex(
  394. '([a-z]{2})/page/(.*)',
  395. array('controller' => 'index', 'action' => 'showpage'),
  396. array('lang' => 1, 'title' => 2),
  397. '%s/page/%s'
  398. );
  399. $url = $route->assemble(array(
  400. 'lang' => 'fi',
  401. 'title' => 'Suomi'
  402. ), true, true);
  403. $this->assertEquals($url, 'fi/page/Suomi');
  404. }
  405. }