ControllerFactory.php 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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\Network\Request;
  18. use Cake\Network\Response;
  19. use Cake\Routing\Exception\MissingControllerException;
  20. use Cake\Utility\Inflector;
  21. use ReflectionClass;
  22. /**
  23. * Factory method for building controllers from request/response pairs.
  24. */
  25. class ControllerFactory
  26. {
  27. /**
  28. * Create a controller for a given request/response
  29. *
  30. * @param \Cake\Network\Request $request The request to build a controller for.
  31. * @param \Cake\Network\Response $response The response to use.
  32. * @return \Cake\Controller\Controller
  33. */
  34. public function create(Request $request, Response $response)
  35. {
  36. $pluginPath = $controller = null;
  37. $namespace = 'Controller';
  38. if (isset($request->params['plugin'])) {
  39. $pluginPath = $request->params['plugin'] . '.';
  40. }
  41. if (isset($request->params['controller'])) {
  42. $controller = $request->params['controller'];
  43. }
  44. if (isset($request->params['prefix'])) {
  45. if (strpos($request->params['prefix'], '/') === false) {
  46. $namespace .= '/' . Inflector::camelize($request->params['prefix']);
  47. } else {
  48. $prefixes = array_map(
  49. 'Cake\Utility\Inflector::camelize',
  50. explode('/', $request->params['prefix'])
  51. );
  52. $namespace .= '/' . implode('/', $prefixes);
  53. }
  54. }
  55. $firstChar = substr($controller, 0, 1);
  56. // Disallow plugin short forms, / and \\ from
  57. // controller names as they allow direct references to
  58. // be created.
  59. if (strpos($controller, '\\') !== false ||
  60. strpos($controller, '/') !== false ||
  61. strpos($controller, '.') !== false ||
  62. $firstChar === strtolower($firstChar)
  63. ) {
  64. return $this->missingController($request);
  65. }
  66. $className = App::classname($pluginPath . $controller, $namespace, 'Controller');
  67. if (!$className) {
  68. return $this->missingController($request);
  69. }
  70. $reflection = new ReflectionClass($className);
  71. if ($reflection->isAbstract() || $reflection->isInterface()) {
  72. return $this->missingController($request);
  73. }
  74. return $reflection->newInstance($request, $response, $controller);
  75. }
  76. /**
  77. * Throws an exception when a controller is missing.
  78. *
  79. * @param \Cake\Network\Request $request The request.
  80. * @throws \Cake\Routing\Exception\MissingControllerException
  81. * @return void
  82. */
  83. protected function missingController($request)
  84. {
  85. throw new MissingControllerException([
  86. 'class' => $request->param('controller'),
  87. 'plugin' => $request->param('plugin'),
  88. 'prefix' => $request->param('prefix'),
  89. '_ext' => $request->param('_ext')
  90. ]);
  91. }
  92. }