Route.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <?php
  2. namespace Goodquestiondev;
  3. use Illuminate\Support\Str;
  4. use Goodquestiondev\Resource;
  5. use Goodquestiondev\Controllers\Controller;
  6. use Symfony\Component\HttpFoundation\Request;
  7. class Route
  8. {
  9. /**
  10. * The Application routers
  11. *
  12. * @var array
  13. */
  14. public $resources = [];
  15. /**
  16. * The Application instance.
  17. *
  18. * @var self
  19. */
  20. private static $instance = null;
  21. /**
  22. * The default actions for a resourceful controller.
  23. *
  24. * @var array
  25. */
  26. public $resourceDefaults = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy'];
  27. /**
  28. * The verbs used in the resource URIs.
  29. *
  30. * @var array
  31. */
  32. public static $verbs = [
  33. 'create',
  34. 'edit',
  35. ];
  36. /**
  37. * The possible resource keys
  38. *
  39. * @var array
  40. */
  41. public $resourceKeys = [];
  42. /**
  43. * The resource strings
  44. *
  45. * @var array
  46. */
  47. public $resourceStrings = [];
  48. /**
  49. * Create a new simple resource instance following singleton pattern
  50. *
  51. * @return self
  52. */
  53. public static function getInstance()
  54. {
  55. if (self::$instance == null) {
  56. self::$instance = new self();
  57. }
  58. return self::$instance;
  59. }
  60. /**
  61. * Register resource
  62. *
  63. * @param string $uri The uri string
  64. *
  65. * @return void
  66. */
  67. public static function resource(string $uri)
  68. {
  69. $route = self::getInstance();
  70. $resourceKeys = array_merge(explode(".", $uri), $route->resourceKeys);
  71. $route->resourceKeys = array_unique($resourceKeys);
  72. $route->resourceStrings[] = $uri;
  73. $route->resources[$uri] = new Resource($uri);
  74. }
  75. /**
  76. * Redirects the user to the correct controller and method based on the path
  77. *
  78. * @param Request $request The request data content
  79. *
  80. * @return Resource
  81. */
  82. public static function getResource($request)
  83. {
  84. $route = self::getInstance();
  85. $uriInfo = $route->getUriInfo($request->getPathInfo());
  86. foreach ($route->resources as $resource) {
  87. if (in_array($uriInfo['uri'], $resource->uriList)) {
  88. $route->callController($resource, $request, $uriInfo);
  89. }
  90. };
  91. }
  92. /**
  93. * Get URI and their params
  94. * E.q for path /users/bob/posts/999
  95. * E.q: ['uri' => 'users/{key}posts/{key}', 'params' ['users' => 'bob', 'posts' => 999]]
  96. *
  97. * @param string $path The request path
  98. *
  99. * @return arrray
  100. */
  101. public function getUriInfo($path)
  102. {
  103. $path = Str::of($path)->ltrim('/')->rtrim('/');
  104. $parts = explode("/", $path);
  105. $params = [];
  106. $uri = '';
  107. foreach ($parts as $index => $part) {
  108. $isResourceString = in_array($part, $this->resourceKeys);
  109. if ($index === 0 && ! $isResourceString) {
  110. throw new \Exception('Bad Url');
  111. }
  112. $isResourceVerb = in_array($part, self::$verbs);
  113. if ($isResourceVerb) {
  114. $uri .= $part;
  115. break;
  116. }
  117. if ($isResourceString) {
  118. $params[$part] = '';
  119. $uri .= "$part/";
  120. } else {
  121. $params[array_key_last($params)] = $part;
  122. $singular = Str::singular(array_key_last($params));
  123. $uri .= "{{$singular}}/";
  124. }
  125. }
  126. foreach ($params as $key => $value) {
  127. unset($params[$key]);
  128. $params[Str::singular($key)] = $value;
  129. }
  130. return [
  131. 'uri' => (string) Str::of($uri)->rtrim('/'),
  132. 'params' => $params
  133. ];
  134. }
  135. /**
  136. * Find controller and instantiate it
  137. *
  138. * @param Resource $resource The Resource verb
  139. * @param Request $request The request
  140. * @param array $uriInfo The url info
  141. *
  142. * @return void
  143. */
  144. public function callController(Resource $resource, Request $request, array $uriInfo)
  145. {
  146. $app = Application::getInstance();
  147. try {
  148. $controllerClassName = $app->controllerUris[$resource->uri];
  149. $controllerName = "Goodquestiondev\\Controllers\\{$controllerClassName}";
  150. $controller = new $controllerName;
  151. } catch (\Exception $e) {
  152. throw new \Exception('Error getting Controller');
  153. }
  154. $this->callAction($controller, $resource, $request, $uriInfo);
  155. }
  156. /**
  157. * Call the Controller method
  158. *
  159. * @param Controller $controller The controller
  160. * @param Resource $resource The Resource verb
  161. * @param Request $request The request
  162. *
  163. * @return void
  164. */
  165. public function callAction(Controller $controller, Resource $resource, Request $request, array $uriInfo)
  166. {
  167. $path = $request->getPathInfo();
  168. switch ($request->getMethod()) {
  169. case 'GET':
  170. if (Str::contains($path, 'create')) {
  171. $controller->create();
  172. break;
  173. }
  174. if (Str::contains($path, 'edit')) {
  175. $controller->edit($uriInfo['params']);
  176. break;
  177. }
  178. if (Str::contains($uriInfo['uri'], '{')) {
  179. $controller->show($uriInfo['params']);
  180. break;
  181. }
  182. $controller->index();
  183. break;
  184. case 'POST':
  185. $controller->store($request);
  186. break;
  187. case 'PUT':
  188. case 'PATCH':
  189. $controller->update($request, $uriInfo['params']);
  190. break;
  191. case 'DELETE':
  192. $controller->destroy($uriInfo['params']);
  193. break;
  194. default:
  195. $controller->error($request);
  196. }
  197. }
  198. }