ControllerFactory.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  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://cakephp.org CakePHP(tm) Project
  12. * @since 3.3.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Http;
  16. use Cake\Core\App;
  17. use Cake\Routing\Exception\MissingControllerException;
  18. use Cake\Utility\Inflector;
  19. use ReflectionClass;
  20. /**
  21. * Factory method for building controllers from request/response pairs.
  22. */
  23. class ControllerFactory
  24. {
  25. /**
  26. * Create a controller for a given request/response
  27. *
  28. * @param \Cake\Http\ServerRequest $request The request to build a controller for.
  29. * @param \Cake\Http\Response $response The response to use.
  30. * @return \Cake\Controller\Controller
  31. */
  32. public function create(ServerRequest $request, Response $response)
  33. {
  34. $controller = null;
  35. if ($request->getParam('controller')) {
  36. $controller = $request->getParam('controller');
  37. }
  38. $className = $this->getControllerClass($request, $controller);
  39. if (!$className) {
  40. $this->missingController($request);
  41. }
  42. $reflection = new ReflectionClass($className);
  43. if ($reflection->isAbstract() || $reflection->isInterface()) {
  44. $this->missingController($request);
  45. }
  46. return $reflection->newInstance($request, $response, $controller);
  47. }
  48. /**
  49. * Determine the controller class name based on current request and controller param
  50. *
  51. * @param \Cake\Http\ServerRequest $request The request to build a controller for.
  52. * @param string|null $controllerName The controller name present in the request params
  53. * @return string|null
  54. */
  55. public function getControllerClass(ServerRequest $request, $controllerName = null)
  56. {
  57. $pluginPath = null;
  58. $controller = $controllerName;
  59. $namespace = 'Controller';
  60. if (!$controller && $request->getParam('controller')) {
  61. $controller = $request->getParam('controller');
  62. }
  63. if ($request->getParam('plugin')) {
  64. $pluginPath = $request->getParam('plugin') . '.';
  65. }
  66. if ($request->getParam('prefix')) {
  67. if (strpos($request->getParam('prefix'), '/') === false) {
  68. $namespace .= '/' . Inflector::camelize($request->getParam('prefix'));
  69. } else {
  70. $prefixes = array_map(
  71. 'Cake\Utility\Inflector::camelize',
  72. explode('/', $request->getParam('prefix'))
  73. );
  74. $namespace .= '/' . implode('/', $prefixes);
  75. }
  76. }
  77. $firstChar = substr($controller, 0, 1);
  78. // Disallow plugin short forms, / and \\ from
  79. // controller names as they allow direct references to
  80. // be created.
  81. if (strpos($controller, '\\') !== false ||
  82. strpos($controller, '/') !== false ||
  83. strpos($controller, '.') !== false ||
  84. $firstChar === strtolower($firstChar)
  85. ) {
  86. $this->missingController($request);
  87. }
  88. return App::className($pluginPath . $controller, $namespace, 'Controller') ?: null;
  89. }
  90. /**
  91. * Throws an exception when a controller is missing.
  92. *
  93. * @param \Cake\Http\ServerRequest $request The request.
  94. * @throws \Cake\Routing\Exception\MissingControllerException
  95. * @return void
  96. */
  97. protected function missingController($request)
  98. {
  99. throw new MissingControllerException([
  100. 'class' => $request->getParam('controller'),
  101. 'plugin' => $request->getParam('plugin'),
  102. 'prefix' => $request->getParam('prefix'),
  103. '_ext' => $request->getParam('_ext')
  104. ]);
  105. }
  106. }