RequestTrait::hasAnyRoleAccess()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
dl 15
loc 15
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 1
1
<?php
2
3
namespace App\Ship\Parents\Requests;
4
5
use App\Ship\Features\Exceptions\ValidationFailedException;
6
use Illuminate\Contracts\Validation\Validator;
7
use Dingo\Api\Http\Request as DingoRequest;
8
9
/**
10
 * Class RequestTrait
11
 *
12
 * @author  Mahmoud Zalt  <[email protected]>
13
 */
14
trait RequestTrait
15
{
16
17
    /**
18
     * Overriding this function to modify the any user input before
19
     * applying the validation rules.
20
     *
21
     * @return  array
22
     */
23
    public function all()
24
    {
25
        $requestData = parent::all();
26
27
        $requestData = $this->mergeUrlParametersWithRequestData($requestData);
28
29
        $requestData = $this->decodeHashedIdsBeforeValidation($requestData);
0 ignored issues
show
Bug introduced by
It seems like decodeHashedIdsBeforeValidation() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
30
31
        return $requestData;
32
    }
33
34
    /**
35
     * Overriding this function to throw a custom
36
     * exception instead of the default Laravel exception.
37
     *
38
     * @param \Illuminate\Contracts\Validation\Validator $validator
39
     *
40
     * @return mixed|void
41
     */
42
    public function failedValidation(Validator $validator)
43
    {
44
        if ($this->container['request'] instanceof DingoRequest) {
0 ignored issues
show
Bug introduced by
The property container does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The class Dingo\Api\Http\Request does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
45
            throw new ValidationFailedException($validator->getMessageBag());
46
        }
47
48
        parent::failedValidation($validator);
49
    }
50
51
52
    /**
53
     * Used from the `authorize` function if the Request class.
54
     * To call functions and compare their bool responses to determine
55
     * if the user can proceed with the request or not.
56
     *
57
     * @param array $functions
58
     *
59
     * @return  bool
60
     */
61
    protected function check(array $functions)
62
    {
63
        $orIndicator = '|';
64
        $returns = [];
65
66
        // iterate all functions in the array
67
        foreach ($functions as $function) {
68
69
            // in case the value doesn't contains a separator (single function per key)
70
            if (!strpos($function, $orIndicator)) {
71
                // simply call the single function and store the response.
72
                $returns[] = $this->{$function}();
73
            } else {
74
                // in case the value contains a separator (multiple functions per key)
75
                $orReturns = [];
76
77
                // iterate over each function in the key
78
                foreach (explode($orIndicator, $function) as $orFunction) {
79
                    // dynamically call each function
80
                    $orReturns[] = $this->{$orFunction}();
81
                }
82
83
                // if in_array returned `true` means at least one function returned `true` thus return `true` to allow access.
84
                // if in_array returned `false` means no function returned `true` thus return `false` to prevent access.
85
                // return single boolean for all the functions found inside the same key.
86
                $returns[] = in_array(true, $orReturns) ? true : false;
87
            }
88
        }
89
90
        // if in_array returned `true` means a function returned `false` thus return `false` to prevent access.
91
        // if in_array returned `false` means all functions returned `true` thus return `true` to allow access.
92
        // return the final boolean
93
        return in_array(false, $returns) ? false : true;
94
    }
95
96
    /**
97
     * apply validation rules to the ID's in the URL, since Laravel
98
     * doesn't validate them by default!
99
     *
100
     * Now you can use validation riles like this: `'id' => 'required|integer|exists:items,id'`
101
     *
102
     * @param array $requestData
103
     *
104
     * @return  array
105
     */
106
    private function mergeUrlParametersWithRequestData(Array $requestData)
107
    {
108
        if (isset($this->urlParameters) && !empty($this->urlParameters)) {
109
            foreach ($this->urlParameters as $param) {
0 ignored issues
show
Bug introduced by
The property urlParameters does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
110
                $requestData[$param] = $this->route($param);
0 ignored issues
show
Bug introduced by
It seems like route() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
111
            }
112
        }
113
114
        return $requestData;
115
    }
116
117
    /**
118
     * @param $user
119
     *
120
     * @return  array
121
     */
122 View Code Duplication
    private function hasAnyPermissionAccess($user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
    {
124
        if (!array_key_exists('permissions', $this->access) || !$this->access['permissions']) {
0 ignored issues
show
Bug introduced by
The property access does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
125
            return [];
126
        }
127
128
        $permissions = explode('|', $this->access['permissions']);
129
130
        $hasAccess = array_map(function ($permission) use ($user) {
131
            // Note: internal return
132
            return $user->hasPermissionTo($permission);
133
        }, $permissions);
134
135
        return $hasAccess;
136
    }
137
138
    /**
139
     * @param $user
140
     *
141
     * @return  array
142
     */
143 View Code Duplication
    private function hasAnyRoleAccess($user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145
        if (!array_key_exists('roles', $this->access) || !$this->access['roles']) {
146
            return [];
147
        }
148
149
        $roles = explode('|', $this->access['roles']);
150
151
        $hasAccess = array_map(function ($role) use ($user) {
152
            // Note: internal return
153
            return $user->hasRole($role);
154
        }, $roles);
155
156
        return $hasAccess;
157
    }
158
}
159