@@ -25,9 +25,13 @@ class Router
25
25
public const BEFORE = -1 ; // before
26
26
public const AFTER = 1 ; // after
27
27
28
+ public const ROUTE = 0 ;
29
+
30
+ public const LINK = 1 ;
31
+
28
32
public const SUPPORTED_METHODS = [
29
33
'GET ' , 'POST ' , 'PUT ' , 'DELETE ' , 'HEAD ' , 'PATCH ' , 'OPTIONS ' ,
30
- 'ANY ' ,
34
+ 'ANY ' , ' LINK '
31
35
];
32
36
33
37
/** @var array */
@@ -77,6 +81,8 @@ class Router
77
81
'{date[0-9]?} ' => '([0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])) ' ,
78
82
':locale ' => '([A-Za-z]{2}|[A-Za-z]{2}[\_\-]{1}[A-Za-z]{2}) ' ,
79
83
'{locale} ' => '([A-Za-z]{2}|[A-Za-z]{2}[\_\-]{1}[A-Za-z]{2}) ' ,
84
+ ':everything ' => '(.*) ' ,
85
+ '{everything} ' => '(.*) ' ,
80
86
];
81
87
82
88
/** @var RequestInterface */
@@ -90,6 +96,7 @@ class Router
90
96
91
97
protected $ container ;
92
98
99
+ /** @var int */
93
100
protected $ id = 0 ;
94
101
95
102
/** @var array */
@@ -268,6 +275,19 @@ public function register($methods, string $path, $execute, array $options = []):
268
275
return $ this ;
269
276
}
270
277
278
+
279
+ public function link (string $ link , string $ source , array $ options = []): self
280
+ {
281
+ if (!\file_exists ($ source )) {
282
+ throw new InvalidArgumentException ("\$source can be directory or file. " );
283
+ }
284
+ if (\is_dir ($ source )) {
285
+ $ link = \rtrim ($ link , '/ ' ) . '/(.*) ' ;
286
+ }
287
+
288
+ return $ this ->register (['LINK ' ], $ link , $ source , $ options );
289
+ }
290
+
271
291
/**
272
292
* @see Router::register()
273
293
* @param string|string[] $methods
@@ -677,23 +697,7 @@ public function dispatch(): ResponseInterface
677
697
$ hasRoute = isset ($ this ->current_route ) && !empty ($ this ->current_route );
678
698
679
699
if ($ hasRoute === FALSE ){
680
- $ this ->response = $ this ->response ->withStatus (404 );
681
- if (empty ($ this ->error_404 ['execute ' ])){
682
- throw new PageNotFoundException ('Error 404 : Page Not Found ' );
683
- }
684
- \define ('INITPHP_ROUTER_CURRENT_ARGUMENTS ' , $ this ->error_404 ['options ' ]['arguments ' ]);
685
- if (\is_callable ($ this ->error_404 ['execute ' ])){
686
- \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , '__CALLABLE__ ' );
687
- \define ('INITPHP_ROUTER_CURRENT_METHOD ' , '' );
688
- return $ this ->response = $ this ->execute ($ this ->error_404 ['execute ' ], $ this ->error_404 ['options ' ]['arguments ' ]);
689
- }
690
- $ parse = $ this ->getControllerMethod ($ this ->error_404 ['execute ' ], $ this ->error_404 ['options ' ]);
691
- $ parse ['controller ' ] = $ this ->controllerFind ($ parse ['controller ' ]);
692
- $ controller = $ this ->getClassContainer (new \ReflectionClass ($ parse ['controller ' ]));
693
- \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , \get_class ($ controller ));
694
- \define ('INITPHP_ROUTER_CURRENT_METHOD ' , $ parse ['method ' ]);
695
-
696
- return $ this ->response = $ this ->execute ([$ controller , $ parse ['method ' ]], $ this ->error_404 ['options ' ]['arguments ' ]);
700
+ return $ this ->notFound ();
697
701
}
698
702
699
703
$ route = $ this ->current_route ;
@@ -723,27 +727,30 @@ public function dispatch(): ResponseInterface
723
727
if ($ responseStatusCode < 200 || $ responseStatusCode > 299 ){
724
728
return $ this ->response ;
725
729
}
726
-
727
- if (\is_callable ($ route ['execute ' ])){
728
- \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , '__CALLABLE__ ' );
729
- \define ('INITPHP_ROUTER_CURRENT_METHOD ' , '' );
730
- $ this ->response = $ this ->execute ($ route ['execute ' ], $ arguments );
731
- }else {
732
- $ parse = $ this ->getControllerMethod ($ route ['execute ' ], $ route ['options ' ]);
733
- $ parse ['controller ' ] = $ this ->controllerFind ($ parse ['controller ' ]);
734
- $ reflection = new \ReflectionClass ($ parse ['controller ' ]);
735
- $ controller = $ this ->getClassContainer ($ reflection );
736
- $ this ->middleware_handle ($ this ->controller_middlewares_property ($ controller , $ parse ['method ' ], self ::BEFORE ), $ arguments , self ::BEFORE );
737
- \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , \get_class ($ controller ));
738
- \define ('INITPHP_ROUTER_CURRENT_METHOD ' , $ parse ['method ' ]);
739
- $ responseStatusCode = (int )$ this ->response ->getStatusCode ();
740
- if ($ responseStatusCode < 200 || $ responseStatusCode > 299 ){
741
- return $ this ->response ;
742
- }
743
- $ this ->response = $ this ->execute ([$ controller , $ parse ['method ' ]], $ arguments );
744
- $ after_middleware = $ this ->controller_middlewares_property ($ controller , $ parse ['method ' ], self ::AFTER );
745
- if (!empty ($ after_middleware )){
746
- $ filters ['after ' ] = \array_merge ($ filters ['after ' ], $ after_middleware );
730
+ if ($ route ['methods ' ] === ['LINK ' ]) {
731
+ return $ this ->execute ($ route ['execute ' ], $ arguments , self ::LINK );
732
+ } else {
733
+ if (\is_callable ($ route ['execute ' ])){
734
+ \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , '__CALLABLE__ ' );
735
+ \define ('INITPHP_ROUTER_CURRENT_METHOD ' , '' );
736
+ $ this ->response = $ this ->execute ($ route ['execute ' ], $ arguments );
737
+ }else {
738
+ $ parse = $ this ->getControllerMethod ($ route ['execute ' ], $ route ['options ' ]);
739
+ $ parse ['controller ' ] = $ this ->controllerFind ($ parse ['controller ' ]);
740
+ $ reflection = new \ReflectionClass ($ parse ['controller ' ]);
741
+ $ controller = $ this ->getClassContainer ($ reflection );
742
+ $ this ->middleware_handle ($ this ->controller_middlewares_property ($ controller , $ parse ['method ' ], self ::BEFORE ), $ arguments , self ::BEFORE );
743
+ \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , \get_class ($ controller ));
744
+ \define ('INITPHP_ROUTER_CURRENT_METHOD ' , $ parse ['method ' ]);
745
+ $ responseStatusCode = (int )$ this ->response ->getStatusCode ();
746
+ if ($ responseStatusCode < 200 || $ responseStatusCode > 299 ){
747
+ return $ this ->response ;
748
+ }
749
+ $ this ->response = $ this ->execute ([$ controller , $ parse ['method ' ]], $ arguments );
750
+ $ after_middleware = $ this ->controller_middlewares_property ($ controller , $ parse ['method ' ], self ::AFTER );
751
+ if (!empty ($ after_middleware )){
752
+ $ filters ['after ' ] = \array_merge ($ filters ['after ' ], $ after_middleware );
753
+ }
747
754
}
748
755
}
749
756
@@ -762,7 +769,7 @@ public function resolve(string $method, string $current_url): ?array
762
769
$ this ->current_url = $ current_url ;
763
770
$ this ->current_method = $ method = \strtoupper ($ method );
764
771
765
- $ routes = \array_unique (\array_merge ($ this ->methodIds ['ANY ' ], $ this ->methodIds [$ method ]));
772
+ $ routes = \array_unique (\array_merge ($ this ->methodIds ['LINK ' ], $ this -> methodIds [ ' ANY ' ], $ this ->methodIds [$ method ]));
766
773
$ patterns = $ this ->getPatterns ();
767
774
$ matches = [];
768
775
foreach ($ routes as $ id ) {
@@ -779,6 +786,9 @@ public function resolve(string $method, string $current_url): ?array
779
786
if (\preg_match ('#^ ' . $ path . '$# ' , $ this ->current_url , $ arguments )){
780
787
\array_shift ($ arguments );
781
788
$ route ['arguments ' ] = $ arguments ;
789
+ if ($ route ['methods ' ] === ['LINK ' ]) {
790
+ return $ this ->current_method = $ route ;
791
+ }
782
792
$ matches_size = \strlen ($ route ['path ' ]);
783
793
if (\is_array ($ arguments ) && !empty ($ arguments )){
784
794
$ matches_size += (\count ($ arguments ) * 25 );
@@ -938,8 +948,25 @@ private function middleware_handle(array $filters, $arguments, int $pos): void
938
948
}
939
949
}
940
950
941
- private function execute ($ execute , array $ arguments ): ResponseInterface
951
+ private function execute ($ execute , array $ arguments, int $ type = self :: ROUTE ): ResponseInterface
942
952
{
953
+ if ($ type === self ::LINK ) {
954
+ $ path = $ execute
955
+ . ($ arguments [0 ] ?? '' );
956
+ if (\is_file ($ path )) {
957
+ if (($ size = \filesize ($ path )) < 2097152 ) {
958
+ $ this ->response ->getBody ()->write (@\file_get_contents ($ path ));
959
+ return $ this ->response = $ this ->response ->withHeader ('Content-Type ' , \mime_content_type ($ path ))
960
+ ->withHeader ('Content-Length ' , $ size );
961
+ } else {
962
+ @header ("Content-Type: " . \mime_content_type ($ path ) . "; " );
963
+ @header ("Content-Length: " . $ size . "; " );
964
+ readfile ($ path );
965
+ exit ;
966
+ }
967
+ }
968
+ return $ this ->notFound ();
969
+ }
943
970
$ reflection = is_array ($ execute ) ? new \ReflectionMethod ($ execute [0 ], $ execute [1 ]) : new \ReflectionFunction ($ execute );
944
971
ob_start (function ($ tmp ) {
945
972
$ this ->content .= $ tmp ;
@@ -1287,4 +1314,35 @@ private function confirm_ip_addresses($ip): array
1287
1314
return $ res ;
1288
1315
}
1289
1316
1317
+ private function notFound (): ResponseInterface
1318
+ {
1319
+ $ this ->response = $ this ->response ->withStatus (404 );
1320
+ if (empty ($ this ->error_404 ['execute ' ])){
1321
+ throw new PageNotFoundException ('Error 404 : Page Not Found ' );
1322
+ }
1323
+ if (!\defined ("INITPHP_ROUTER_CURRENT_ARGUMENTS " )) {
1324
+ \define ('INITPHP_ROUTER_CURRENT_ARGUMENTS ' , $ this ->error_404 ['options ' ]['arguments ' ]);
1325
+ }
1326
+ if (\is_callable ($ this ->error_404 ['execute ' ])){
1327
+ if (!\defined ("INITPHP_ROUTER_CURRENT_CONTROLLER " )) {
1328
+ \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , '__CALLABLE__ ' );
1329
+ }
1330
+ if (!\defined ("INITPHP_ROUTER_CURRENT_METHOD " )) {
1331
+ \define ('INITPHP_ROUTER_CURRENT_METHOD ' , '' );
1332
+ }
1333
+ return $ this ->response = $ this ->execute ($ this ->error_404 ['execute ' ], $ this ->error_404 ['options ' ]['arguments ' ]);
1334
+ }
1335
+ $ parse = $ this ->getControllerMethod ($ this ->error_404 ['execute ' ], $ this ->error_404 ['options ' ]);
1336
+ $ parse ['controller ' ] = $ this ->controllerFind ($ parse ['controller ' ]);
1337
+ $ controller = $ this ->getClassContainer (new \ReflectionClass ($ parse ['controller ' ]));
1338
+ if (!\defined ("INITPHP_ROUTER_CURRENT_CONTROLLER " )) {
1339
+ \define ('INITPHP_ROUTER_CURRENT_CONTROLLER ' , \get_class ($ controller ));
1340
+ }
1341
+ if (!\defined ("INITPHP_ROUTER_CURRENT_METHOD " )) {
1342
+ \define ('INITPHP_ROUTER_CURRENT_METHOD ' , $ parse ['method ' ]);
1343
+ }
1344
+
1345
+ return $ this ->response = $ this ->execute ([$ controller , $ parse ['method ' ]], $ this ->error_404 ['options ' ]['arguments ' ]);
1346
+ }
1347
+
1290
1348
}
0 commit comments