@@ -502,6 +502,95 @@ public function testSchemeAndMethodMismatch()
502
502
$ matcher ->match ('/ ' );
503
503
}
504
504
505
+ public function testSiblingRoutes ()
506
+ {
507
+ $ coll = new RouteCollection ();
508
+ $ coll ->add ('a ' , (new Route ('/a{a} ' ))->setMethods ('POST ' ));
509
+ $ coll ->add ('b ' , (new Route ('/a{a} ' ))->setMethods ('PUT ' ));
510
+ $ coll ->add ('c ' , new Route ('/a{a} ' ));
511
+ $ coll ->add ('d ' , (new Route ('/b{a} ' ))->setCondition ('false ' ));
512
+ $ coll ->add ('e ' , (new Route ('/{b}{a} ' ))->setCondition ('false ' ));
513
+ $ coll ->add ('f ' , (new Route ('/{b}{a} ' ))->setRequirements (['b ' => 'b ' ]));
514
+
515
+ $ matcher = $ this ->getUrlMatcher ($ coll );
516
+ $ this ->assertEquals (['_route ' => 'c ' , 'a ' => 'a ' ], $ matcher ->match ('/aa ' ));
517
+ $ this ->assertEquals (['_route ' => 'f ' , 'b ' => 'b ' , 'a ' => 'a ' ], $ matcher ->match ('/ba ' ));
518
+ }
519
+
520
+ public function testRequirementWithCapturingGroup ()
521
+ {
522
+ $ coll = new RouteCollection ();
523
+ $ coll ->add ('a ' , new Route ('/{a}/{b} ' , [], ['a ' => '(a|b) ' ]));
524
+
525
+ $ matcher = $ this ->getUrlMatcher ($ coll );
526
+ $ this ->assertEquals (['_route ' => 'a ' , 'a ' => 'a ' , 'b ' => 'b ' ], $ matcher ->match ('/a/b ' ));
527
+ }
528
+
529
+ public function testDotAllWithCatchAll ()
530
+ {
531
+ $ coll = new RouteCollection ();
532
+ $ coll ->add ('a ' , new Route ('/{id}.html ' , [], ['id ' => '.+ ' ]));
533
+ $ coll ->add ('b ' , new Route ('/{all} ' , [], ['all ' => '.+ ' ]));
534
+
535
+ $ matcher = $ this ->getUrlMatcher ($ coll );
536
+ $ this ->assertEquals (['_route ' => 'a ' , 'id ' => 'foo/bar ' ], $ matcher ->match ('/foo/bar.html ' ));
537
+ }
538
+
539
+ public function testHostPattern ()
540
+ {
541
+ $ coll = new RouteCollection ();
542
+ $ coll ->add ('a ' , new Route ('/{app}/{action}/{unused} ' , [], [], [], '{host} ' ));
543
+
544
+ $ expected = [
545
+ '_route ' => 'a ' ,
546
+ 'app ' => 'an_app ' ,
547
+ 'action ' => 'an_action ' ,
548
+ 'unused ' => 'unused ' ,
549
+ 'host ' => 'foo ' ,
550
+ ];
551
+ $ matcher = $ this ->getUrlMatcher ($ coll , new RequestContext ('' , 'GET ' , 'foo ' ));
552
+ $ this ->assertEquals ($ expected , $ matcher ->match ('/an_app/an_action/unused ' ));
553
+ }
554
+
555
+ public function testHostWithDot ()
556
+ {
557
+ $ coll = new RouteCollection ();
558
+ $ coll ->add ('a ' , new Route ('/foo ' , [], [], [], 'foo.example.com ' ));
559
+ $ coll ->add ('b ' , new Route ('/bar/{baz} ' ));
560
+
561
+ $ matcher = $ this ->getUrlMatcher ($ coll );
562
+ $ this ->assertEquals ('b ' , $ matcher ->match ('/bar/abc.123 ' )['_route ' ]);
563
+ }
564
+
565
+ public function testSlashVariant ()
566
+ {
567
+ $ coll = new RouteCollection ();
568
+ $ coll ->add ('a ' , new Route ('/foo/{bar} ' , [], ['bar ' => '.* ' ]));
569
+
570
+ $ matcher = $ this ->getUrlMatcher ($ coll );
571
+ $ this ->assertEquals ('a ' , $ matcher ->match ('/foo/ ' )['_route ' ]);
572
+ }
573
+
574
+ public function testSlashWithVerb ()
575
+ {
576
+ $ coll = new RouteCollection ();
577
+ $ coll ->add ('a ' , new Route ('/{foo} ' , [], [], [], '' , [], ['put ' , 'delete ' ]));
578
+ $ coll ->add ('b ' , new Route ('/bar/ ' ));
579
+
580
+ $ matcher = $ this ->getUrlMatcher ($ coll );
581
+ $ this ->assertSame (['_route ' => 'b ' ], $ matcher ->match ('/bar/ ' ));
582
+
583
+ $ coll = new RouteCollection ();
584
+ $ coll ->add ('a ' , new Route ('/dav/{foo} ' , [], ['foo ' => '.* ' ], [], '' , [], ['GET ' , 'OPTIONS ' ]));
585
+
586
+ $ matcher = $ this ->getUrlMatcher ($ coll , new RequestContext ('' , 'OPTIONS ' ));
587
+ $ expected = [
588
+ '_route ' => 'a ' ,
589
+ 'foo ' => 'files/bar/ ' ,
590
+ ];
591
+ $ this ->assertEquals ($ expected , $ matcher ->match ('/dav/files/bar/ ' ));
592
+ }
593
+
505
594
public function testSlashAndVerbPrecedence ()
506
595
{
507
596
$ coll = new RouteCollection ();
@@ -527,6 +616,17 @@ public function testSlashAndVerbPrecedence()
527
616
$ this ->assertEquals ($ expected , $ matcher ->match ('/api/customers/123/contactpersons ' ));
528
617
}
529
618
619
+ public function testGreedyTrailingRequirement ()
620
+ {
621
+ $ coll = new RouteCollection ();
622
+ $ coll ->add ('a ' , new Route ('/{a} ' , [], ['a ' => '.+ ' ]));
623
+
624
+ $ matcher = $ this ->getUrlMatcher ($ coll );
625
+
626
+ $ this ->assertEquals (['_route ' => 'a ' , 'a ' => 'foo ' ], $ matcher ->match ('/foo ' ));
627
+ $ this ->assertEquals (['_route ' => 'a ' , 'a ' => 'foo/ ' ], $ matcher ->match ('/foo/ ' ));
628
+ }
629
+
530
630
protected function getUrlMatcher (RouteCollection $ routes , RequestContext $ context = null )
531
631
{
532
632
return new UrlMatcher ($ routes , $ context ?: new RequestContext ());