RouterTest.php 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766
  1. <?php
  2. /**
  3. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Routing;
  16. use Cake\Core\App;
  17. use Cake\Core\Configure;
  18. use Cake\Core\Plugin;
  19. use Cake\Network\Request;
  20. use Cake\Routing\RouteCollection;
  21. use Cake\Routing\Router;
  22. use Cake\Routing\Route\Route;
  23. use Cake\TestSuite\TestCase;
  24. use TestPlugin\Routing\Route\TestRoute;
  25. /**
  26. * RouterTest class
  27. *
  28. */
  29. class RouterTest extends TestCase {
  30. /**
  31. * setUp method
  32. *
  33. * @return void
  34. */
  35. public function setUp() {
  36. parent::setUp();
  37. Configure::write('Routing', array('admin' => null, 'prefixes' => []));
  38. Router::fullbaseUrl('');
  39. Configure::write('App.fullBaseUrl', 'http://localhost');
  40. }
  41. /**
  42. * tearDown method
  43. *
  44. * @return void
  45. */
  46. public function tearDown() {
  47. parent::tearDown();
  48. Plugin::unload();
  49. Router::reload();
  50. Router::defaultRouteClass('Cake\Routing\Route\Route');
  51. }
  52. /**
  53. * testFullBaseUrl method
  54. *
  55. * @return void
  56. */
  57. public function testbaseUrl() {
  58. $this->assertRegExp('/^http(s)?:\/\//', Router::url('/', true));
  59. $this->assertRegExp('/^http(s)?:\/\//', Router::url(null, true));
  60. $this->assertRegExp('/^http(s)?:\/\//', Router::url(array('_full' => true)));
  61. }
  62. /**
  63. * Tests that the base URL can be changed at runtime.
  64. *
  65. * @return void
  66. */
  67. public function testfullBaseURL() {
  68. Router::fullbaseUrl('http://example.com');
  69. $this->assertEquals('http://example.com/', Router::url('/', true));
  70. $this->assertEquals('http://example.com', Configure::read('App.fullBaseUrl'));
  71. Router::fullBaseUrl('https://example.com');
  72. $this->assertEquals('https://example.com/', Router::url('/', true));
  73. $this->assertEquals('https://example.com', Configure::read('App.fullBaseUrl'));
  74. }
  75. /**
  76. * Test that Router uses App.base to build URL's when there are no stored
  77. * request objects.
  78. *
  79. * @return void
  80. */
  81. public function testBaseUrlWithBasePath() {
  82. Configure::write('App.base', '/cakephp');
  83. Router::fullBaseUrl('http://example.com');
  84. $this->assertEquals('http://example.com/cakephp/tasks', Router::url('/tasks', true));
  85. }
  86. /**
  87. * testRouteDefaultParams method
  88. *
  89. * @return void
  90. */
  91. public function testRouteDefaultParams() {
  92. Router::connect('/:controller', array('controller' => 'posts'));
  93. $this->assertEquals(Router::url(array('action' => 'index')), '/');
  94. }
  95. /**
  96. * testMapResources method
  97. *
  98. * @return void
  99. */
  100. public function testMapResources() {
  101. Router::mapResources('Posts');
  102. $_SERVER['REQUEST_METHOD'] = 'GET';
  103. $expected = [
  104. 'pass' => [],
  105. 'plugin' => null,
  106. 'controller' => 'Posts',
  107. 'action' => 'index',
  108. '_method' => 'GET',
  109. '_ext' => null
  110. ];
  111. $result = Router::parse('/posts');
  112. $this->assertEquals($expected, $result);
  113. $_SERVER['REQUEST_METHOD'] = 'GET';
  114. $expected = [
  115. 'pass' => ['13'],
  116. 'plugin' => null,
  117. 'controller' => 'Posts',
  118. 'action' => 'view',
  119. 'id' => '13',
  120. '_method' => 'GET',
  121. '_ext' => null
  122. ];
  123. $result = Router::parse('/posts/13');
  124. $this->assertEquals($expected, $result);
  125. $_SERVER['REQUEST_METHOD'] = 'POST';
  126. $expected = [
  127. 'pass' => [],
  128. 'plugin' => null,
  129. 'controller' => 'Posts',
  130. 'action' => 'add',
  131. '_method' => 'POST',
  132. '_ext' => null
  133. ];
  134. $result = Router::parse('/posts');
  135. $this->assertEquals($expected, $result);
  136. $_SERVER['REQUEST_METHOD'] = 'PUT';
  137. $expected = [
  138. 'pass' => ['13'],
  139. 'plugin' => null,
  140. 'controller' => 'Posts',
  141. 'action' => 'edit',
  142. 'id' => '13',
  143. '_method' => ['PUT', 'PATCH'],
  144. '_ext' => null
  145. ];
  146. $result = Router::parse('/posts/13');
  147. $this->assertEquals($expected, $result);
  148. $expected = [
  149. 'pass' => ['475acc39-a328-44d3-95fb-015000000000'],
  150. 'plugin' => null,
  151. 'controller' => 'Posts',
  152. 'action' => 'edit',
  153. 'id' => '475acc39-a328-44d3-95fb-015000000000',
  154. '_method' => ['PUT', 'PATCH'],
  155. '_ext' => null
  156. ];
  157. $result = Router::parse('/posts/475acc39-a328-44d3-95fb-015000000000');
  158. $this->assertEquals($expected, $result);
  159. $_SERVER['REQUEST_METHOD'] = 'DELETE';
  160. $expected = [
  161. 'pass' => ['13'],
  162. 'plugin' => null,
  163. 'controller' => 'Posts',
  164. 'action' => 'delete',
  165. 'id' => '13',
  166. '_method' => 'DELETE',
  167. '_ext' => null
  168. ];
  169. $result = Router::parse('/posts/13');
  170. $this->assertEquals($expected, $result);
  171. Router::reload();
  172. Router::mapResources('Posts', ['id' => '[a-z0-9_]+']);
  173. $_SERVER['REQUEST_METHOD'] = 'GET';
  174. $expected = [
  175. 'pass' => ['add'],
  176. 'plugin' => null,
  177. 'controller' => 'Posts',
  178. 'action' => 'view',
  179. 'id' => 'add',
  180. '_method' => 'GET',
  181. '_ext' => null
  182. ];
  183. $result = Router::parse('/posts/add');
  184. $this->assertEquals($expected, $result);
  185. $_SERVER['REQUEST_METHOD'] = 'PUT';
  186. $expected = [
  187. 'pass' => ['name'],
  188. 'plugin' => null,
  189. 'controller' => 'Posts',
  190. 'action' => 'edit',
  191. 'id' => 'name',
  192. '_method' => ['PUT', 'PATCH'],
  193. '_ext' => null
  194. ];
  195. $result = Router::parse('/posts/name');
  196. $this->assertEquals($expected, $result);
  197. }
  198. /**
  199. * testMapResources with plugin controllers.
  200. *
  201. * @return void
  202. */
  203. public function testPluginMapResources() {
  204. Router::mapResources('TestPlugin.TestPlugin');
  205. $_SERVER['REQUEST_METHOD'] = 'GET';
  206. $result = Router::parse('/test_plugin/test_plugin');
  207. $expected = array(
  208. 'pass' => [],
  209. 'plugin' => 'TestPlugin',
  210. 'controller' => 'TestPlugin',
  211. 'action' => 'index',
  212. '_method' => 'GET',
  213. '_ext' => null
  214. );
  215. $this->assertEquals($expected, $result);
  216. $_SERVER['REQUEST_METHOD'] = 'GET';
  217. $result = Router::parse('/test_plugin/test_plugin/13');
  218. $expected = array(
  219. 'pass' => array('13'),
  220. 'plugin' => 'TestPlugin',
  221. 'controller' => 'TestPlugin',
  222. 'action' => 'view',
  223. 'id' => '13',
  224. '_method' => 'GET',
  225. '_ext' => null
  226. );
  227. $this->assertEquals($expected, $result);
  228. }
  229. /**
  230. * Test mapResources with a prefix.
  231. *
  232. * @return void
  233. */
  234. public function testMapResourcesWithPrefix() {
  235. Router::mapResources('Posts', array('prefix' => 'api'));
  236. $_SERVER['REQUEST_METHOD'] = 'GET';
  237. $result = Router::parse('/api/posts');
  238. $expected = array(
  239. 'plugin' => null,
  240. 'controller' => 'Posts',
  241. 'action' => 'index',
  242. 'pass' => [],
  243. 'prefix' => 'api',
  244. '_method' => 'GET',
  245. '_ext' => null
  246. );
  247. $this->assertEquals($expected, $result);
  248. }
  249. /**
  250. * Test mapResources with a default extension.
  251. *
  252. * @return void
  253. */
  254. public function testMapResourcesWithExtension() {
  255. Router::extensions(['json', 'xml'], false);
  256. Router::mapResources('Posts', ['_ext' => 'json']);
  257. $_SERVER['REQUEST_METHOD'] = 'GET';
  258. $expected = array(
  259. 'plugin' => null,
  260. 'controller' => 'Posts',
  261. 'action' => 'index',
  262. 'pass' => [],
  263. '_method' => 'GET',
  264. '_ext' => 'json',
  265. );
  266. $result = Router::parse('/posts');
  267. $this->assertEquals($expected, $result);
  268. $result = Router::parse('/posts.json');
  269. $this->assertEquals($expected, $result);
  270. $expected['_ext'] = 'xml';
  271. $result = Router::parse('/posts.xml');
  272. $this->assertEquals($expected, $result);
  273. }
  274. /**
  275. * testMapResources with custom connectOptions
  276. */
  277. public function testMapResourcesConnectOptions() {
  278. Plugin::load('TestPlugin');
  279. Router::mapResources('Posts', array(
  280. 'connectOptions' => array(
  281. 'routeClass' => 'TestPlugin.TestRoute',
  282. 'foo' => '^(bar)$',
  283. ),
  284. ));
  285. $routes = Router::routes();
  286. $route = $routes[0];
  287. $this->assertInstanceOf('TestPlugin\Routing\Route\TestRoute', $route);
  288. $this->assertEquals('^(bar)$', $route->options['foo']);
  289. }
  290. /**
  291. * Test mapResources with a plugin and prefix.
  292. *
  293. * @return void
  294. */
  295. public function testPluginMapResourcesWithPrefix() {
  296. Router::mapResources('TestPlugin.TestPlugin', array('prefix' => 'api'));
  297. $_SERVER['REQUEST_METHOD'] = 'GET';
  298. $result = Router::parse('/api/test_plugin/test_plugin');
  299. $expected = array(
  300. 'pass' => [],
  301. 'plugin' => 'TestPlugin',
  302. 'controller' => 'TestPlugin',
  303. 'prefix' => 'api',
  304. 'action' => 'index',
  305. '_method' => 'GET',
  306. '_ext' => null
  307. );
  308. $this->assertEquals($expected, $result);
  309. $resources = Router::mapResources('Posts', array('prefix' => 'api'));
  310. $_SERVER['REQUEST_METHOD'] = 'GET';
  311. $result = Router::parse('/api/posts');
  312. $expected = array(
  313. 'pass' => [],
  314. 'plugin' => null,
  315. 'controller' => 'Posts',
  316. 'action' => 'index',
  317. '_method' => 'GET',
  318. 'prefix' => 'api',
  319. '_ext' => null
  320. );
  321. $this->assertEquals($expected, $result);
  322. }
  323. /**
  324. * testMultipleResourceRoute method
  325. *
  326. * @return void
  327. */
  328. public function testMultipleResourceRoute() {
  329. Router::connect('/:controller', array('action' => 'index', '_method' => array('GET', 'POST')));
  330. $_SERVER['REQUEST_METHOD'] = 'GET';
  331. $result = Router::parse('/posts');
  332. $expected = array(
  333. 'pass' => [],
  334. 'plugin' => null,
  335. 'controller' => 'posts',
  336. 'action' => 'index',
  337. '_method' => array('GET', 'POST')
  338. );
  339. $this->assertEquals($expected, $result);
  340. $_SERVER['REQUEST_METHOD'] = 'POST';
  341. $result = Router::parse('/posts');
  342. $expected = array(
  343. 'pass' => [],
  344. 'plugin' => null,
  345. 'controller' => 'posts',
  346. 'action' => 'index',
  347. '_method' => array('GET', 'POST')
  348. );
  349. $this->assertEquals($expected, $result);
  350. }
  351. /**
  352. * testGenerateUrlResourceRoute method
  353. *
  354. * @return void
  355. */
  356. public function testGenerateUrlResourceRoute() {
  357. Router::mapResources('Posts');
  358. $result = Router::url([
  359. 'controller' => 'Posts',
  360. 'action' => 'index',
  361. '_method' => 'GET'
  362. ]);
  363. $expected = '/posts';
  364. $this->assertEquals($expected, $result);
  365. $result = Router::url([
  366. 'controller' => 'Posts',
  367. 'action' => 'view',
  368. '_method' => 'GET',
  369. 'id' => 10
  370. ]);
  371. $expected = '/posts/10';
  372. $this->assertEquals($expected, $result);
  373. $result = Router::url(['controller' => 'Posts', 'action' => 'add', '_method' => 'POST']);
  374. $expected = '/posts';
  375. $this->assertEquals($expected, $result);
  376. $result = Router::url(['controller' => 'Posts', 'action' => 'edit', '_method' => 'PUT', 'id' => 10]);
  377. $expected = '/posts/10';
  378. $this->assertEquals($expected, $result);
  379. $result = Router::url(['controller' => 'Posts', 'action' => 'delete', '_method' => 'DELETE', 'id' => 10]);
  380. $expected = '/posts/10';
  381. $this->assertEquals($expected, $result);
  382. $result = Router::url(['controller' => 'Posts', 'action' => 'edit', '_method' => 'PATCH', 'id' => 10]);
  383. $expected = '/posts/10';
  384. $this->assertEquals($expected, $result);
  385. }
  386. /**
  387. * testUrlNormalization method
  388. *
  389. * @return void
  390. */
  391. public function testUrlNormalization() {
  392. Router::connect('/:controller/:action');
  393. $expected = '/users/logout';
  394. $result = Router::normalize('/users/logout/');
  395. $this->assertEquals($expected, $result);
  396. $result = Router::normalize('//users//logout//');
  397. $this->assertEquals($expected, $result);
  398. $result = Router::normalize('users/logout');
  399. $this->assertEquals($expected, $result);
  400. $result = Router::normalize(array('controller' => 'users', 'action' => 'logout'));
  401. $this->assertEquals($expected, $result);
  402. $result = Router::normalize('/');
  403. $this->assertEquals('/', $result);
  404. $result = Router::normalize('http://google.com/');
  405. $this->assertEquals('http://google.com/', $result);
  406. $result = Router::normalize('http://google.com//');
  407. $this->assertEquals('http://google.com//', $result);
  408. $result = Router::normalize('/users/login/scope://foo');
  409. $this->assertEquals('/users/login/scope:/foo', $result);
  410. $result = Router::normalize('/recipe/recipes/add');
  411. $this->assertEquals('/recipe/recipes/add', $result);
  412. $request = new Request();
  413. $request->base = '/us';
  414. Router::setRequestInfo($request);
  415. $result = Router::normalize('/us/users/logout/');
  416. $this->assertEquals('/users/logout', $result);
  417. Router::reload();
  418. $request = new Request();
  419. $request->base = '/cake_12';
  420. Router::setRequestInfo($request);
  421. $result = Router::normalize('/cake_12/users/logout/');
  422. $this->assertEquals('/users/logout', $result);
  423. Router::reload();
  424. $_back = Configure::read('App.fullBaseUrl');
  425. Configure::write('App.fullBaseUrl', '/');
  426. $request = new Request();
  427. $request->base = '/';
  428. Router::setRequestInfo($request);
  429. $result = Router::normalize('users/login');
  430. $this->assertEquals('/users/login', $result);
  431. Configure::write('App.fullBaseUrl', $_back);
  432. Router::reload();
  433. $request = new Request();
  434. $request->base = 'beer';
  435. Router::setRequestInfo($request);
  436. $result = Router::normalize('beer/admin/beers_tags/add');
  437. $this->assertEquals('/admin/beers_tags/add', $result);
  438. $result = Router::normalize('/admin/beers_tags/add');
  439. $this->assertEquals('/admin/beers_tags/add', $result);
  440. }
  441. /**
  442. * Test generating urls with base paths.
  443. *
  444. * @return void
  445. */
  446. public function testUrlGenerationWithBasePath() {
  447. Router::connect('/:controller/:action/*');
  448. $request = new Request();
  449. $request->addParams([
  450. 'action' => 'index',
  451. 'plugin' => null,
  452. 'controller' => 'subscribe',
  453. ]);
  454. $request->base = '/magazine';
  455. $request->here = '/magazine/';
  456. $request->webroot = '/magazine/';
  457. Router::pushRequest($request);
  458. $result = Router::url();
  459. $this->assertEquals('/magazine/', $result);
  460. $result = Router::url('/');
  461. $this->assertEquals('/magazine/', $result);
  462. $result = Router::url('/articles/');
  463. $this->assertEquals('/magazine/articles/', $result);
  464. $result = Router::url('/articles/view');
  465. $this->assertEquals('/magazine/articles/view', $result);
  466. $result = Router::url(['controller' => 'articles', 'action' => 'view', 1]);
  467. $this->assertEquals('/magazine/articles/view/1', $result);
  468. }
  469. /**
  470. * Test that catch all routes work with a variety of falsey inputs.
  471. *
  472. * @return void
  473. */
  474. public function testUrlCatchAllRoute() {
  475. Router::connect('/*', array('controller' => 'categories', 'action' => 'index'));
  476. $result = Router::url(array('controller' => 'categories', 'action' => 'index', '0'));
  477. $this->assertEquals('/0', $result);
  478. $expected = [
  479. 'plugin' => null,
  480. 'controller' => 'categories',
  481. 'action' => 'index',
  482. 'pass' => ['0'],
  483. ];
  484. $result = Router::parse('/0');
  485. $this->assertEquals($expected, $result);
  486. $result = Router::parse('0');
  487. $this->assertEquals($expected, $result);
  488. }
  489. /**
  490. * test generation of basic urls.
  491. *
  492. * @return void
  493. */
  494. public function testUrlGenerationBasic() {
  495. extract(Router::getNamedExpressions());
  496. Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
  497. $out = Router::url(array('controller' => 'pages', 'action' => 'display', 'home'));
  498. $this->assertEquals('/', $out);
  499. Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  500. $result = Router::url(array('controller' => 'pages', 'action' => 'display', 'about'));
  501. $expected = '/pages/about';
  502. $this->assertEquals($expected, $result);
  503. Router::reload();
  504. Router::connect('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'), array('id' => $ID));
  505. $result = Router::url(array(
  506. 'plugin' => 'cake_plugin',
  507. 'controller' => 'posts',
  508. 'action' => 'view',
  509. 'id' => '1'
  510. ));
  511. $expected = '/cake_plugin/1';
  512. $this->assertEquals($expected, $result);
  513. $result = Router::url(array(
  514. 'plugin' => 'cake_plugin',
  515. 'controller' => 'posts',
  516. 'action' => 'view',
  517. 'id' => '1',
  518. '0'
  519. ));
  520. $expected = '/cake_plugin/1/0';
  521. $this->assertEquals($expected, $result);
  522. Router::reload();
  523. Router::connect('/:controller/:action/:id', [], array('id' => $ID));
  524. $result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
  525. $expected = '/posts/view/1';
  526. $this->assertEquals($expected, $result);
  527. Router::reload();
  528. Router::connect('/:controller/:id', array('action' => 'view'));
  529. $result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
  530. $expected = '/posts/1';
  531. $this->assertEquals($expected, $result);
  532. Router::connect('/view/*', array('controller' => 'posts', 'action' => 'view'));
  533. $result = Router::url(array('controller' => 'posts', 'action' => 'view', '1'));
  534. $expected = '/view/1';
  535. $this->assertEquals($expected, $result);
  536. Router::reload();
  537. Router::connect('/:controller/:action');
  538. $request = new Request();
  539. $request->addParams(array(
  540. 'action' => 'index',
  541. 'plugin' => null,
  542. 'controller' => 'users',
  543. ));
  544. $request->base = '/';
  545. $request->here = '/';
  546. $request->webroot = '/';
  547. Router::setRequestInfo($request);
  548. $result = Router::url(array('action' => 'login'));
  549. $expected = '/users/login';
  550. $this->assertEquals($expected, $result);
  551. Router::reload();
  552. Router::connect('/contact/:action', array('plugin' => 'contact', 'controller' => 'contact'));
  553. $result = Router::url(array(
  554. 'plugin' => 'contact',
  555. 'controller' => 'contact',
  556. 'action' => 'me'
  557. ));
  558. $expected = '/contact/me';
  559. $this->assertEquals($expected, $result);
  560. Router::reload();
  561. Router::connect('/:controller', array('action' => 'index'));
  562. $request = new Request();
  563. $request->addParams(array(
  564. 'action' => 'index',
  565. 'plugin' => 'myplugin',
  566. 'controller' => 'mycontroller',
  567. ));
  568. $request->base = '/';
  569. $request->here = '/';
  570. $request->webroot = '/';
  571. Router::setRequestInfo($request);
  572. $result = Router::url(array('plugin' => null, 'controller' => 'myothercontroller'));
  573. $expected = '/myothercontroller';
  574. $this->assertEquals($expected, $result);
  575. }
  576. /**
  577. * Test that generated names for routes are case-insensitive.
  578. *
  579. * @return void
  580. */
  581. public function testRouteNameCasing() {
  582. Router::connect('/articles/:id', ['controller' => 'Articles', 'action' => 'view']);
  583. Router::connect('/:controller/:action/*', [], ['routeClass' => 'InflectedRoute']);
  584. $result = Router::url(['controller' => 'Articles', 'action' => 'view', 'id' => 10]);
  585. $expected = '/articles/10';
  586. $this->assertEquals($expected, $result);
  587. }
  588. /**
  589. * Test generation of routes with query string parameters.
  590. *
  591. * @return void
  592. */
  593. public function testUrlGenerationWithQueryStrings() {
  594. Router::connect('/:controller/:action/*');
  595. $result = Router::url(array(
  596. 'controller' => 'posts',
  597. '0',
  598. '?' => array('var' => 'test', 'var2' => 'test2')
  599. ));
  600. $expected = '/posts/index/0?var=test&var2=test2';
  601. $this->assertEquals($expected, $result);
  602. $result = Router::url(array('controller' => 'posts', '0', '?' => array('var' => null)));
  603. $this->assertEquals('/posts/index/0', $result);
  604. $result = Router::url(array(
  605. 'controller' => 'posts',
  606. '0',
  607. '?' => array(
  608. 'var' => 'test',
  609. 'var2' => 'test2'
  610. ),
  611. '#' => 'unencoded string %'
  612. ));
  613. $expected = '/posts/index/0?var=test&var2=test2#unencoded string %';
  614. $this->assertEquals($expected, $result);
  615. }
  616. /**
  617. * test that regex validation of keyed route params is working.
  618. *
  619. * @return void
  620. */
  621. public function testUrlGenerationWithRegexQualifiedParams() {
  622. Router::connect(
  623. ':language/galleries',
  624. array('controller' => 'galleries', 'action' => 'index'),
  625. array('language' => '[a-z]{3}')
  626. );
  627. Router::connect(
  628. '/:language/:admin/:controller/:action/*',
  629. array('admin' => 'admin'),
  630. array('language' => '[a-z]{3}', 'admin' => 'admin')
  631. );
  632. Router::connect('/:language/:controller/:action/*',
  633. [],
  634. array('language' => '[a-z]{3}')
  635. );
  636. $result = Router::url(array('admin' => false, 'language' => 'dan', 'action' => 'index', 'controller' => 'galleries'));
  637. $expected = '/dan/galleries';
  638. $this->assertEquals($expected, $result);
  639. $result = Router::url(array('admin' => false, 'language' => 'eng', 'action' => 'index', 'controller' => 'galleries'));
  640. $expected = '/eng/galleries';
  641. $this->assertEquals($expected, $result);
  642. Router::reload();
  643. Router::connect('/:language/pages',
  644. array('controller' => 'pages', 'action' => 'index'),
  645. array('language' => '[a-z]{3}')
  646. );
  647. Router::connect('/:language/:controller/:action/*', [], array('language' => '[a-z]{3}'));
  648. $result = Router::url(array('language' => 'eng', 'action' => 'index', 'controller' => 'pages'));
  649. $expected = '/eng/pages';
  650. $this->assertEquals($expected, $result);
  651. $result = Router::url(array('language' => 'eng', 'controller' => 'pages'));
  652. $this->assertEquals($expected, $result);
  653. $result = Router::url(array('language' => 'eng', 'controller' => 'pages', 'action' => 'add'));
  654. $expected = '/eng/pages/add';
  655. $this->assertEquals($expected, $result);
  656. Router::reload();
  657. Router::connect('/forestillinger/:month/:year/*',
  658. array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'),
  659. array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}')
  660. );
  661. $result = Router::url(array(
  662. 'plugin' => 'shows',
  663. 'controller' => 'shows',
  664. 'action' => 'calendar',
  665. 'month' => 10,
  666. 'year' => 2007,
  667. 'min-forestilling'
  668. ));
  669. $expected = '/forestillinger/10/2007/min-forestilling';
  670. $this->assertEquals($expected, $result);
  671. Router::reload();
  672. Router::connect('/kalender/:month/:year/*',
  673. array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'),
  674. array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}')
  675. );
  676. Router::connect('/kalender/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'));
  677. $result = Router::url(array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'min-forestilling'));
  678. $expected = '/kalender/min-forestilling';
  679. $this->assertEquals($expected, $result);
  680. $result = Router::url(array(
  681. 'plugin' => 'shows',
  682. 'controller' => 'shows',
  683. 'action' => 'calendar',
  684. 'year' => 2007,
  685. 'month' => 10,
  686. 'min-forestilling'
  687. ));
  688. $expected = '/kalender/10/2007/min-forestilling';
  689. $this->assertEquals($expected, $result);
  690. }
  691. /**
  692. * Test URL generation with an admin prefix
  693. *
  694. * @return void
  695. */
  696. public function testUrlGenerationWithPrefix() {
  697. Configure::write('Routing.prefixes', array('admin'));
  698. Router::reload();
  699. Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  700. Router::connect('/reset/*', array('admin' => true, 'controller' => 'users', 'action' => 'reset'));
  701. Router::connect('/tests', array('controller' => 'tests', 'action' => 'index'));
  702. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  703. Router::extensions('rss', false);
  704. $request = new Request();
  705. $request->addParams(array(
  706. 'controller' => 'registrations',
  707. 'action' => 'admin_index',
  708. 'plugin' => null,
  709. 'prefix' => 'admin',
  710. '_ext' => 'html'
  711. ));
  712. $request->base = '';
  713. $request->here = '/admin/registrations/index';
  714. $request->webroot = '/';
  715. Router::setRequestInfo($request);
  716. $result = Router::url([]);
  717. $expected = '/admin/registrations/index';
  718. $this->assertEquals($expected, $result);
  719. Router::reload();
  720. Router::connect('/admin/subscriptions/:action/*', array('controller' => 'subscribe', 'prefix' => 'admin'));
  721. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  722. $request = new Request();
  723. $request->addParams(array(
  724. 'action' => 'index',
  725. 'plugin' => null,
  726. 'controller' => 'subscribe',
  727. 'prefix' => 'admin',
  728. ));
  729. $request->base = '/magazine';
  730. $request->here = '/magazine/admin/subscriptions/edit/1';
  731. $request->webroot = '/magazine/';
  732. Router::setRequestInfo($request);
  733. $result = Router::url(array('action' => 'edit', 1));
  734. $expected = '/magazine/admin/subscriptions/edit/1';
  735. $this->assertEquals($expected, $result);
  736. $result = Router::url(array('prefix' => 'admin', 'controller' => 'users', 'action' => 'login'));
  737. $expected = '/magazine/admin/users/login';
  738. $this->assertEquals($expected, $result);
  739. Router::reload();
  740. $request = new Request();
  741. $request->addParams(array(
  742. 'prefix' => 'admin',
  743. 'action' => 'index',
  744. 'plugin' => null,
  745. 'controller' => 'users',
  746. ));
  747. $request->base = '/';
  748. $request->here = '/';
  749. $request->webroot = '/';
  750. Router::setRequestInfo($request);
  751. Router::connect('/page/*', array('controller' => 'pages', 'action' => 'view', 'prefix' => 'admin'));
  752. $result = Router::url(array('prefix' => 'admin', 'controller' => 'pages', 'action' => 'view', 'my-page'));
  753. $expected = '/page/my-page';
  754. $this->assertEquals($expected, $result);
  755. Router::reload();
  756. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  757. $request = new Request();
  758. $request->addParams(array(
  759. 'plugin' => null,
  760. 'controller' => 'pages',
  761. 'action' => 'add',
  762. 'prefix' => 'admin'
  763. ));
  764. $request->base = '';
  765. $request->here = '/admin/pages/add';
  766. $request->webroot = '/';
  767. Router::setRequestInfo($request);
  768. $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false));
  769. $expected = '/admin/pages/add';
  770. $this->assertEquals($expected, $result);
  771. Router::reload();
  772. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  773. $request = new Request();
  774. $request->addParams(array(
  775. 'plugin' => null,
  776. 'controller' => 'pages',
  777. 'action' => 'add',
  778. 'prefix' => 'admin'
  779. ));
  780. $request->base = '';
  781. $request->here = '/admin/pages/add';
  782. $request->webroot = '/';
  783. Router::setRequestInfo($request);
  784. $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false));
  785. $expected = '/admin/pages/add';
  786. $this->assertEquals($expected, $result);
  787. Router::reload();
  788. Router::connect('/admin/:controller/:action/:id', array('prefix' => 'admin'), array('id' => '[0-9]+'));
  789. $request = new Request();
  790. Router::setRequestInfo(
  791. $request->addParams(array(
  792. 'plugin' => null,
  793. 'controller' => 'pages',
  794. 'action' => 'edit',
  795. 'pass' => array('284'),
  796. 'prefix' => 'admin'
  797. ))->addPaths(array(
  798. 'base' => '',
  799. 'here' => '/admin/pages/edit/284',
  800. 'webroot' => '/'
  801. ))
  802. );
  803. $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'edit', 'id' => '284'));
  804. $expected = '/admin/pages/edit/284';
  805. $this->assertEquals($expected, $result);
  806. Router::reload();
  807. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  808. $request = new Request();
  809. Router::setRequestInfo(
  810. $request->addParams(array(
  811. 'plugin' => null, 'controller' => 'pages', 'action' => 'add', 'prefix' => 'admin',
  812. ))->addPaths(array(
  813. 'base' => '', 'here' => '/admin/pages/add', 'webroot' => '/'
  814. ))
  815. );
  816. $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false));
  817. $expected = '/admin/pages/add';
  818. $this->assertEquals($expected, $result);
  819. Router::reload();
  820. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  821. $request = new Request();
  822. Router::setRequestInfo(
  823. $request->addParams(array(
  824. 'plugin' => null, 'controller' => 'pages', 'action' => 'edit', 'prefix' => 'admin',
  825. 'pass' => array('284')
  826. ))->addPaths(array(
  827. 'base' => '', 'here' => '/admin/pages/edit/284', 'webroot' => '/'
  828. ))
  829. );
  830. $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'edit', 284));
  831. $expected = '/admin/pages/edit/284';
  832. $this->assertEquals($expected, $result);
  833. Router::reload();
  834. Router::connect('/admin/posts/*', array('controller' => 'posts', 'action' => 'index', 'prefix' => 'admin'));
  835. Router::setRequestInfo(
  836. $request->addParams(array(
  837. 'plugin' => null, 'controller' => 'posts', 'action' => 'index', 'prefix' => 'admin',
  838. 'pass' => array('284')
  839. ))->addPaths(array(
  840. 'base' => '', 'here' => '/admin/posts', 'webroot' => '/'
  841. ))
  842. );
  843. $result = Router::url(array('all'));
  844. $expected = '/admin/posts/all';
  845. $this->assertEquals($expected, $result);
  846. }
  847. /**
  848. * Test URL generation inside a prefixed plugin.
  849. *
  850. * @return void
  851. */
  852. public function testUrlGenerationPrefixedPlugin() {
  853. Router::prefix('admin', function ($routes) {
  854. $routes->plugin('MyPlugin', function ($routes) {
  855. $routes->fallbacks();
  856. });
  857. });
  858. $result = Router::url(['prefix' => 'admin', 'plugin' => 'MyPlugin', 'controller' => 'Forms', 'action' => 'edit', 2]);
  859. $expected = '/admin/my_plugin/forms/edit/2';
  860. $this->assertEquals($expected, $result);
  861. }
  862. /**
  863. * testUrlGenerationWithExtensions method
  864. *
  865. * @return void
  866. */
  867. public function testUrlGenerationWithExtensions() {
  868. Router::connect('/:controller', array('action' => 'index'));
  869. Router::connect('/:controller/:action');
  870. $result = Router::url(array(
  871. 'plugin' => null,
  872. 'controller' => 'articles',
  873. 'action' => 'add',
  874. 'id' => null,
  875. '_ext' => 'json'
  876. ));
  877. $expected = '/articles/add.json';
  878. $this->assertEquals($expected, $result);
  879. $result = Router::url(array(
  880. 'plugin' => null,
  881. 'controller' => 'articles',
  882. 'action' => 'add',
  883. '_ext' => 'json'
  884. ));
  885. $expected = '/articles/add.json';
  886. $this->assertEquals($expected, $result);
  887. $result = Router::url(array(
  888. 'plugin' => null,
  889. 'controller' => 'articles',
  890. 'action' => 'index',
  891. 'id' => null,
  892. '_ext' => 'json'
  893. ));
  894. $expected = '/articles.json';
  895. $this->assertEquals($expected, $result);
  896. }
  897. /**
  898. * test url() when the current request has an extension.
  899. *
  900. * @return void
  901. */
  902. public function testUrlGenerationWithExtensionInCurrentRequest() {
  903. Router::extensions('rss');
  904. Router::scope('/', function ($r) {
  905. $r->fallbacks();
  906. });
  907. $request = new Request();
  908. $request->addParams(['controller' => 'Tasks', 'action' => 'index', '_ext' => 'rss']);
  909. Router::pushRequest($request);
  910. $result = Router::url(array(
  911. 'controller' => 'Tasks',
  912. 'action' => 'view',
  913. 1
  914. ));
  915. $expected = '/tasks/view/1';
  916. $this->assertEquals($expected, $result);
  917. $result = Router::url(array(
  918. 'controller' => 'Tasks',
  919. 'action' => 'view',
  920. 1,
  921. '_ext' => 'json'
  922. ));
  923. $expected = '/tasks/view/1.json';
  924. $this->assertEquals($expected, $result);
  925. }
  926. /**
  927. * Test url generation with named routes.
  928. */
  929. public function testUrlGenerationNamedRoute() {
  930. Router::connect(
  931. '/users',
  932. array('controller' => 'users', 'action' => 'index'),
  933. array('_name' => 'users-index')
  934. );
  935. Router::connect(
  936. '/users/:name',
  937. array('controller' => 'users', 'action' => 'view'),
  938. array('_name' => 'test')
  939. );
  940. Router::connect(
  941. '/view/*',
  942. ['action' => 'view'],
  943. ['_name' => 'Articles::view']
  944. );
  945. $url = Router::url(['_name' => 'test', 'name' => 'mark']);
  946. $this->assertEquals('/users/mark', $url);
  947. $url = Router::url([
  948. '_name' => 'test', 'name' => 'mark',
  949. 'page' => 1, 'sort' => 'title', 'dir' => 'desc'
  950. ]);
  951. $this->assertEquals('/users/mark?page=1&sort=title&dir=desc', $url);
  952. $url = Router::url(['_name' => 'Articles::view']);
  953. $this->assertEquals('/view/', $url);
  954. $url = Router::url(['_name' => 'Articles::view', '1']);
  955. $this->assertEquals('/view/1', $url);
  956. $url = Router::url(['_name' => 'Articles::view', '_full' => true, '1']);
  957. $this->assertEquals('http://localhost/view/1', $url);
  958. $url = Router::url(['_name' => 'Articles::view', '1', '#' => 'frag']);
  959. $this->assertEquals('/view/1#frag', $url);
  960. }
  961. /**
  962. * Test that using invalid names causes exceptions.
  963. *
  964. * @expectedException \Cake\Routing\Exception\MissingRouteException
  965. * @return void
  966. */
  967. public function testNamedRouteException() {
  968. Router::connect(
  969. '/users/:name',
  970. array('controller' => 'users', 'action' => 'view'),
  971. array('_name' => 'test')
  972. );
  973. $url = Router::url(['_name' => 'junk', 'name' => 'mark']);
  974. }
  975. /**
  976. * Test that url filters are applied to url params.
  977. *
  978. * @return void
  979. */
  980. public function testUrlGenerationWithUrlFilter() {
  981. Router::connect('/:lang/:controller/:action/*');
  982. $request = new Request();
  983. $request->addParams(array(
  984. 'lang' => 'en',
  985. 'controller' => 'posts',
  986. 'action' => 'index'
  987. ))->addPaths(array(
  988. 'base' => '',
  989. 'here' => '/'
  990. ));
  991. Router::pushRequest($request);
  992. $calledCount = 0;
  993. Router::addUrlFilter(function ($url, $request) use (&$calledCount) {
  994. $calledCount++;
  995. $url['lang'] = $request->lang;
  996. return $url;
  997. });
  998. Router::addUrlFilter(function ($url, $request) use (&$calledCount) {
  999. $calledCount++;
  1000. $url[] = '1234';
  1001. return $url;
  1002. });
  1003. $result = Router::url(array('controller' => 'tasks', 'action' => 'edit'));
  1004. $this->assertEquals('/en/tasks/edit/1234', $result);
  1005. $this->assertEquals(2, $calledCount);
  1006. }
  1007. /**
  1008. * Test that plain strings urls work
  1009. *
  1010. * @return void
  1011. */
  1012. public function testUrlGenerationPlainString() {
  1013. $mailto = 'mailto:mark@example.com';
  1014. $result = Router::url($mailto);
  1015. $this->assertEquals($mailto, $result);
  1016. $js = 'javascript:alert("hi")';
  1017. $result = Router::url($js);
  1018. $this->assertEquals($js, $result);
  1019. $hash = '#first';
  1020. $result = Router::url($hash);
  1021. $this->assertEquals($hash, $result);
  1022. }
  1023. /**
  1024. * test that you can leave active plugin routes with plugin = null
  1025. *
  1026. * @return void
  1027. */
  1028. public function testCanLeavePlugin() {
  1029. Router::connect('/admin/:controller', array('action' => 'index', 'prefix' => 'admin'));
  1030. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  1031. $request = new Request();
  1032. Router::setRequestInfo(
  1033. $request->addParams(array(
  1034. 'pass' => [],
  1035. 'prefix' => 'admin',
  1036. 'plugin' => 'this',
  1037. 'action' => 'index',
  1038. 'controller' => 'interesting',
  1039. ))->addPaths(array(
  1040. 'base' => '',
  1041. 'here' => '/admin/this/interesting/index',
  1042. 'webroot' => '/',
  1043. ))
  1044. );
  1045. $result = Router::url(array('plugin' => null, 'controller' => 'posts', 'action' => 'index'));
  1046. $this->assertEquals('/admin/posts', $result);
  1047. }
  1048. /**
  1049. * testUrlParsing method
  1050. *
  1051. * @return void
  1052. */
  1053. public function testUrlParsing() {
  1054. extract(Router::getNamedExpressions());
  1055. Router::connect(
  1056. '/posts/:value/:somevalue/:othervalue/*',
  1057. array('controller' => 'Posts', 'action' => 'view'),
  1058. array('value', 'somevalue', 'othervalue')
  1059. );
  1060. $result = Router::parse('/posts/2007/08/01/title-of-post-here');
  1061. $expected = array(
  1062. 'value' => '2007',
  1063. 'somevalue' => '08',
  1064. 'othervalue' => '01',
  1065. 'controller' => 'Posts',
  1066. 'action' => 'view',
  1067. 'plugin' => null,
  1068. 'pass' => array('0' => 'title-of-post-here')
  1069. );
  1070. $this->assertEquals($expected, $result);
  1071. Router::reload();
  1072. Router::connect(
  1073. '/posts/:year/:month/:day/*',
  1074. array('controller' => 'posts', 'action' => 'view'),
  1075. array('year' => $Year, 'month' => $Month, 'day' => $Day)
  1076. );
  1077. $result = Router::parse('/posts/2007/08/01/title-of-post-here');
  1078. $expected = array(
  1079. 'year' => '2007',
  1080. 'month' => '08',
  1081. 'day' => '01',
  1082. 'controller' => 'posts',
  1083. 'action' => 'view',
  1084. 'plugin' => null,
  1085. 'pass' => array('0' => 'title-of-post-here')
  1086. );
  1087. $this->assertEquals($expected, $result);
  1088. Router::reload();
  1089. Router::connect(
  1090. '/posts/:day/:year/:month/*',
  1091. array('controller' => 'posts', 'action' => 'view'),
  1092. array('year' => $Year, 'month' => $Month, 'day' => $Day)
  1093. );
  1094. $result = Router::parse('/posts/01/2007/08/title-of-post-here');
  1095. $expected = array(
  1096. 'day' => '01',
  1097. 'year' => '2007',
  1098. 'month' => '08',
  1099. 'controller' => 'posts',
  1100. 'action' => 'view',
  1101. 'plugin' => null,
  1102. 'pass' => array('0' => 'title-of-post-here')
  1103. );
  1104. $this->assertEquals($expected, $result);
  1105. Router::reload();
  1106. Router::connect(
  1107. '/posts/:month/:day/:year/*',
  1108. array('controller' => 'posts', 'action' => 'view'),
  1109. array('year' => $Year, 'month' => $Month, 'day' => $Day)
  1110. );
  1111. $result = Router::parse('/posts/08/01/2007/title-of-post-here');
  1112. $expected = array(
  1113. 'month' => '08',
  1114. 'day' => '01',
  1115. 'year' => '2007',
  1116. 'controller' => 'posts',
  1117. 'action' => 'view',
  1118. 'plugin' => null,
  1119. 'pass' => array('0' => 'title-of-post-here')
  1120. );
  1121. $this->assertEquals($expected, $result);
  1122. Router::reload();
  1123. Router::connect(
  1124. '/posts/:year/:month/:day/*',
  1125. array('controller' => 'posts', 'action' => 'view')
  1126. );
  1127. $result = Router::parse('/posts/2007/08/01/title-of-post-here');
  1128. $expected = array(
  1129. 'year' => '2007',
  1130. 'month' => '08',
  1131. 'day' => '01',
  1132. 'controller' => 'posts',
  1133. 'action' => 'view',
  1134. 'plugin' => null,
  1135. 'pass' => array('0' => 'title-of-post-here')
  1136. );
  1137. $this->assertEquals($expected, $result);
  1138. Router::reload();
  1139. $this->_connectDefaultRoutes();
  1140. $result = Router::parse('/pages/display/home');
  1141. $expected = array(
  1142. 'plugin' => null,
  1143. 'pass' => array('home'),
  1144. 'controller' => 'Pages',
  1145. 'action' => 'display'
  1146. );
  1147. $this->assertEquals($expected, $result);
  1148. $result = Router::parse('pages/display/home/');
  1149. $this->assertEquals($expected, $result);
  1150. $result = Router::parse('pages/display/home');
  1151. $this->assertEquals($expected, $result);
  1152. Router::reload();
  1153. Router::connect('/page/*', array('controller' => 'test'));
  1154. $result = Router::parse('/page/my-page');
  1155. $expected = array('pass' => array('my-page'), 'plugin' => null, 'controller' => 'test', 'action' => 'index');
  1156. $this->assertEquals($expected, $result);
  1157. Router::reload();
  1158. Router::connect(
  1159. '/:language/contact',
  1160. array('language' => 'eng', 'plugin' => 'contact', 'controller' => 'contact', 'action' => 'index'),
  1161. array('language' => '[a-z]{3}')
  1162. );
  1163. $result = Router::parse('/eng/contact');
  1164. $expected = array(
  1165. 'pass' => [],
  1166. 'language' => 'eng',
  1167. 'plugin' => 'contact',
  1168. 'controller' => 'contact',
  1169. 'action' => 'index'
  1170. );
  1171. $this->assertEquals($expected, $result);
  1172. Router::reload();
  1173. Router::connect('/forestillinger/:month/:year/*',
  1174. array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'),
  1175. array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}')
  1176. );
  1177. $result = Router::parse('/forestillinger/10/2007/min-forestilling');
  1178. $expected = array(
  1179. 'pass' => array('min-forestilling'),
  1180. 'plugin' => 'shows',
  1181. 'controller' => 'shows',
  1182. 'action' => 'calendar',
  1183. 'year' => 2007,
  1184. 'month' => 10
  1185. );
  1186. $this->assertEquals($expected, $result);
  1187. Router::reload();
  1188. Router::connect('/:controller/:action/*');
  1189. Router::connect('/', array('plugin' => 'pages', 'controller' => 'pages', 'action' => 'display'));
  1190. $result = Router::parse('/');
  1191. $expected = array('pass' => [], 'controller' => 'pages', 'action' => 'display', 'plugin' => 'pages');
  1192. $this->assertEquals($expected, $result);
  1193. $result = Router::parse('/posts/edit/0');
  1194. $expected = array('pass' => array(0), 'controller' => 'posts', 'action' => 'edit', 'plugin' => null);
  1195. $this->assertEquals($expected, $result);
  1196. Router::reload();
  1197. Router::connect(
  1198. '/posts/:id::url_title',
  1199. array('controller' => 'posts', 'action' => 'view'),
  1200. array('pass' => array('id', 'url_title'), 'id' => '[\d]+')
  1201. );
  1202. $result = Router::parse('/posts/5:sample-post-title');
  1203. $expected = array(
  1204. 'pass' => array('5', 'sample-post-title'),
  1205. 'id' => 5,
  1206. 'url_title' => 'sample-post-title',
  1207. 'plugin' => null,
  1208. 'controller' => 'posts',
  1209. 'action' => 'view'
  1210. );
  1211. $this->assertEquals($expected, $result);
  1212. Router::reload();
  1213. Router::connect(
  1214. '/posts/:id::url_title/*',
  1215. array('controller' => 'posts', 'action' => 'view'),
  1216. array('pass' => array('id', 'url_title'), 'id' => '[\d]+')
  1217. );
  1218. $result = Router::parse('/posts/5:sample-post-title/other/params/4');
  1219. $expected = array(
  1220. 'pass' => array('5', 'sample-post-title', 'other', 'params', '4'),
  1221. 'id' => 5,
  1222. 'url_title' => 'sample-post-title',
  1223. 'plugin' => null,
  1224. 'controller' => 'posts',
  1225. 'action' => 'view'
  1226. );
  1227. $this->assertEquals($expected, $result);
  1228. Router::reload();
  1229. Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'));
  1230. $result = Router::parse('/posts/view/10?id=123&tab=abc');
  1231. $expected = array('pass' => array(10), 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '?' => array('id' => '123', 'tab' => 'abc'));
  1232. $this->assertEquals($expected, $result);
  1233. Router::reload();
  1234. Router::connect(
  1235. '/posts/:url_title-(uuid::id)',
  1236. array('controller' => 'posts', 'action' => 'view'),
  1237. array('pass' => array('id', 'url_title'), 'id' => $UUID)
  1238. );
  1239. $result = Router::parse('/posts/sample-post-title-(uuid:47fc97a9-019c-41d1-a058-1fa3cbdd56cb)');
  1240. $expected = array(
  1241. 'pass' => array('47fc97a9-019c-41d1-a058-1fa3cbdd56cb', 'sample-post-title'),
  1242. 'id' => '47fc97a9-019c-41d1-a058-1fa3cbdd56cb',
  1243. 'url_title' => 'sample-post-title',
  1244. 'plugin' => null,
  1245. 'controller' => 'posts',
  1246. 'action' => 'view'
  1247. );
  1248. $this->assertEquals($expected, $result);
  1249. Router::reload();
  1250. Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'));
  1251. $result = Router::parse('/posts/view/foo:bar/routing:fun');
  1252. $expected = array(
  1253. 'pass' => array('foo:bar', 'routing:fun'),
  1254. 'plugin' => null,
  1255. 'controller' => 'posts',
  1256. 'action' => 'view'
  1257. );
  1258. $this->assertEquals($expected, $result);
  1259. }
  1260. /**
  1261. * testUuidRoutes method
  1262. *
  1263. * @return void
  1264. */
  1265. public function testUuidRoutes() {
  1266. Router::connect(
  1267. '/subjects/add/:category_id',
  1268. array('controller' => 'subjects', 'action' => 'add'),
  1269. array('category_id' => '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}')
  1270. );
  1271. $result = Router::parse('/subjects/add/4795d601-19c8-49a6-930e-06a8b01d17b7');
  1272. $expected = array(
  1273. 'pass' => [],
  1274. 'category_id' => '4795d601-19c8-49a6-930e-06a8b01d17b7',
  1275. 'plugin' => null,
  1276. 'controller' => 'subjects',
  1277. 'action' => 'add'
  1278. );
  1279. $this->assertEquals($expected, $result);
  1280. }
  1281. /**
  1282. * testRouteSymmetry method
  1283. *
  1284. * @return void
  1285. */
  1286. public function testRouteSymmetry() {
  1287. Router::connect(
  1288. "/:extra/page/:slug/*",
  1289. array('controller' => 'pages', 'action' => 'view', 'extra' => null),
  1290. array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+', "action" => 'view')
  1291. );
  1292. $result = Router::parse('/some_extra/page/this_is_the_slug');
  1293. $expected = array(
  1294. 'pass' => [],
  1295. 'plugin' => null,
  1296. 'controller' => 'pages',
  1297. 'action' => 'view',
  1298. 'slug' => 'this_is_the_slug',
  1299. 'extra' => 'some_extra'
  1300. );
  1301. $this->assertEquals($expected, $result);
  1302. $result = Router::parse('/page/this_is_the_slug');
  1303. $expected = array(
  1304. 'pass' => [],
  1305. 'plugin' => null,
  1306. 'controller' => 'pages',
  1307. 'action' => 'view',
  1308. 'slug' => 'this_is_the_slug',
  1309. 'extra' => null
  1310. );
  1311. $this->assertEquals($expected, $result);
  1312. Router::reload();
  1313. Router::connect(
  1314. "/:extra/page/:slug/*",
  1315. array('controller' => 'pages', 'action' => 'view', 'extra' => null),
  1316. array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+')
  1317. );
  1318. $result = Router::url(array(
  1319. 'admin' => null,
  1320. 'plugin' => null,
  1321. 'controller' => 'pages',
  1322. 'action' => 'view',
  1323. 'slug' => 'this_is_the_slug',
  1324. 'extra' => null
  1325. ));
  1326. $expected = '/page/this_is_the_slug';
  1327. $this->assertEquals($expected, $result);
  1328. $result = Router::url(array(
  1329. 'admin' => null,
  1330. 'plugin' => null,
  1331. 'controller' => 'pages',
  1332. 'action' => 'view',
  1333. 'slug' => 'this_is_the_slug',
  1334. 'extra' => 'some_extra'
  1335. ));
  1336. $expected = '/some_extra/page/this_is_the_slug';
  1337. $this->assertEquals($expected, $result);
  1338. }
  1339. /**
  1340. * Test exceptions when parsing fails.
  1341. *
  1342. * @expectedException \Cake\Routing\Exception\MissingRouteException
  1343. */
  1344. public function testParseError() {
  1345. Router::connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
  1346. Router::parse('/nope');
  1347. }
  1348. /**
  1349. * Test parse and reverse symmetry
  1350. *
  1351. * @return void
  1352. * @dataProvider parseReverseSymmetryData
  1353. */
  1354. public function testParseReverseSymmetry($url) {
  1355. $this->_connectDefaultRoutes();
  1356. $this->assertSame($url, Router::reverse(Router::parse($url) + array('url' => [])));
  1357. }
  1358. /**
  1359. * Data for parse and reverse test
  1360. *
  1361. * @return array
  1362. */
  1363. public function parseReverseSymmetryData() {
  1364. return array(
  1365. array('/controller/action'),
  1366. array('/controller/action/param'),
  1367. array('/controller/action?param1=value1&param2=value2'),
  1368. array('/controller/action/param?param1=value1'),
  1369. );
  1370. }
  1371. /**
  1372. * testSetExtensions method
  1373. *
  1374. * @return void
  1375. */
  1376. public function testSetExtensions() {
  1377. Router::extensions('rss', false);
  1378. $this->assertContains('rss', Router::extensions());
  1379. $this->_connectDefaultRoutes();
  1380. $result = Router::parse('/posts.rss');
  1381. $this->assertEquals('rss', $result['_ext']);
  1382. $result = Router::parse('/posts.xml');
  1383. $this->assertFalse(isset($result['_ext']));
  1384. Router::extensions(array('xml'));
  1385. }
  1386. /**
  1387. * Test that route builders propagate extensions to the top.
  1388. *
  1389. * @return void
  1390. */
  1391. public function testExtensionsWithScopedRoutes() {
  1392. Router::extensions(['json']);
  1393. Router::scope('/', function ($routes) {
  1394. $routes->extensions('rss');
  1395. $routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
  1396. $routes->scope('/api', function ($routes) {
  1397. $routes->extensions('xml');
  1398. $routes->connect('/docs', ['controller' => 'ApiDocs', 'action' => 'index']);
  1399. });
  1400. });
  1401. $this->assertEquals(['json', 'rss', 'xml'], array_values(Router::extensions()));
  1402. }
  1403. /**
  1404. * testExtensionParsing method
  1405. *
  1406. * @return void
  1407. */
  1408. public function testExtensionParsing() {
  1409. Router::extensions('rss', false);
  1410. $this->_connectDefaultRoutes();
  1411. $result = Router::parse('/posts.rss');
  1412. $expected = array(
  1413. 'plugin' => null,
  1414. 'controller' => 'Posts',
  1415. 'action' => 'index',
  1416. '_ext' => 'rss',
  1417. 'pass' => []
  1418. );
  1419. $this->assertEquals($expected, $result);
  1420. $result = Router::parse('/posts/view/1.rss');
  1421. $expected = array(
  1422. 'plugin' => null,
  1423. 'controller' => 'Posts',
  1424. 'action' => 'view',
  1425. 'pass' => array('1'),
  1426. '_ext' => 'rss'
  1427. );
  1428. $this->assertEquals($expected, $result);
  1429. $result = Router::parse('/posts/view/1.rss?query=test');
  1430. $expected['?'] = array('query' => 'test');
  1431. $this->assertEquals($expected, $result);
  1432. Router::reload();
  1433. Router::extensions(['rss', 'xml'], false);
  1434. $this->_connectDefaultRoutes();
  1435. $result = Router::parse('/posts.xml');
  1436. $expected = array(
  1437. 'plugin' => null,
  1438. 'controller' => 'Posts',
  1439. 'action' => 'index',
  1440. '_ext' => 'xml',
  1441. 'pass' => []
  1442. );
  1443. $this->assertEquals($expected, $result);
  1444. $result = Router::parse('/posts.atom?hello=goodbye');
  1445. $expected = array(
  1446. 'plugin' => null,
  1447. 'controller' => 'Posts.atom',
  1448. 'action' => 'index',
  1449. 'pass' => [],
  1450. '?' => array('hello' => 'goodbye')
  1451. );
  1452. $this->assertEquals($expected, $result);
  1453. Router::reload();
  1454. Router::connect('/controller/action', array('controller' => 'controller', 'action' => 'action', '_ext' => 'rss'));
  1455. $result = Router::parse('/controller/action');
  1456. $expected = array('controller' => 'controller', 'action' => 'action', 'plugin' => null, '_ext' => 'rss', 'pass' => []);
  1457. $this->assertEquals($expected, $result);
  1458. Router::reload();
  1459. Router::connect('/controller/action', array('controller' => 'controller', 'action' => 'action', '_ext' => 'rss'));
  1460. $result = Router::parse('/controller/action');
  1461. $expected = array(
  1462. 'controller' => 'controller',
  1463. 'action' => 'action',
  1464. 'plugin' => null,
  1465. '_ext' => 'rss',
  1466. 'pass' => []
  1467. );
  1468. $this->assertEquals($expected, $result);
  1469. Router::reload();
  1470. Router::extensions('rss', false);
  1471. Router::connect('/controller/action', array('controller' => 'controller', 'action' => 'action', '_ext' => 'rss'));
  1472. $result = Router::parse('/controller/action');
  1473. $expected = array(
  1474. 'controller' => 'controller',
  1475. 'action' => 'action',
  1476. 'plugin' => null,
  1477. '_ext' => 'rss',
  1478. 'pass' => []
  1479. );
  1480. $this->assertEquals($expected, $result);
  1481. }
  1482. /**
  1483. * Test newer style automatically generated prefix routes.
  1484. *
  1485. * @return void
  1486. * @see testUrlGenerationWithAutoPrefixes
  1487. */
  1488. public function testUrlGenerationWithAutoPrefixes() {
  1489. Router::reload();
  1490. Router::connect('/protected/:controller/:action/*', array('prefix' => 'protected'));
  1491. Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
  1492. Router::connect('/:controller/:action/*');
  1493. $request = new Request();
  1494. Router::setRequestInfo(
  1495. $request->addParams(array(
  1496. 'plugin' => null, 'controller' => 'images', 'action' => 'index',
  1497. 'prefix' => null, 'protected' => false, 'url' => array('url' => 'images/index')
  1498. ))->addPaths(array(
  1499. 'base' => '',
  1500. 'here' => '/images/index',
  1501. 'webroot' => '/',
  1502. ))
  1503. );
  1504. $result = Router::url(array('controller' => 'images', 'action' => 'add'));
  1505. $expected = '/images/add';
  1506. $this->assertEquals($expected, $result);
  1507. $result = Router::url(array('controller' => 'images', 'action' => 'add', 'prefix' => 'protected'));
  1508. $expected = '/protected/images/add';
  1509. $this->assertEquals($expected, $result);
  1510. $result = Router::url(array('controller' => 'images', 'action' => 'add_protected_test', 'prefix' => 'protected'));
  1511. $expected = '/protected/images/add_protected_test';
  1512. $this->assertEquals($expected, $result);
  1513. $result = Router::url(array('action' => 'edit', 1));
  1514. $expected = '/images/edit/1';
  1515. $this->assertEquals($expected, $result);
  1516. $result = Router::url(array('action' => 'edit', 1, 'prefix' => 'protected'));
  1517. $expected = '/protected/images/edit/1';
  1518. $this->assertEquals($expected, $result);
  1519. $result = Router::url(array('action' => 'protectededit', 1, 'prefix' => 'protected'));
  1520. $expected = '/protected/images/protectededit/1';
  1521. $this->assertEquals($expected, $result);
  1522. $result = Router::url(array('action' => 'edit', 1, 'prefix' => 'protected'));
  1523. $expected = '/protected/images/edit/1';
  1524. $this->assertEquals($expected, $result);
  1525. $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1));
  1526. $expected = '/others/edit/1';
  1527. $this->assertEquals($expected, $result);
  1528. $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'prefix' => 'protected'));
  1529. $expected = '/protected/others/edit/1';
  1530. $this->assertEquals($expected, $result);
  1531. }
  1532. /**
  1533. * Test that the ssl option works.
  1534. *
  1535. * @return void
  1536. */
  1537. public function testGenerationWithSslOption() {
  1538. Router::connect('/:controller/:action/*');
  1539. $request = new Request();
  1540. $request->env('HTTP_HOST', 'localhost');
  1541. Router::pushRequest(
  1542. $request->addParams(array(
  1543. 'plugin' => null, 'controller' => 'images', 'action' => 'index'
  1544. ))->addPaths(array(
  1545. 'base' => '',
  1546. 'here' => '/images/index',
  1547. 'webroot' => '/',
  1548. ))
  1549. );
  1550. $result = Router::url(array(
  1551. '_ssl' => true
  1552. ));
  1553. $this->assertEquals('https://localhost/images/index', $result);
  1554. $result = Router::url(array(
  1555. '_ssl' => false
  1556. ));
  1557. $this->assertEquals('http://localhost/images/index', $result);
  1558. }
  1559. /**
  1560. * Test ssl option when the current request is ssl.
  1561. *
  1562. * @return void
  1563. */
  1564. public function testGenerateWithSslInSsl() {
  1565. Router::connect('/:controller/:action/*');
  1566. $request = new Request();
  1567. $request->env('HTTP_HOST', 'localhost');
  1568. $request->env('HTTPS', 'on');
  1569. Router::pushRequest(
  1570. $request->addParams(array(
  1571. 'plugin' => null,
  1572. 'controller' => 'images',
  1573. 'action' => 'index'
  1574. ))->addPaths(array(
  1575. 'base' => '',
  1576. 'here' => '/images/index',
  1577. 'webroot' => '/',
  1578. ))
  1579. );
  1580. $result = Router::url(array(
  1581. '_ssl' => false
  1582. ));
  1583. $this->assertEquals('http://localhost/images/index', $result);
  1584. $result = Router::url(array(
  1585. '_ssl' => true
  1586. ));
  1587. $this->assertEquals('https://localhost/images/index', $result);
  1588. }
  1589. /**
  1590. * test that prefix routes persist when they are in the current request.
  1591. *
  1592. * @return void
  1593. */
  1594. public function testPrefixRoutePersistence() {
  1595. Router::reload();
  1596. Router::connect('/protected/:controller/:action', array('prefix' => 'protected'));
  1597. Router::connect('/:controller/:action');
  1598. $request = new Request();
  1599. Router::setRequestInfo(
  1600. $request->addParams(array(
  1601. 'plugin' => null,
  1602. 'controller' => 'images',
  1603. 'action' => 'index',
  1604. 'prefix' => 'protected',
  1605. ))->addPaths(array(
  1606. 'base' => '',
  1607. 'here' => '/protected/images/index',
  1608. 'webroot' => '/',
  1609. ))
  1610. );
  1611. $result = Router::url(array('prefix' => 'protected', 'controller' => 'images', 'action' => 'add'));
  1612. $expected = '/protected/images/add';
  1613. $this->assertEquals($expected, $result);
  1614. $result = Router::url(array('controller' => 'images', 'action' => 'add'));
  1615. $expected = '/protected/images/add';
  1616. $this->assertEquals($expected, $result);
  1617. $result = Router::url(array('controller' => 'images', 'action' => 'add', 'prefix' => false));
  1618. $expected = '/images/add';
  1619. $this->assertEquals($expected, $result);
  1620. }
  1621. /**
  1622. * test that setting a prefix override the current one
  1623. *
  1624. * @return void
  1625. */
  1626. public function testPrefixOverride() {
  1627. Router::connect('/admin/:controller/:action', array('prefix' => 'admin'));
  1628. Router::connect('/protected/:controller/:action', array('prefix' => 'protected'));
  1629. $request = new Request();
  1630. Router::setRequestInfo(
  1631. $request->addParams(array(
  1632. 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => 'protected',
  1633. ))->addPaths(array(
  1634. 'base' => '',
  1635. 'here' => '/protected/images/index',
  1636. 'webroot' => '/',
  1637. ))
  1638. );
  1639. $result = Router::url(array('controller' => 'images', 'action' => 'add', 'prefix' => 'admin'));
  1640. $expected = '/admin/images/add';
  1641. $this->assertEquals($expected, $result);
  1642. $request = new Request();
  1643. Router::setRequestInfo(
  1644. $request->addParams(array(
  1645. 'plugin' => null,
  1646. 'controller' => 'images',
  1647. 'action' => 'index',
  1648. 'prefix' => 'admin',
  1649. ))->addPaths(array(
  1650. 'base' => '',
  1651. 'here' => '/admin/images/index',
  1652. 'webroot' => '/',
  1653. ))
  1654. );
  1655. $result = Router::url(array('controller' => 'images', 'action' => 'add', 'prefix' => 'protected'));
  1656. $expected = '/protected/images/add';
  1657. $this->assertEquals($expected, $result);
  1658. }
  1659. /**
  1660. * Test that well known route parameters are passed through.
  1661. *
  1662. * @return void
  1663. */
  1664. public function testRouteParamDefaults() {
  1665. Router::connect('/cache/*', array('prefix' => false, 'plugin' => true, 'controller' => 0, 'action' => 1));
  1666. $url = Router::url(array('prefix' => 0, 'plugin' => 1, 'controller' => 0, 'action' => 1, 'test'));
  1667. $expected = '/cache/test';
  1668. $this->assertEquals($expected, $url);
  1669. try {
  1670. Router::url(array('controller' => 0, 'action' => 1, 'test'));
  1671. $this->fail('No exception raised');
  1672. } catch (\Exception $e) {
  1673. $this->assertTrue(true, 'Exception was raised');
  1674. }
  1675. try {
  1676. Router::url(array('prefix' => 1, 'controller' => 0, 'action' => 1, 'test'));
  1677. $this->fail('No exception raised');
  1678. } catch (\Exception $e) {
  1679. $this->assertTrue(true, 'Exception was raised');
  1680. }
  1681. }
  1682. /**
  1683. * testRemoveBase method
  1684. *
  1685. * @return void
  1686. */
  1687. public function testRemoveBase() {
  1688. Router::connect('/:controller/:action');
  1689. $request = new Request();
  1690. Router::setRequestInfo(
  1691. $request->addParams(array(
  1692. 'plugin' => null, 'controller' => 'controller', 'action' => 'index',
  1693. ))->addPaths(array(
  1694. 'base' => '/base',
  1695. 'here' => '/',
  1696. 'webroot' => '/base/',
  1697. ))
  1698. );
  1699. $result = Router::url(array('controller' => 'my_controller', 'action' => 'my_action'));
  1700. $expected = '/base/my_controller/my_action';
  1701. $this->assertEquals($expected, $result);
  1702. $result = Router::url(array('controller' => 'my_controller', 'action' => 'my_action', '_base' => false));
  1703. $expected = '/my_controller/my_action';
  1704. $this->assertEquals($expected, $result);
  1705. }
  1706. /**
  1707. * testPagesUrlParsing method
  1708. *
  1709. * @return void
  1710. */
  1711. public function testPagesUrlParsing() {
  1712. Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
  1713. Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  1714. $result = Router::parse('/');
  1715. $expected = array('pass' => array('home'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display');
  1716. $this->assertEquals($expected, $result);
  1717. $result = Router::parse('/pages/home/');
  1718. $expected = array('pass' => array('home'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display');
  1719. $this->assertEquals($expected, $result);
  1720. Router::reload();
  1721. Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
  1722. $result = Router::parse('/');
  1723. $expected = array('pass' => array('home'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display');
  1724. $this->assertEquals($expected, $result);
  1725. Router::reload();
  1726. Router::connect('/', array('controller' => 'posts', 'action' => 'index'));
  1727. Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  1728. $result = Router::parse('/pages/contact/');
  1729. $expected = array('pass' => array('contact'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display');
  1730. $this->assertEquals($expected, $result);
  1731. }
  1732. /**
  1733. * test that requests with a trailing dot don't loose the do.
  1734. *
  1735. * @return void
  1736. */
  1737. public function testParsingWithTrailingPeriod() {
  1738. Router::reload();
  1739. Router::connect('/:controller/:action/*');
  1740. $result = Router::parse('/posts/view/something.');
  1741. $this->assertEquals('something.', $result['pass'][0], 'Period was chopped off %s');
  1742. $result = Router::parse('/posts/view/something. . .');
  1743. $this->assertEquals('something. . .', $result['pass'][0], 'Period was chopped off %s');
  1744. }
  1745. /**
  1746. * test that requests with a trailing dot don't loose the do.
  1747. *
  1748. * @return void
  1749. */
  1750. public function testParsingWithTrailingPeriodAndParseExtensions() {
  1751. Router::reload();
  1752. Router::connect('/:controller/:action/*');
  1753. Router::extensions('json', false);
  1754. $result = Router::parse('/posts/view/something.');
  1755. $this->assertEquals('something.', $result['pass'][0], 'Period was chopped off %s');
  1756. $result = Router::parse('/posts/view/something. . .');
  1757. $this->assertEquals('something. . .', $result['pass'][0], 'Period was chopped off %s');
  1758. }
  1759. /**
  1760. * test that patterns work for :action
  1761. *
  1762. * @expectedException \Cake\Routing\Exception\MissingRouteException
  1763. * @return void
  1764. */
  1765. public function testParsingWithPatternOnAction() {
  1766. Router::connect(
  1767. '/blog/:action/*',
  1768. array('controller' => 'blog_posts'),
  1769. array('action' => 'other|actions')
  1770. );
  1771. $result = Router::parse('/blog/other');
  1772. $expected = array(
  1773. 'plugin' => null,
  1774. 'controller' => 'blog_posts',
  1775. 'action' => 'other',
  1776. 'pass' => [],
  1777. );
  1778. $this->assertEquals($expected, $result);
  1779. Router::parse('/blog/foobar');
  1780. }
  1781. /**
  1782. * Test url() works with patterns on :action
  1783. *
  1784. * @expectedException \Cake\Routing\Exception\MissingRouteException
  1785. * @return void
  1786. */
  1787. public function testUrlPatternOnAction() {
  1788. Router::connect(
  1789. '/blog/:action/*',
  1790. array('controller' => 'blog_posts'),
  1791. array('action' => 'other|actions')
  1792. );
  1793. $result = Router::url(array('controller' => 'blog_posts', 'action' => 'actions'));
  1794. $this->assertEquals('/blog/actions', $result);
  1795. $result = Router::url(array('controller' => 'blog_posts', 'action' => 'foo'));
  1796. $this->assertEquals('/', $result);
  1797. }
  1798. /**
  1799. * testParsingWithLiteralPrefixes method
  1800. *
  1801. * @return void
  1802. */
  1803. public function testParsingWithLiteralPrefixes() {
  1804. Router::reload();
  1805. $adminParams = array('prefix' => 'admin');
  1806. Router::connect('/admin/:controller', $adminParams);
  1807. Router::connect('/admin/:controller/:action/*', $adminParams);
  1808. $request = new Request();
  1809. Router::setRequestInfo(
  1810. $request->addParams(array(
  1811. 'plugin' => null, 'controller' => 'controller', 'action' => 'index'
  1812. ))->addPaths(array(
  1813. 'base' => '/base',
  1814. 'here' => '/',
  1815. 'webroot' => '/base/',
  1816. ))
  1817. );
  1818. $result = Router::parse('/admin/posts/');
  1819. $expected = array('pass' => [], 'prefix' => 'admin', 'plugin' => null, 'controller' => 'posts', 'action' => 'index');
  1820. $this->assertEquals($expected, $result);
  1821. $result = Router::parse('/admin/posts');
  1822. $this->assertEquals($expected, $result);
  1823. $result = Router::url(array('prefix' => 'admin', 'controller' => 'posts'));
  1824. $expected = '/base/admin/posts';
  1825. $this->assertEquals($expected, $result);
  1826. Router::reload();
  1827. $prefixParams = array('prefix' => 'members');
  1828. Router::connect('/members/:controller', $prefixParams);
  1829. Router::connect('/members/:controller/:action', $prefixParams);
  1830. Router::connect('/members/:controller/:action/*', $prefixParams);
  1831. $request = new Request();
  1832. Router::setRequestInfo(
  1833. $request->addParams(array(
  1834. 'plugin' => null, 'controller' => 'controller', 'action' => 'index',
  1835. ))->addPaths(array(
  1836. 'base' => '/base',
  1837. 'here' => '/',
  1838. 'webroot' => '/',
  1839. ))
  1840. );
  1841. $result = Router::parse('/members/posts/index');
  1842. $expected = array('pass' => [], 'prefix' => 'members', 'plugin' => null, 'controller' => 'posts', 'action' => 'index');
  1843. $this->assertEquals($expected, $result);
  1844. $result = Router::url(array('prefix' => 'members', 'controller' => 'users', 'action' => 'add'));
  1845. $expected = '/base/members/users/add';
  1846. $this->assertEquals($expected, $result);
  1847. }
  1848. /**
  1849. * Tests URL generation with flags and prefixes in and out of context
  1850. *
  1851. * @return void
  1852. */
  1853. public function testUrlWritingWithPrefixes() {
  1854. Router::connect('/company/:controller/:action/*', array('prefix' => 'company'));
  1855. Router::connect('/:action', array('controller' => 'users'));
  1856. $result = Router::url(array('controller' => 'users', 'action' => 'login', 'prefix' => 'company'));
  1857. $expected = '/company/users/login';
  1858. $this->assertEquals($expected, $result);
  1859. $request = new Request();
  1860. Router::setRequestInfo(
  1861. $request->addParams(array(
  1862. 'plugin' => null,
  1863. 'controller' => 'users',
  1864. 'action' => 'login',
  1865. 'prefix' => 'company'
  1866. ))->addPaths(array(
  1867. 'base' => '/',
  1868. 'here' => '/',
  1869. 'webroot' => '/base/',
  1870. ))
  1871. );
  1872. $result = Router::url(array('controller' => 'users', 'action' => 'login', 'prefix' => false));
  1873. $expected = '/login';
  1874. $this->assertEquals($expected, $result);
  1875. }
  1876. /**
  1877. * test url generation with prefixes and custom routes
  1878. *
  1879. * @return void
  1880. */
  1881. public function testUrlWritingWithPrefixesAndCustomRoutes() {
  1882. Router::connect(
  1883. '/admin/login',
  1884. array('controller' => 'users', 'action' => 'login', 'prefix' => 'admin')
  1885. );
  1886. $request = new Request();
  1887. Router::setRequestInfo(
  1888. $request->addParams(array(
  1889. 'plugin' => null, 'controller' => 'posts', 'action' => 'index',
  1890. 'prefix' => 'admin'
  1891. ))->addPaths(array(
  1892. 'base' => '/',
  1893. 'here' => '/',
  1894. 'webroot' => '/',
  1895. ))
  1896. );
  1897. $result = Router::url(array('controller' => 'users', 'action' => 'login'));
  1898. $this->assertEquals('/admin/login', $result);
  1899. $result = Router::url(array('controller' => 'users', 'action' => 'login'));
  1900. $this->assertEquals('/admin/login', $result);
  1901. }
  1902. /**
  1903. * testPassedArgsOrder method
  1904. *
  1905. * @return void
  1906. */
  1907. public function testPassedArgsOrder() {
  1908. Router::connect('/test-passed/*', array('controller' => 'pages', 'action' => 'display', 'home'));
  1909. Router::connect('/test2/*', array('controller' => 'pages', 'action' => 'display', 2));
  1910. Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 1));
  1911. $result = Router::url(array('controller' => 'pages', 'action' => 'display', 1, 'whatever'));
  1912. $expected = '/test/whatever';
  1913. $this->assertEquals($expected, $result);
  1914. $result = Router::url(array('controller' => 'pages', 'action' => 'display', 2, 'whatever'));
  1915. $expected = '/test2/whatever';
  1916. $this->assertEquals($expected, $result);
  1917. $result = Router::url(array('controller' => 'pages', 'action' => 'display', 'home', 'whatever'));
  1918. $expected = '/test-passed/whatever';
  1919. $this->assertEquals($expected, $result);
  1920. }
  1921. /**
  1922. * testRegexRouteMatching method
  1923. *
  1924. * @return void
  1925. */
  1926. public function testRegexRouteMatching() {
  1927. Router::connect('/:locale/:controller/:action/*', [], array('locale' => 'dan|eng'));
  1928. $result = Router::parse('/eng/test/test_action');
  1929. $expected = array('pass' => [], 'locale' => 'eng', 'controller' => 'test', 'action' => 'test_action', 'plugin' => null);
  1930. $this->assertEquals($expected, $result);
  1931. }
  1932. /**
  1933. * testRegexRouteMatching error
  1934. *
  1935. * @expectedException \Cake\Routing\Exception\MissingRouteException
  1936. * @return void
  1937. */
  1938. public function testRegexRouteMatchingError() {
  1939. Router::connect('/:locale/:controller/:action/*', [], array('locale' => 'dan|eng'));
  1940. Router::parse('/badness/test/test_action');
  1941. }
  1942. /**
  1943. * testRegexRouteMatching method
  1944. *
  1945. * @expectedException \Cake\Routing\Exception\MissingRouteException
  1946. * @return void
  1947. */
  1948. public function testRegexRouteMatchUrl() {
  1949. Router::connect('/:locale/:controller/:action/*', [], array('locale' => 'dan|eng'));
  1950. $request = new Request();
  1951. Router::setRequestInfo(
  1952. $request->addParams(array(
  1953. 'plugin' => null,
  1954. 'controller' => 'test',
  1955. 'action' => 'index',
  1956. 'url' => array('url' => 'test/test_action')
  1957. ))->addPaths(array(
  1958. 'base' => '',
  1959. 'here' => '/test/test_action',
  1960. 'webroot' => '/',
  1961. ))
  1962. );
  1963. $result = Router::url(array('action' => 'test_another_action', 'locale' => 'eng'));
  1964. $expected = '/eng/test/test_another_action';
  1965. $this->assertEquals($expected, $result);
  1966. $result = Router::url(array('action' => 'test_another_action'));
  1967. $expected = '/';
  1968. $this->assertEquals($expected, $result);
  1969. }
  1970. /**
  1971. * test using a custom route class for route connection
  1972. *
  1973. * @return void
  1974. */
  1975. public function testUsingCustomRouteClass() {
  1976. Plugin::load('TestPlugin');
  1977. Router::connect(
  1978. '/:slug',
  1979. array('plugin' => 'TestPlugin', 'action' => 'index'),
  1980. array('routeClass' => 'PluginShortRoute', 'slug' => '[a-z_-]+')
  1981. );
  1982. $result = Router::parse('/the-best');
  1983. $expected = [
  1984. 'plugin' => 'TestPlugin',
  1985. 'controller' => 'TestPlugin',
  1986. 'action' => 'index',
  1987. 'slug' => 'the-best',
  1988. 'pass' => [],
  1989. ];
  1990. $this->assertEquals($expected, $result);
  1991. }
  1992. /**
  1993. * test using custom route class in PluginDot notation
  1994. *
  1995. * @return void
  1996. */
  1997. public function testUsingCustomRouteClassPluginDotSyntax() {
  1998. Plugin::load('TestPlugin');
  1999. Router::connect(
  2000. '/:slug',
  2001. array('controller' => 'posts', 'action' => 'view'),
  2002. array('routeClass' => 'TestPlugin.TestRoute', 'slug' => '[a-z_-]+')
  2003. );
  2004. $this->assertTrue(true); // Just to make sure the connect do not throw exception
  2005. Plugin::unload('TestPlugin');
  2006. }
  2007. /**
  2008. * test that route classes must extend \Cake\Routing\Route\Route
  2009. *
  2010. * @expectedException \InvalidArgumentException
  2011. * @return void
  2012. */
  2013. public function testCustomRouteException() {
  2014. Router::connect('/:controller', [], array('routeClass' => 'Object'));
  2015. }
  2016. /**
  2017. * test reversing parameter arrays back into strings.
  2018. *
  2019. * Mark the router as initialized so it doesn't auto-load routes
  2020. *
  2021. * @return void
  2022. */
  2023. public function testReverse() {
  2024. Router::connect('/:controller/:action/*');
  2025. $params = array(
  2026. 'controller' => 'posts',
  2027. 'action' => 'view',
  2028. 'pass' => array(1),
  2029. 'url' => [],
  2030. 'autoRender' => 1,
  2031. 'bare' => 1,
  2032. 'return' => 1,
  2033. 'requested' => 1,
  2034. '_Token' => array('key' => 'sekret')
  2035. );
  2036. $result = Router::reverse($params);
  2037. $this->assertEquals('/posts/view/1', $result);
  2038. Router::reload();
  2039. Router::connect('/:lang/:controller/:action/*', [], array('lang' => '[a-z]{3}'));
  2040. $params = array(
  2041. 'lang' => 'eng',
  2042. 'controller' => 'posts',
  2043. 'action' => 'view',
  2044. 'pass' => array(1),
  2045. 'url' => array('url' => 'eng/posts/view/1')
  2046. );
  2047. $result = Router::reverse($params);
  2048. $this->assertEquals('/eng/posts/view/1', $result);
  2049. $params = array(
  2050. 'lang' => 'eng',
  2051. 'controller' => 'posts',
  2052. 'action' => 'view',
  2053. 1,
  2054. '?' => ['foo' => 'bar']
  2055. );
  2056. $result = Router::reverse($params);
  2057. $this->assertEquals('/eng/posts/view/1?foo=bar', $result);
  2058. $params = array(
  2059. 'lang' => 'eng',
  2060. 'controller' => 'posts',
  2061. 'action' => 'view',
  2062. 'pass' => array(1),
  2063. 'url' => array('url' => 'eng/posts/view/1', 'foo' => 'bar', 'baz' => 'quu'),
  2064. 'paging' => [],
  2065. 'models' => []
  2066. );
  2067. $result = Router::reverse($params);
  2068. $this->assertEquals('/eng/posts/view/1?foo=bar&baz=quu', $result);
  2069. $request = new Request('/eng/posts/view/1');
  2070. $request->addParams(array(
  2071. 'lang' => 'eng',
  2072. 'controller' => 'posts',
  2073. 'action' => 'view',
  2074. 'pass' => array(1),
  2075. ));
  2076. $request->query = array('url' => 'eng/posts/view/1', 'test' => 'value');
  2077. $result = Router::reverse($request);
  2078. $expected = '/eng/posts/view/1?test=value';
  2079. $this->assertEquals($expected, $result);
  2080. $params = array(
  2081. 'lang' => 'eng',
  2082. 'controller' => 'posts',
  2083. 'action' => 'view',
  2084. 'pass' => array(1),
  2085. 'url' => array('url' => 'eng/posts/view/1')
  2086. );
  2087. $result = Router::reverse($params, true);
  2088. $this->assertRegExp('/^http(s)?:\/\//', $result);
  2089. }
  2090. /**
  2091. * Test that extensions work with Router::reverse()
  2092. *
  2093. * @return void
  2094. */
  2095. public function testReverseWithExtension() {
  2096. Router::connect('/:controller/:action/*');
  2097. Router::extensions('json', false);
  2098. $request = new Request('/posts/view/1.json');
  2099. $request->addParams(array(
  2100. 'controller' => 'posts',
  2101. 'action' => 'view',
  2102. 'pass' => array(1),
  2103. '_ext' => 'json',
  2104. ));
  2105. $request->query = [];
  2106. $result = Router::reverse($request);
  2107. $expected = '/posts/view/1.json';
  2108. $this->assertEquals($expected, $result);
  2109. }
  2110. /**
  2111. * test that setRequestInfo can accept arrays and turn that into a Request object.
  2112. *
  2113. * @return void
  2114. */
  2115. public function testSetRequestInfoLegacy() {
  2116. Router::setRequestInfo(array(
  2117. array(
  2118. 'plugin' => null, 'controller' => 'images', 'action' => 'index',
  2119. 'url' => array('url' => 'protected/images/index')
  2120. ),
  2121. array(
  2122. 'base' => '',
  2123. 'here' => '/protected/images/index',
  2124. 'webroot' => '/',
  2125. )
  2126. ));
  2127. $result = Router::getRequest();
  2128. $this->assertEquals('images', $result->controller);
  2129. $this->assertEquals('index', $result->action);
  2130. $this->assertEquals('', $result->base);
  2131. $this->assertEquals('/protected/images/index', $result->here);
  2132. $this->assertEquals('/', $result->webroot);
  2133. }
  2134. /**
  2135. * test get request.
  2136. *
  2137. * @return void
  2138. */
  2139. public function testGetRequest() {
  2140. $requestA = new Request('/');
  2141. $requestB = new Request('/posts');
  2142. Router::pushRequest($requestA);
  2143. Router::pushRequest($requestB);
  2144. $this->assertSame($requestA, Router::getRequest(false));
  2145. $this->assertSame($requestB, Router::getRequest(true));
  2146. }
  2147. /**
  2148. * Test that Router::url() uses the first request
  2149. */
  2150. public function testUrlWithRequestAction() {
  2151. Router::connect('/:controller', array('action' => 'index'));
  2152. Router::connect('/:controller/:action');
  2153. $firstRequest = new Request('/posts/index');
  2154. $firstRequest->addParams(array(
  2155. 'plugin' => null,
  2156. 'controller' => 'posts',
  2157. 'action' => 'index'
  2158. ))->addPaths(array('base' => ''));
  2159. $secondRequest = new Request('/posts/index');
  2160. $secondRequest->addParams(array(
  2161. 'requested' => 1,
  2162. 'plugin' => null,
  2163. 'controller' => 'comments',
  2164. 'action' => 'listing'
  2165. ))->addPaths(array('base' => ''));
  2166. Router::setRequestInfo($firstRequest);
  2167. Router::setRequestInfo($secondRequest);
  2168. $result = Router::url(array('_base' => false));
  2169. $this->assertEquals('/comments/listing', $result, 'with second requests, the last should win.');
  2170. Router::popRequest();
  2171. $result = Router::url(array('_base' => false));
  2172. $this->assertEquals('/posts', $result, 'with second requests, the last should win.');
  2173. // Make sure that popping an empty request doesn't fail.
  2174. Router::popRequest();
  2175. }
  2176. /**
  2177. * test that a route object returning a full URL is not modified.
  2178. *
  2179. * @return void
  2180. */
  2181. public function testUrlFullUrlReturnFromRoute() {
  2182. $url = 'http://example.com/posts/view/1';
  2183. $route = $this->getMock(
  2184. 'Cake\Routing\Route\Route',
  2185. ['match'],
  2186. ['/:controller/:action/*']
  2187. );
  2188. $route->expects($this->any())
  2189. ->method('match')
  2190. ->will($this->returnValue($url));
  2191. Router::connect($route);
  2192. $result = Router::url(array('controller' => 'posts', 'action' => 'view', 1));
  2193. $this->assertEquals($url, $result);
  2194. }
  2195. /**
  2196. * test protocol in url
  2197. *
  2198. * @return void
  2199. */
  2200. public function testUrlProtocol() {
  2201. $url = 'http://example.com';
  2202. $this->assertEquals($url, Router::url($url));
  2203. $url = 'ed2k://example.com';
  2204. $this->assertEquals($url, Router::url($url));
  2205. $url = 'svn+ssh://example.com';
  2206. $this->assertEquals($url, Router::url($url));
  2207. $url = '://example.com';
  2208. $this->assertEquals($url, Router::url($url));
  2209. $url = '//example.com';
  2210. $this->assertEquals($url, Router::url($url));
  2211. $url = 'javascript:void(0)';
  2212. $this->assertEquals($url, Router::url($url));
  2213. $url = 'tel:012345-678';
  2214. $this->assertEquals($url, Router::url($url));
  2215. $url = 'sms:012345-678';
  2216. $this->assertEquals($url, Router::url($url));
  2217. $url = '#here';
  2218. $this->assertEquals($url, Router::url($url));
  2219. $url = '?param=0';
  2220. $this->assertEquals($url, Router::url($url));
  2221. $url = '/posts/index#here';
  2222. $expected = Configure::read('App.fullBaseUrl') . '/posts/index#here';
  2223. $this->assertEquals($expected, Router::url($url, true));
  2224. }
  2225. /**
  2226. * Testing that patterns on the :action param work properly.
  2227. *
  2228. * @return void
  2229. */
  2230. public function testPatternOnAction() {
  2231. $route = new Route(
  2232. '/blog/:action/*',
  2233. array('controller' => 'blog_posts'),
  2234. array('action' => 'other|actions')
  2235. );
  2236. $result = $route->match(array('controller' => 'blog_posts', 'action' => 'foo'));
  2237. $this->assertFalse($result);
  2238. $result = $route->match(array('controller' => 'blog_posts', 'action' => 'actions'));
  2239. $this->assertEquals('/blog/actions/', $result);
  2240. $result = $route->parse('/blog/other');
  2241. $expected = array('controller' => 'blog_posts', 'action' => 'other', 'pass' => []);
  2242. $this->assertEquals($expected, $result);
  2243. $result = $route->parse('/blog/foobar');
  2244. $this->assertFalse($result);
  2245. }
  2246. /**
  2247. * Test that redirect() works.
  2248. *
  2249. * @return void
  2250. */
  2251. public function testRedirect() {
  2252. Router::redirect('/mobile', '/', ['status' => 301]);
  2253. $routes = Router::routes();
  2254. $route = $routes[0];
  2255. $this->assertInstanceOf('Cake\Routing\Route\RedirectRoute', $route);
  2256. }
  2257. /**
  2258. * Test that the compatibility method for incoming urls works.
  2259. *
  2260. * @return void
  2261. */
  2262. public function testParseNamedParameters() {
  2263. $request = new Request();
  2264. $request->addParams(array(
  2265. 'controller' => 'posts',
  2266. 'action' => 'index',
  2267. ));
  2268. $result = Router::parseNamedParams($request);
  2269. $this->assertSame([], $result->params['named']);
  2270. $request = new Request();
  2271. $request->addParams(array(
  2272. 'controller' => 'posts',
  2273. 'action' => 'index',
  2274. 'pass' => array('home', 'one:two', 'three:four', 'five[nested][0]:six', 'five[nested][1]:seven')
  2275. ));
  2276. Router::parseNamedParams($request);
  2277. $expected = array(
  2278. 'plugin' => null,
  2279. 'controller' => 'posts',
  2280. 'action' => 'index',
  2281. '_ext' => null,
  2282. 'pass' => array('home'),
  2283. 'named' => array(
  2284. 'one' => 'two',
  2285. 'three' => 'four',
  2286. 'five' => array(
  2287. 'nested' => array('six', 'seven')
  2288. )
  2289. )
  2290. );
  2291. $this->assertEquals($expected, $request->params);
  2292. }
  2293. /**
  2294. * Test the scope() method
  2295. *
  2296. * @return void
  2297. */
  2298. public function testScope() {
  2299. Router::scope('/path', ['param' => 'value'], function ($routes) {
  2300. $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
  2301. $this->assertEquals('/path', $routes->path());
  2302. $this->assertEquals(['param' => 'value'], $routes->params());
  2303. $routes->connect('/articles', ['controller' => 'Articles']);
  2304. });
  2305. }
  2306. /**
  2307. * Test the scope() method
  2308. *
  2309. * @expectedException \InvalidArgumentException
  2310. * @return void
  2311. */
  2312. public function testScopeError() {
  2313. Router::scope('/path', 'derpy');
  2314. }
  2315. /**
  2316. * Test to ensure that extensions defined in scopes don't leak.
  2317. * And that global extensions are propagated.
  2318. *
  2319. * @return void
  2320. */
  2321. public function testScopeExtensionsContained() {
  2322. Router::extensions(['json']);
  2323. Router::scope('/', function ($routes) {
  2324. $this->assertEquals(['json'], $routes->extensions(), 'Should default to global extensions.');
  2325. $routes->extensions(['rss']);
  2326. $this->assertEquals(
  2327. ['rss'],
  2328. $routes->extensions(),
  2329. 'Should include new extensions.'
  2330. );
  2331. $routes->connect('/home', []);
  2332. });
  2333. $this->assertEquals(['json', 'rss'], array_values(Router::extensions()));
  2334. Router::scope('/api', function ($routes) {
  2335. $this->assertEquals(['json'], $routes->extensions(), 'Should default to global extensions.');
  2336. $routes->extensions(['json', 'csv']);
  2337. $routes->connect('/export', []);
  2338. $routes->scope('/v1', function ($routes) {
  2339. $this->assertEquals(['json', 'csv'], $routes->extensions());
  2340. });
  2341. });
  2342. $this->assertEquals(['json', 'rss', 'csv'], array_values(Router::extensions()));
  2343. }
  2344. /**
  2345. * Test that prefix() creates a scope.
  2346. *
  2347. * @return void
  2348. */
  2349. public function testPrefix() {
  2350. Router::prefix('admin', function ($routes) {
  2351. $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
  2352. $this->assertEquals('/admin', $routes->path());
  2353. $this->assertEquals(['prefix' => 'admin'], $routes->params());
  2354. });
  2355. }
  2356. /**
  2357. * Test that plugin() creates a scope.
  2358. *
  2359. * @return void
  2360. */
  2361. public function testPlugin() {
  2362. Router::plugin('DebugKit', function ($routes) {
  2363. $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
  2364. $this->assertEquals('/debug_kit', $routes->path());
  2365. $this->assertEquals(['plugin' => 'DebugKit'], $routes->params());
  2366. });
  2367. }
  2368. /**
  2369. * Test that plugin() accepts options
  2370. *
  2371. * @return void
  2372. */
  2373. public function testPluginOptions() {
  2374. Router::plugin('DebugKit', ['path' => '/debugger'], function ($routes) {
  2375. $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
  2376. $this->assertEquals('/debugger', $routes->path());
  2377. $this->assertEquals(['plugin' => 'DebugKit'], $routes->params());
  2378. });
  2379. }
  2380. /**
  2381. * Test setting default route class.
  2382. *
  2383. * @return void
  2384. */
  2385. public function testDefaultRouteClass() {
  2386. Router::connect('/:controller', ['action' => 'index']);
  2387. $result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
  2388. $this->assertEquals('/FooBar', $result);
  2389. // This is needed because tests/boostrap.php sets App.namespace to 'App'
  2390. Configure::write('App.namespace', 'TestApp');
  2391. Router::defaultRouteClass('DashedRoute');
  2392. Router::connect('/cake/:controller', ['action' => 'cake']);
  2393. $result = Router::url(['controller' => 'FooBar', 'action' => 'cake']);
  2394. $this->assertEquals('/cake/foo-bar', $result);
  2395. $result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
  2396. $this->assertEquals('/FooBar', $result);
  2397. Router::reload();
  2398. Router::defaultRouteClass('DashedRoute');
  2399. Router::scope('/', function ($routes) {
  2400. $routes->fallbacks();
  2401. });
  2402. $result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
  2403. $this->assertEquals('/foo-bar', $result);
  2404. }
  2405. /**
  2406. * Connect some fallback routes for testing router behavior.
  2407. *
  2408. * @return void
  2409. */
  2410. protected function _connectDefaultRoutes() {
  2411. Router::scope('/', function ($routes) {
  2412. $routes->fallbacks();
  2413. });
  2414. }
  2415. }