Просмотр файла app/Services/Validator.php

Размер файла: 27.1Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace App\Services;
  6.  
  7. use BadMethodCallException;
  8. use Countable;
  9. use Psr\Http\Message\UploadedFileInterface;
  10.  
  11. /**
  12. * Class Validation data
  13. *
  14. * @license Code and contributions have MIT License
  15. * @link https://visavi.net
  16. * @author Alexander Grigorev <admin@visavi.net>
  17. *
  18. * @method $this required(array|string $key, ?string $label = null)
  19. * @method $this length(array|string $key, int $min, int $max, ?string $label = null)
  20. * @method $this minLength(array|string $key, int $length, ?string $label = null)
  21. * @method $this maxLength(array|string $key, int $length, ?string $label = null)
  22. * @method $this range(array|string $key, int|float $min, int|float $max, ?string $label = null)
  23. * @method $this gt(array|string $key, int|float $num, ?string $label = null)
  24. * @method $this gte(array|string $key, int|float $num, ?string $label = null)
  25. * @method $this lt(array|string $key, int|float $num, ?string $label = null)
  26. * @method $this lte(array|string $key, int|float $num, ?string $label = null)
  27. * @method $this same(string $key, mixed $value, string $label = null)
  28. * @method $this notSame(string $key, mixed $value, string $label = null)
  29. * @method $this equal(string $key1, string $key2, ?string $label = null)
  30. * @method $this notEqual(string $key1, string $key2, ?string $label = null)
  31. * @method $this empty(array|string $key, ?string $label = null)
  32. * @method $this notEmpty(array|string $key, ?string $label = null)
  33. * @method $this in(array|string $key, array $haystack, ?string $label = null)
  34. * @method $this notIn(array|string $key, array $haystack, ?string $label = null)
  35. * @method $this regex(array|string $key, string $pattern, ?string $label = null)
  36. * @method $this url(array|string $key, ?string $label = null)
  37. * @method $this email(array|string $key, ?string $label = null)
  38. * @method $this ip(array|string $key, ?string $label = null)
  39. * @method $this phone(array|string $key, ?string $label = null)
  40. * @method $this boolean(array|string $key, ?string $label = null)
  41. * @method $this file(string $key, array $rules)
  42. * @method $this add(string $key, callable $callable, string $label)
  43. * @method $this custom(bool $compare, array|string $label)
  44. *
  45. */
  46. class Validator
  47. {
  48. private array $rules;
  49. private array $input;
  50. private array $errors = [];
  51.  
  52. private array $data = [
  53. 'required' => 'Поле %s является обязательным',
  54. 'length' => [
  55. 'between' => 'Количество символов в поле %s должно быть от %d до %d',
  56. 'min' => 'Количество символов в поле %s должно быть не меньше %d',
  57. 'max' => 'Количество символов в поле %s должно быть не больше %d',
  58. ],
  59. 'range' => 'Значение поля %s должно быть между %d и %d',
  60. 'gt' => 'Значение поля %s должно быть больше %d',
  61. 'gte' => 'Значение поля %s должно быть больше или равно %d',
  62. 'lt' => 'Значение поля %s должно быть меньше %d',
  63. 'lte' => 'Значение поля %s должно быть меньше или равно %d',
  64.  
  65. 'equal' => 'Значения полей %s и %s должны совпадать',
  66. 'notEqual' => 'Значения полей %s и %s должны различаться',
  67. 'same' => 'Значения поля %s должно быть равным %s',
  68. 'notSame' => 'Значения поля %s должно быть не равным %s',
  69.  
  70. 'empty' => 'Значение поля %s должно быть пустым',
  71. 'notEmpty' => 'Значение поля %s не должно быть пустым',
  72. 'in' => 'Значение поля %s ошибочно',
  73. 'notIn' => 'Значение поля %s ошибочно',
  74. 'regex' => 'Значение поля %s имеет ошибочный формат',
  75. 'url' => 'Значение поля %s содержит недействительный URL',
  76. 'email' => 'Значение поля %s содержит недействительный email',
  77. 'ip' => 'Значение поля %s содержит недействительный IP-адрес',
  78. 'phone' => 'Значение поля %s содержит недействительный номер телефона',
  79. 'file' => [
  80. 'error' => 'Ошибка загрузки файла',
  81. 'extension' => 'Поле %s должно быть файлом одного из следующих типов: %s',
  82. 'size_max' => 'Размер файла в поле %s должен быть не больше %s',
  83. 'weight_min' => 'Размер изображения в поле %s не должен быть меньше %s px',
  84. 'weight_max' => 'Размер изображения в поле %s не должен быть больше %s px',
  85. 'weight_empty' => 'Размер изображения в поле %s слишком маленький!',
  86. ],
  87. 'boolean' => 'Поле %s должно быть логического типа',
  88. ];
  89.  
  90. private array $images = ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'];
  91.  
  92. /**
  93. * Call
  94. *
  95. * @param string $name
  96. * @param array $arguments
  97. *
  98. * @return $this
  99. */
  100. public function __call(string $name, array $arguments): self
  101. {
  102. $keys = (array) $arguments[0];
  103.  
  104. foreach ($keys as $key) {
  105. $arguments[0] = $key;
  106. $this->rules[$key][$name] = $arguments;
  107. }
  108.  
  109. return $this;
  110. }
  111.  
  112. /**
  113. * Возвращает успешность валидации
  114. *
  115. * @param array $input
  116. *
  117. * @return bool
  118. */
  119. public function isValid(array $input): bool
  120. {
  121. $this->input = $input;
  122.  
  123. foreach ($this->rules as $rules) {
  124. foreach ($rules as $rule => $params) {
  125. $method = $rule . 'Rule';
  126.  
  127. if (! method_exists($this, $method)) {
  128. throw new BadMethodCallException(sprintf('%s() called undefined method. Method "%s" does not exist', __METHOD__, $rule));
  129. }
  130.  
  131. $this->$method(...$params);
  132. }
  133. }
  134.  
  135. return empty($this->errors);
  136. }
  137.  
  138. /**
  139. * Required
  140. *
  141. * @param array|string $key
  142. * @param string|null $label
  143. *
  144. * @return $this
  145. */
  146. private function requiredRule(array|string $key, ?string $label = null): self
  147. {
  148. $key = (array) $key;
  149.  
  150. foreach ($key as $field) {
  151. $input = $this->getInput($field);
  152.  
  153. if ($this->blank($input)) {
  154. $this->addError($field, sprintf($label ?? $this->data['required'], $field));
  155. }
  156. }
  157.  
  158. return $this;
  159. }
  160.  
  161. /**
  162. * Length
  163. *
  164. * @param array|string $key
  165. * @param int $min
  166. * @param int $max
  167. * @param string|null $label
  168. *
  169. * @return $this
  170. */
  171. private function lengthRule(array|string $key, int $min, int $max, ?string $label = null): self
  172. {
  173. $key = (array) $key;
  174.  
  175. foreach ($key as $field) {
  176. $input = $this->getInput($field);
  177.  
  178. if (! $this->isRequired($field) && $this->blank($input)) {
  179. return $this;
  180. }
  181.  
  182. if (mb_strlen((string) $input, 'UTF-8') < $min || mb_strlen((string) $input, 'UTF-8') > $max) {
  183. $this->addError($field, sprintf($label ?? $this->data['length']['between'], $field, $min, $max));
  184. }
  185. }
  186.  
  187. return $this;
  188. }
  189.  
  190. /**
  191. * Min length
  192. *
  193. * @param array|string $key
  194. * @param int $length
  195. * @param string|null $label
  196. *
  197. * @return $this
  198. */
  199. private function minLengthRule(array|string $key, int $length, ?string $label = null): self
  200. {
  201. $key = (array) $key;
  202.  
  203. foreach ($key as $field) {
  204. $input = $this->getInput($field);
  205.  
  206. if (! $this->isRequired($field) && $this->blank($input)) {
  207. return $this;
  208. }
  209.  
  210. if (mb_strlen((string) $input, 'UTF-8') < $length) {
  211. $this->addError($field, sprintf($label ?? $this->data['length']['min'], $field, $length));
  212. }
  213. }
  214.  
  215. return $this;
  216. }
  217.  
  218. /**
  219. * Max length
  220. *
  221. * @param array|string $key
  222. * @param int $length
  223. * @param string|null $label
  224. *
  225. * @return $this
  226. */
  227. private function maxLengthRule(array|string $key, int $length, ?string $label = null): self
  228. {
  229. $key = (array) $key;
  230.  
  231. foreach ($key as $field) {
  232. $input = $this->getInput($field);
  233.  
  234. if (! $this->isRequired($field) && $this->blank($input)) {
  235. return $this;
  236. }
  237.  
  238. if (mb_strlen((string) $input, 'UTF-8') > $length) {
  239. $this->addError($field, sprintf($label ?? $this->data['length']['max'], $field, $length));
  240. }
  241. }
  242.  
  243. return $this;
  244. }
  245.  
  246. /**
  247. * Range
  248. *
  249. * @param array|string $key
  250. * @param int|float $min
  251. * @param int|float $max
  252. * @param string|null $label
  253. *
  254. * @return $this
  255. */
  256. private function rangeRule(array|string $key, int|float $min, int|float $max, ?string $label = null): self
  257. {
  258. $key = (array) $key;
  259.  
  260. foreach ($key as $field) {
  261. $input = $this->getInput($field);
  262.  
  263. if (! $this->isRequired($field) && $this->blank($input)) {
  264. return $this;
  265. }
  266.  
  267. if ($input < $min || $input > $max) {
  268. $this->addError($field, sprintf($label ?? $this->data['range'], $field, $min, $max));
  269. }
  270. }
  271.  
  272. return $this;
  273. }
  274.  
  275. /**
  276. * Greater than
  277. *
  278. * @param array|string $key
  279. * @param int|float $num
  280. * @param string|null $label
  281. *
  282. * @return $this
  283. */
  284. private function gtRule(array|string $key, int|float $num, ?string $label = null): self
  285. {
  286. $key = (array) $key;
  287.  
  288. foreach ($key as $field) {
  289. $input = $this->getInput($field);
  290.  
  291. if (! $this->isRequired($field) && $this->blank($input)) {
  292. return $this;
  293. }
  294.  
  295. if ($input <= $num) {
  296. $this->addError($field, sprintf($label ?? $this->data['gt'], $field, $num));
  297. }
  298. }
  299.  
  300. return $this;
  301. }
  302.  
  303. /**
  304. * Greater than or equal
  305. *
  306. * @param array|string $key
  307. * @param int|float $num
  308. * @param string|null $label
  309. *
  310. * @return $this
  311. */
  312. private function gteRule(array|string $key, int|float $num, ?string $label = null): self
  313. {
  314. $key = (array) $key;
  315.  
  316. foreach ($key as $field) {
  317. $input = $this->getInput($field);
  318.  
  319. if (! $this->isRequired($field) && $this->blank($input)) {
  320. return $this;
  321. }
  322.  
  323. if ($input < $num) {
  324. $this->addError($field, sprintf($label ?? $this->data['gte'], $field, $num));
  325. }
  326. }
  327.  
  328. return $this;
  329. }
  330.  
  331. /**
  332. * Less than
  333. *
  334. * @param array|string $key
  335. * @param int|float $num
  336. * @param string|null $label
  337. *
  338. * @return $this
  339. */
  340. private function ltRule(array|string $key, int|float $num, ?string $label = null): self
  341. {
  342. $key = (array) $key;
  343.  
  344. foreach ($key as $field) {
  345. $input = $this->getInput($field);
  346.  
  347. if (! $this->isRequired($field) && $this->blank($input)) {
  348. return $this;
  349. }
  350.  
  351. if ($input >= $num) {
  352. $this->addError($field, sprintf($label ?? $this->data['lt'], $field, $num));
  353. }
  354. }
  355.  
  356. return $this;
  357. }
  358.  
  359. /**
  360. * Less than or equal
  361. *
  362. * @param array|string $key
  363. * @param int|float $num
  364. * @param string|null $label
  365. *
  366. * @return $this
  367. */
  368. private function lteRule(array|string $key, int|float $num, ?string $label = null): self
  369. {
  370. $key = (array) $key;
  371.  
  372. foreach ($key as $field) {
  373. $input = $this->getInput($field);
  374.  
  375. if (! $this->isRequired($field) && $this->blank($input)) {
  376. return $this;
  377. }
  378.  
  379. if ($input > $num) {
  380. $this->addError($field, sprintf($label ?? $this->data['lte'], $field, $num));
  381. }
  382. }
  383.  
  384. return $this;
  385. }
  386.  
  387. /**
  388. * Same rule
  389. *
  390. * @param string $key
  391. * @param mixed $value
  392. * @param string|null $label
  393. *
  394. * @return $this
  395. */
  396. private function sameRule(string $key, mixed $value, ?string $label = null): self
  397. {
  398. $input = $this->getInput($key);
  399.  
  400. if (! $this->isRequired($key) && $this->blank($input)) {
  401. return $this;
  402. }
  403.  
  404. if ($input !== $value) {
  405. $this->addError($key, sprintf($label ?? $this->data['same'], $key, $value));
  406. }
  407.  
  408. return $this;
  409. }
  410.  
  411. /**
  412. * Not same rule
  413. *
  414. * @param string $key
  415. * @param mixed $value
  416. * @param string|null $label
  417. *
  418. * @return $this
  419. */
  420. private function notSameRule(string $key, mixed $value, ?string $label = null): self
  421. {
  422. $input = $this->getInput($key);
  423.  
  424. if (! $this->isRequired($key) && $this->blank($input)) {
  425. return $this;
  426. }
  427.  
  428. if ($input === $value) {
  429. $this->addError($key, sprintf($label ?? $this->data['notSame'], $key, $value));
  430. }
  431.  
  432. return $this;
  433. }
  434.  
  435. /**
  436. * Equal
  437. *
  438. * @param string $key1
  439. * @param string $key2
  440. * @param string|null $label
  441. *
  442. * @return $this
  443. */
  444. private function equalRule(string $key1, string $key2, ?string $label = null): self
  445. {
  446. $input1 = $this->getInput($key1);
  447. $input2 = $this->getInput($key2);
  448.  
  449. if (! $this->isRequired($key1) && $this->blank($input1)) {
  450. return $this;
  451. }
  452.  
  453. if ($input1 !== $input2) {
  454. $this->addError($key1, sprintf($label ?? $this->data['equal'], $key1, $key2));
  455. }
  456.  
  457. return $this;
  458. }
  459.  
  460. /**
  461. * Not equal
  462. *
  463. * @param string $key1
  464. * @param string $key2
  465. * @param string|null $label
  466. *
  467. * @return $this
  468. */
  469. private function notEqualRule(string $key1, string $key2, ?string $label = null): self
  470. {
  471. $input1 = $this->getInput($key1);
  472. $input2 = $this->getInput($key2);
  473.  
  474. if (! $this->isRequired($key1) && $this->blank($input1)) {
  475. return $this;
  476. }
  477.  
  478. if ($input1 === $input2) {
  479. $this->addError($key1, sprintf($label ?? $this->data['notEqual'], $key1, $key2));
  480. }
  481.  
  482. return $this;
  483. }
  484.  
  485. /**
  486. * Empty
  487. *
  488. * @param array|string $key
  489. * @param string|null $label
  490. *
  491. * @return $this
  492. */
  493. private function emptyRule(array|string $key, ?string $label = null): self
  494. {
  495. $key = (array) $key;
  496.  
  497. foreach ($key as $field) {
  498. $input = $this->getInput($field);
  499.  
  500. if (! $this->isRequired($field) && $this->blank($input)) {
  501. return $this;
  502. }
  503.  
  504. if (! $this->blank($input)) {
  505. $this->addError($field, sprintf($label ?? $this->data['empty'], $field));
  506. }
  507. }
  508.  
  509. return $this;
  510. }
  511.  
  512. /**
  513. * Not empty
  514. *
  515. * @param array|string $key
  516. * @param string|null $label
  517. *
  518. * @return $this
  519. */
  520. private function notEmptyRule(array|string $key, ?string $label = null): self
  521. {
  522. $key = (array) $key;
  523.  
  524. foreach ($key as $field) {
  525. $input = $this->getInput($field);
  526.  
  527. if (! $this->isRequired($field) && $this->blank($input)) {
  528. return $this;
  529. }
  530.  
  531. if ($this->blank($input)) {
  532. $this->addError($field, sprintf($label ?? $this->data['notEmpty'], $field));
  533. }
  534. }
  535.  
  536. return $this;
  537. }
  538.  
  539. /**
  540. * In
  541. *
  542. * @param array|string $key
  543. * @param array $haystack
  544. * @param string|null $label
  545. *
  546. * @return $this
  547. */
  548. private function inRule(array|string $key, array $haystack, ?string $label = null): self
  549. {
  550. $key = (array) $key;
  551.  
  552. foreach ($key as $field) {
  553. $input = $this->getInput($field);
  554.  
  555. if (! $this->isRequired($field) && $this->blank($input)) {
  556. return $this;
  557. }
  558.  
  559. if (! in_array($input, $haystack, true)) {
  560. $this->addError($field, sprintf($label ?? $this->data['in'], $field));
  561. }
  562. }
  563.  
  564. return $this;
  565. }
  566.  
  567. /**
  568. * Not in
  569. *
  570. * @param array|string $key
  571. * @param array $haystack
  572. * @param string|null $label
  573. *
  574. * @return $this
  575. */
  576. private function notInRule(array|string $key, array $haystack, ?string $label = null): self
  577. {
  578. $key = (array) $key;
  579.  
  580. foreach ($key as $field) {
  581. $input = $this->getInput($field);
  582.  
  583. if (! $this->isRequired($field) && $this->blank($input)) {
  584. return $this;
  585. }
  586.  
  587. if (in_array($input, $haystack, true)) {
  588. $this->addError($field, sprintf($label ?? $this->data['notIn'], $field));
  589. }
  590. }
  591.  
  592. return $this;
  593. }
  594.  
  595. /**
  596. * Regex
  597. *
  598. * @param array|string $key
  599. * @param string $pattern
  600. * @param string|null $label
  601. *
  602. * @return $this
  603. */
  604. private function regexRule(array|string $key, string $pattern, ?string $label = null): self
  605. {
  606. $key = (array) $key;
  607.  
  608. foreach ($key as $field) {
  609. $input = $this->getInput($field);
  610.  
  611. if (! $this->isRequired($field) && $this->blank($input)) {
  612. return $this;
  613. }
  614.  
  615. if (! preg_match($pattern, $input)) {
  616. $this->addError($field, sprintf($label ?? $this->data['regex'], $field));
  617. }
  618. }
  619.  
  620. return $this;
  621. }
  622.  
  623. /**
  624. * Check url
  625. *
  626. * @param array|string $key
  627. * @param string|null $label
  628. *
  629. * @return $this
  630. */
  631. private function urlRule(array|string $key, ?string $label = null): self
  632. {
  633. $key = (array) $key;
  634.  
  635. foreach ($key as $field) {
  636. $input = $this->getInput($field);
  637.  
  638. if (! $this->isRequired($field) && $this->blank($input)) {
  639. return $this;
  640. }
  641.  
  642. if (! preg_match('|^https?://([а-яa-z0-9_\-.])+(\.([а-яa-z0-9/\-?_=#])+)+$|iu', $input)) {
  643. $this->addError($field, sprintf($label ?? $this->data['url'], $field));
  644. }
  645. }
  646.  
  647. return $this;
  648. }
  649.  
  650. /**
  651. * Check email
  652. *
  653. * @param array|string $key
  654. * @param string|null $label
  655. *
  656. * @return $this
  657. */
  658. private function emailRule(array|string $key, ?string $label = null): self
  659. {
  660. $key = (array) $key;
  661.  
  662. foreach ($key as $field) {
  663. $input = $this->getInput($field);
  664.  
  665. if (! $this->isRequired($field) && $this->blank($input)) {
  666. return $this;
  667. }
  668.  
  669. if (filter_var($input, FILTER_VALIDATE_EMAIL) === false) {
  670. $this->addError($field, sprintf($label ?? $this->data['email'], $field));
  671. }
  672. }
  673.  
  674. return $this;
  675. }
  676.  
  677. /**
  678. * Check IP address
  679. *
  680. * @param array|string $key
  681. * @param string|null $label
  682. *
  683. * @return $this
  684. */
  685. private function ipRule(array|string $key, ?string $label = null): self
  686. {
  687. $key = (array) $key;
  688.  
  689. foreach ($key as $field) {
  690. $input = $this->getInput($field);
  691.  
  692. if (! $this->isRequired($field) && $this->blank($input)) {
  693. return $this;
  694. }
  695.  
  696. if (filter_var($input, FILTER_VALIDATE_IP) === false) {
  697. $this->addError($field, sprintf($label ?? $this->data['ip'], $field));
  698. }
  699. }
  700.  
  701. return $this;
  702. }
  703.  
  704. /**
  705. * Check phone
  706. *
  707. * @param array|string $key
  708. * @param string|null $label
  709. *
  710. * @return $this
  711. */
  712. private function phoneRule(array|string $key, ?string $label = null): self
  713. {
  714. $key = (array) $key;
  715.  
  716. foreach ($key as $field) {
  717. $input = $this->getInput($field);
  718.  
  719. if (! $this->isRequired($field) && $this->blank($input)) {
  720. return $this;
  721. }
  722.  
  723. if (! preg_match('#^\d{8,13}$#', $input)) {
  724. $this->addError($field, sprintf($label ?? $this->data['phone'], $field));
  725. }
  726. }
  727.  
  728. return $this;
  729. }
  730.  
  731. /**
  732. * Boolean rule
  733. *
  734. * @param array|string $key
  735. * @param string|null $label
  736. *
  737. * @return $this
  738. */
  739. private function booleanRule(array|string $key, ?string $label = null): self
  740. {
  741. $key = (array) $key;
  742.  
  743. foreach ($key as $field) {
  744. $input = $this->getInput($field);
  745.  
  746. if (! $this->isRequired($field) && $this->blank($input)) {
  747. return $this;
  748. }
  749.  
  750. if (! in_array($input, [1, '1', 0, '0', true, false], true)) {
  751. $this->addError($field, sprintf($label ?? $this->data['boolean'], $field));
  752. }
  753. }
  754.  
  755. return $this;
  756. }
  757.  
  758. /**
  759. * Add rule
  760. *
  761. * @param string $key
  762. * @param callable $callable
  763. * @param string $label
  764. *
  765. * @return $this
  766. */
  767. private function addRule(string $key, callable $callable, string $label): self
  768. {
  769. $input = $this->getInput($key);
  770.  
  771. if (! $callable($input)) {
  772. $this->addError($key, $label);
  773. }
  774.  
  775. return $this;
  776. }
  777.  
  778. /**
  779. * Custom rule
  780. *
  781. * @param bool $compare
  782. * @param array|string $label
  783. *
  784. * @return $this
  785. */
  786. private function customRule(bool $compare, array|string $label): self
  787. {
  788. $key = '';
  789.  
  790. if (is_array($label)) {
  791. $key = key($label);
  792. $label = $label[$key];
  793. }
  794.  
  795. if (! $compare) {
  796. $this->addError($key, $label);
  797. }
  798.  
  799. return $this;
  800. }
  801.  
  802. /**
  803. * Проверяет файл
  804. *
  805. * @param string $key
  806. * @param array $rules
  807. *
  808. * @return $this
  809. */
  810. private function fileRule(string $key, array $rules): self
  811. {
  812. $input = $this->getInput($key);
  813.  
  814. if (! $this->isRequired($key) && $this->blank($input)) {
  815. return $this;
  816. }
  817.  
  818. if (! $input instanceof UploadedFileInterface) {
  819. $this->addError($key, sprintf($this->data['file']['error'], $key));
  820. return $this;
  821. }
  822.  
  823. if ($input->getError() !== UPLOAD_ERR_OK) {
  824. $this->addError($key, $this->getUploadErrorByCode($input->getError()));
  825. return $this;
  826. }
  827.  
  828. if (empty($rules['extensions'])) {
  829. $rules['extensions'] = $this->images;
  830. }
  831.  
  832. $extension = strtolower(pathinfo($input->getClientFilename(), PATHINFO_EXTENSION));
  833. if (! in_array($extension, $rules['extensions'], true)) {
  834. $this->addError($key, sprintf($this->data['file']['extension'], $key, implode(', ', $rules['extensions'])));
  835. }
  836.  
  837. if (isset($rules['size_max']) && $input->getSize() > $rules['size_max']) {
  838. $this->addError($key, sprintf($this->data['file']['size_max'], $key, formatSize($rules['size_max'])));
  839. }
  840.  
  841. if (in_array($extension, $this->images, true)) {
  842. [$width, $height] = getimagesize($input->getFilePath());
  843.  
  844. if (! empty($rules['weight_max'])) {
  845. if ($width > $rules['weight_max'] || $height > $rules['weight_max']) {
  846. $this->addError($key, sprintf($this->data['file']['weight_max'], $key, $rules['weight_max']));
  847. }
  848. }
  849.  
  850. if (! empty($rules['weight_min'])) {
  851. if ($width < $rules['weight_min'] || $height < $rules['weight_min']) {
  852. $this->addError($key, sprintf($this->data['file']['weight_min'], $key, $rules['weight_min']));
  853. }
  854. } elseif (empty($width) || empty($height)) {
  855. $this->addError($key, sprintf($this->data['file']['weight_empty'], $key));
  856. }
  857. }
  858.  
  859. return $this;
  860. }
  861.  
  862. /**
  863. * Add error
  864. *
  865. * @param string $key Field name
  866. * @param string $label Text error
  867. *
  868. * @return void
  869. */
  870. public function addError(string $key, string $label): void
  871. {
  872. if (isset($this->errors[$key])) {
  873. $this->errors[] = $label;
  874. } else {
  875. $this->errors[$key] = $label;
  876. }
  877. }
  878.  
  879. /**
  880. * Get errors
  881. *
  882. * @return array
  883. */
  884. public function getErrors(): array
  885. {
  886. return $this->errors;
  887. }
  888.  
  889. /**
  890. * Determine if the given value is "blank".
  891. *
  892. * @param mixed $value
  893. * @return bool
  894. */
  895. private function blank(mixed $value): bool
  896. {
  897. if (is_null($value)) {
  898. return true;
  899. }
  900.  
  901. if (is_string($value)) {
  902. return trim($value) === '';
  903. }
  904.  
  905. if (is_numeric($value) || is_bool($value)) {
  906. return false;
  907. }
  908.  
  909. if ($value instanceof Countable) {
  910. return count($value) === 0;
  911. }
  912.  
  913. if ($value instanceof UploadedFileInterface) {
  914. return $value->getError() === UPLOAD_ERR_NO_FILE;
  915. }
  916.  
  917. return empty($value);
  918. }
  919.  
  920. /**
  921. * Is required
  922. *
  923. * @param string $key
  924. * @return bool
  925. */
  926. private function isRequired(string $key): bool
  927. {
  928. return isset($this->rules[$key]['required']);
  929. }
  930.  
  931. /**
  932. * Get input
  933. *
  934. * @param string $key
  935. * @param mixed|null $default
  936. *
  937. * @return mixed
  938. */
  939. private function getInput(string $key, mixed $default = null): mixed
  940. {
  941. return $this->input[$key] ?? $default;
  942. }
  943.  
  944. /**
  945. * Get upload error by code
  946. *
  947. * @param int $code
  948. *
  949. * @return string
  950. */
  951. private function getUploadErrorByCode(int $code): string
  952. {
  953. return match ($code) {
  954. UPLOAD_ERR_INI_SIZE => 'Размер файла превысил значение upload_max_filesize',
  955. UPLOAD_ERR_FORM_SIZE => 'Размер файла превысил значение MAX_FILE_SIZE',
  956. UPLOAD_ERR_PARTIAL => 'Загруженный файл был загружен только частично',
  957. UPLOAD_ERR_NO_FILE => 'Файл не был загружен',
  958. UPLOAD_ERR_NO_TMP_DIR => 'Отсутствует временная папка',
  959. UPLOAD_ERR_CANT_WRITE => 'Не удалось записать файл на диск',
  960. UPLOAD_ERR_EXTENSION => 'Модуль PHP остановил загрузку файла',
  961. default => 'Неизвестная ошибка загрузки',
  962. };
  963. }
  964. }