api de gestion de ticket, basé sur php-crud-api. Le but est de décorrélé les outils de gestion des données, afin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SanitationMiddleware.php 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace Tqdev\PhpCrudApi\Middleware;
  3. use Psr\Http\Message\ResponseInterface;
  4. use Psr\Http\Message\ServerRequestInterface;
  5. use Psr\Http\Server\RequestHandlerInterface;
  6. use Tqdev\PhpCrudApi\Column\Reflection\ReflectedTable;
  7. use Tqdev\PhpCrudApi\Column\Reflection\ReflectedColumn;
  8. use Tqdev\PhpCrudApi\Column\ReflectionService;
  9. use Tqdev\PhpCrudApi\Controller\Responder;
  10. use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
  11. use Tqdev\PhpCrudApi\Middleware\Router\Router;
  12. use Tqdev\PhpCrudApi\RequestUtils;
  13. class SanitationMiddleware extends Middleware
  14. {
  15. private $reflection;
  16. public function __construct(Router $router, Responder $responder, array $properties, ReflectionService $reflection)
  17. {
  18. parent::__construct($router, $responder, $properties);
  19. $this->reflection = $reflection;
  20. }
  21. private function callHandler($handler, $record, string $operation, ReflectedTable $table) /*: object */
  22. {
  23. $context = (array) $record;
  24. $tableName = $table->getName();
  25. foreach ($context as $columnName => &$value) {
  26. if ($table->hasColumn($columnName)) {
  27. $column = $table->getColumn($columnName);
  28. $value = call_user_func($handler, $operation, $tableName, $column->serialize(), $value);
  29. $value = $this->sanitizeType($table, $column, $value);
  30. }
  31. }
  32. return (object) $context;
  33. }
  34. private function sanitizeType(ReflectedTable $table, ReflectedColumn $column, $value)
  35. {
  36. $tables = $this->getArrayProperty('tables', 'all');
  37. $types = $this->getArrayProperty('types', 'all');
  38. if (
  39. (in_array('all', $tables) || in_array($table->getName(), $tables)) &&
  40. (in_array('all', $types) || in_array($column->getType(), $types))
  41. ) {
  42. if (is_null($value)) {
  43. return $value;
  44. }
  45. if (is_string($value)) {
  46. $newValue = null;
  47. switch ($column->getType()) {
  48. case 'integer':
  49. case 'bigint':
  50. $newValue = filter_var(trim($value), FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
  51. break;
  52. case 'decimal':
  53. $newValue = filter_var(trim($value), FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE);
  54. if (is_float($newValue)) {
  55. $newValue = number_format($newValue, $column->getScale(), '.', '');
  56. }
  57. break;
  58. case 'float':
  59. case 'double':
  60. $newValue = filter_var(trim($value), FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE);
  61. break;
  62. case 'boolean':
  63. $newValue = filter_var(trim($value), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
  64. break;
  65. case 'date':
  66. $time = strtotime(trim($value));
  67. if ($time !== false) {
  68. $newValue = date('Y-m-d', $time);
  69. }
  70. break;
  71. case 'time':
  72. $time = strtotime(trim($value));
  73. if ($time !== false) {
  74. $newValue = date('H:i:s', $time);
  75. }
  76. break;
  77. case 'timestamp':
  78. $time = strtotime(trim($value));
  79. if ($time !== false) {
  80. $newValue = date('Y-m-d H:i:s', $time);
  81. }
  82. break;
  83. case 'blob':
  84. case 'varbinary':
  85. // allow base64url format
  86. $newValue = strtr(trim($value), '-_', '+/');
  87. break;
  88. case 'clob':
  89. case 'varchar':
  90. $newValue = $value;
  91. break;
  92. case 'geometry':
  93. $newValue = trim($value);
  94. break;
  95. }
  96. if (!is_null($newValue)) {
  97. $value = $newValue;
  98. }
  99. } else {
  100. switch ($column->getType()) {
  101. case 'integer':
  102. case 'bigint':
  103. if (is_float($value)) {
  104. $value = (int) round($value);
  105. }
  106. break;
  107. case 'decimal':
  108. if (is_float($value) || is_int($value)) {
  109. $value = number_format((float) $value, $column->getScale(), '.', '');
  110. }
  111. break;
  112. }
  113. }
  114. // post process
  115. }
  116. return $value;
  117. }
  118. public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
  119. {
  120. $operation = RequestUtils::getOperation($request);
  121. if (in_array($operation, ['create', 'update', 'increment'])) {
  122. $tableName = RequestUtils::getPathSegment($request, 2);
  123. if ($this->reflection->hasTable($tableName)) {
  124. $record = $request->getParsedBody();
  125. if ($record !== null) {
  126. $handler = $this->getProperty('handler', '');
  127. if ($handler !== '') {
  128. $table = $this->reflection->getTable($tableName);
  129. if (is_array($record)) {
  130. foreach ($record as &$r) {
  131. $r = $this->callHandler($handler, $r, $operation, $table);
  132. }
  133. } else {
  134. $record = $this->callHandler($handler, $record, $operation, $table);
  135. }
  136. $request = $request->withParsedBody($record);
  137. }
  138. }
  139. }
  140. }
  141. return $next->handle($request);
  142. }
  143. }