ActionController.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * MINZ - Copyright 2011 Marien Fressinaud
  5. * Sous licence AGPL3 <http://www.gnu.org/licenses/>
  6. */
  7. /**
  8. * The Minz_ActionController class is a controller in the MVC paradigm
  9. */
  10. abstract class Minz_ActionController {
  11. /** @var array<string,string> */
  12. private static array $csp_default = [
  13. 'default-src' => "'self'",
  14. ];
  15. /** @var array<string,string> */
  16. private array $csp_policies;
  17. /** @var Minz_View */
  18. protected $view;
  19. /**
  20. * Gives the possibility to override the default view model type.
  21. * @var class-string
  22. * @deprecated Use constructor with view type instead
  23. */
  24. public static string $defaultViewType = Minz_View::class;
  25. /**
  26. * @phpstan-param class-string|'' $viewType
  27. * @param string $viewType Name of the class (inheriting from Minz_View) to use for the view model
  28. */
  29. public function __construct(string $viewType = '') {
  30. $this->csp_policies = self::$csp_default;
  31. $view = null;
  32. if ($viewType !== '' && class_exists($viewType)) {
  33. $view = new $viewType();
  34. if (!($view instanceof Minz_View)) {
  35. $view = null;
  36. }
  37. }
  38. if ($view === null && class_exists(self::$defaultViewType)) {
  39. $view = new self::$defaultViewType();
  40. if (!($view instanceof Minz_View)) {
  41. $view = null;
  42. }
  43. }
  44. $this->view = $view ?? new Minz_View();
  45. $view_path = Minz_Request::controllerName() . '/' . Minz_Request::actionName() . '.phtml';
  46. $this->view->_path($view_path);
  47. $this->view->attributeParams();
  48. }
  49. /**
  50. * Getteur
  51. */
  52. public function view(): Minz_View {
  53. return $this->view;
  54. }
  55. /**
  56. * Set default CSP policies.
  57. * @param array<string,string> $policies An array where keys are directives and values are sources.
  58. */
  59. public static function _defaultCsp(array $policies): void {
  60. if (!isset($policies['default-src'])) {
  61. Minz_Log::warning('Default CSP policy is not declared', ADMIN_LOG);
  62. }
  63. self::$csp_default = $policies;
  64. }
  65. /**
  66. * Set CSP policies.
  67. *
  68. * A default-src directive should always be given.
  69. *
  70. * References:
  71. * - https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
  72. * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src
  73. *
  74. * @param array<string,string> $policies An array where keys are directives and values are sources.
  75. */
  76. protected function _csp(array $policies): void {
  77. if (!isset($policies['default-src'])) {
  78. $action = Minz_Request::controllerName() . '#' . Minz_Request::actionName();
  79. Minz_Log::warning(
  80. "Default CSP policy is not declared for action {$action}.",
  81. ADMIN_LOG
  82. );
  83. }
  84. $this->csp_policies = $policies;
  85. }
  86. /**
  87. * Send HTTP Content-Security-Policy header based on declared policies.
  88. */
  89. public function declareCspHeader(): void {
  90. $policies = [];
  91. foreach (Minz_ExtensionManager::listExtensions(true) as $extension) {
  92. $extension->amendCsp($this->csp_policies);
  93. }
  94. foreach ($this->csp_policies as $directive => $sources) {
  95. $policies[] = $directive . ' ' . $sources;
  96. }
  97. header('Content-Security-Policy: ' . implode('; ', $policies));
  98. }
  99. /**
  100. * Méthodes à redéfinir (ou non) par héritage
  101. * firstAction est la première méthode exécutée par le Dispatcher
  102. * lastAction est la dernière
  103. */
  104. public function init(): void { }
  105. public function firstAction(): void { }
  106. public function lastAction(): void { }
  107. }