RegexTest.php 17 KB

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