1 <?php
2 /**
3 * Created by PhpStorm.
4 * User: Jean-françois
5 * Date: 22/08/2015
6 * Time: 11:36.
7 */
8 namespace Skimia\ApiFusion\Domain\Traits;
9
10 use Skimia\ApiFusion\Domain\Exceptions\ValidationException;
11 use Skimia\ApiFusion\Domain\Exceptions\AuthorisationException;
12 use Skimia\ApiFusion\Domain\Exceptions\RequiredInputValidatorException;
13
14 trait CheckableTrait
15 {
16 /**
17 * Validator class for the resource.
18 * @var InputValidatorContract
19 */
20 protected $inputValidator;
21
22 /*
23 |--------------------------------------------------------------------------
24 | Security Authorisation & Validation & Filters
25 |--------------------------------------------------------------------------
26 */
27
28 /**
29 * Run required checks for given action.
30 * @param string $action Requested action to check
31 * @param array $input Input data relevant to checks
32 * @param array $original Original data from the model
33 * @return array InputFilteredData if $input is provided
34 */
35 protected function runChecks($action, $input = [], $original = [])
36 {
37 // Perform a basic check to see if the current action is authorised
38 // to be performed on this resource
39 $this->checkAuthorisation($action);
40
41 // If input data is given
42 if (! empty($input)) {
43 // Run input validation on the input data
44 $filtered = $this->applyValidationRules($action, $input);
45
46 // Run business rule validation on the input data
47 $this->applyDomainRules($action, $input, $original);
48
49 return $filtered;
50 }
51 }
52
53 /**
54 * Check if given action is authorised on resource.
55 * @param string $action Requested action to check
56 * @throws AuthorisationException If action is unathorised
57 */
58 protected function checkAuthorisation($action)
59 {
60 $authCheckMethod = $action.'Authorised'; // e.g. readAuthorised
61
62 if (! $this->{ $authCheckMethod }()) {
63 throw new AuthorisationException('You are not authorised to perform this action');
64 }
65 }
66
67 /**
68 * Apply validation rules.
69 * @param string $action Requested action to check
70 * @param array $input Input data
71 * @throws ValidationException If input validation fails
72 * @throws RequiredInputValidatorException If inputValidator is not proivide on a data modification / creation
73 * @return array InputFilteredData
74 */
75 protected function applyValidationRules($action, $input = [])
76 {
77 if ($action == 'read' or $action == 'destroy') {
78 return;
79 }
80
81 if (! $this->inputValidator) {
82 throw new RequiredInputValidatorException('You must provide an inputValidator to perform a data modification / creation');
83 }
84
85 $validation = $this->inputValidator->make($input);
86
87 $validation->scope([$action]);
88
89 $validation->bind($validation->getInputs()); // provide all input data for use in rule definitions
90
91 if ($validation->fails()) {
92 throw new ValidationException('Validation failed', $validation->errors()->all());
93 } else {
94 return $validation->getInputs();
95 }
96 }
97
98 /**
99 * Apply domain rules.
100 * @param string $action Requested action to check
101 * @param array $input Input data
102 * @param array $original Original item before modification
103 */
104 protected function applyDomainRules($action, $input = [], $original = [])
105 {
106 $domainRulesMethod = 'domainRulesOn'.ucfirst($action);
107
108 // Pass in original model if we are updating
109 if ($action = 'update') {
110 $this->{ $domainRulesMethod }($input, $original);
111 } else {
112 $this->{ $domainRulesMethod }($input);
113 }
114 }
115 }
116