Completed
Push — FVSv2 ( 673865...e43498 )
by Patrick
01:56
created

Processor::isUserDepartmentLead2()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 8
nop 2
dl 0
loc 28
rs 8.8497
c 0
b 0
f 0
1
<?php
2
trait Processor
3
{
4
    protected function certCheck($requirements, $certs, $certType)
5
    {
6
        if(isset($requirements[$certType]) && $requirements[$certType])
7
        {
8
            return (!isset($certs[$certType]) || !$certs[$certType]);
9
        }
10
        return false;
11
    }
12
13
    public function canUserDoRole($user, $role)
14
    {
15
        if($role['publicly_visible'] === true)
16
        {
17
            return true;
18
        }
19
        $requirements = array();
20
        if(isset($role['requirements']))
21
        {
22
            $requirements = $role['requirements'];
23
        }
24
        $certs = $user->certs;
25
        if(count($requirements) === 0)
26
        {
27
            //Bugged role...
28
            return true;
29
        }
30
        if(isset($requirements['email_list']))
31
        {
32
            $emails = explode(',', $requirements['email_list']);
33
            if(!$user->userInEmailList($emails))
34
            {
35
                return array('whyClass' => 'INVITE', 'whyMsg' => 'Shift is invite only.');
36
            }
37
        }
38
        if($this->certCheck($requirements, $certs, 'ics100'))
39
        {
40
            return array('whyClass' => 'CERT', 'whyMsg' => 'Shift requires ICS 100 and you do not have that certification');
41
        }
42
        if($this->certCheck($requirements, $certs, 'ics200'))
43
        {
44
            return array('whyClass' => 'CERT', 'whyMsg' => 'Shift requires ICS 200 and you do not have that certification');
45
        }
46
        if($this->certCheck($requirements, $certs, 'bls'))
47
        {
48
            return array('whyClass' => 'CERT', 'whyMsg' => 'Shift requires Basic Life Support certification and you do not have that certification');
49
        }
50
        return true;
51
    }
52
53
    protected function getParticipantDiplayName($uid)
54
    {
55
        static $uids = array();
56
        if(!isset($uids[$uid]))
57
        {
58
            $profile = new \VolunteerProfile($uid);
59
            $uids[$uid] = $profile->getDisplayName();
60
        }
61
        return $uids[$uid];
62
    }
63
64
    protected function isUserDepartmentLead($departmentID, $user)
65
    {
66
        static $deptCache = array();
67
        if(!isset($deptCache[$departmentID]))
68
        {
69
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'departments');
70
            $filter = new \Data\Filter('departmentID eq '.$departmentID);
71
            $depts = $dataTable->read($filter);
72
            if(empty($depts))
73
            {
74
                return false;
75
            }
76
            $deptCache[$departmentID] = $depts[0];
77
        }
78
        return $this->isUserDepartmentLead2($deptCache[$departmentID], $user);
79
    }
80
81
    protected function userIsLeadCached($user)
82
    {
83
        static $userIsLead = null;
84
        if($userIsLead === null)
85
        {
86
            $userIsLead = $user->isInGroupNamed('Leads');
87
        }
88
        return $userIsLead;
89
    }
90
91
    protected function isUserDepartmentLead2($dept, $user)
92
    {
93
        static $depts = array();
94
        if(!isset($depts[$dept['departmentID']]))
95
        {
96
            $depts[$dept['departmentID']] = array();
97
        }
98
        $deptCache = $depts[$dept['departmentID']];
99
        $uid = $user->uid;
100
        if(!isset($deptCache[$uid]))
101
        {
102
            if($this->userIsLeadCached($user) && in_array($dept['lead'], $user->title))
103
            {
104
                $deptCache[$uid] = true;
105
            }
106
            else if(!isset($dept['others']))
107
            {
108
                $deptCache[$uid] = false;
109
            }
110
            else
111
            {
112
                $email = $user->mail;
113
                $otherAdmins = explode(',', $dept['others']);
114
                $deptCache[$uid] = in_array($email, $otherAdmins);
115
            }
116
        }
117
        return $deptCache[$uid];
118
    }
119
120
    public function isAdminForShift($shift, $user)
121
    {
122
        if($this->isAdmin)
1 ignored issue
show
Bug introduced by
The property isAdmin 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...
123
        {
124
            return true;
125
        }
126
        if($this->isUserDepartmentLead($shift['departmentID'], $user))
127
        {
128
            return true;
129
        }
130
        return false;
131
    }
132
133
    public function isAdminForRole($role, $user)
134
    {
135
        //Shift and Role use the same key for department ID...
136
        return $this->isAdminForShift($role, $user);
137
    }
138
139
    protected function shouldShowDepartment($deptId, $isAdmin)
140
    {
141
        static $privateDepts = null;
142
        if($privateDepts === null)
143
        {
144
            $privateDepts = VolunteerDepartment::getPrivateDepartments();
145
        }
146
        if($isAdmin)
147
        {
148
            return true;
149
        }
150
        return !in_array($deptId, $privateDepts);
151
    }
152
153
    protected function doShiftTimeChecks($shift, $entry)
154
    {
155
        $now = new DateTime();
156
        if($shift->startTime < $now)
157
        {
158
            $entry['available'] = false;
159
            $entry['why'] = 'Shift already started';
160
        }
161
        if($shift->endTime < $now)
162
        {
163
            $entry['available'] = false;
164
            $entry['why'] = 'Shift already ended';
165
        }
166
    }
167
168
    protected function processShift($entry)
169
    {
170
        static $profile = null;
171
        static $eeAvailable = false;
172
        static $canDoRole = array();
173
        static $roles = array();
174
        if($profile === null)
175
        {
176
            $profile = new \VolunteerProfile($this->user->uid);
1 ignored issue
show
Bug introduced by
The property user 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...
177
            $eeAvailable = $profile->isEEAvailable();
178
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
179
            $tmp = $dataTable->read();
180
            foreach($tmp as $role)
0 ignored issues
show
Bug introduced by
The expression $tmp of type boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
181
            {
182
               $roles[$role['short_name']] = $role;
183
            }
184
        }
185
        $shift = new \VolunteerShift(false, $entry);
186
        $entry['isAdmin'] = $this->isAdminForShift($entry, $this->user);
187
        $entry['overlap'] = $shift->findOverlaps($this->user->uid, true);
188
        if(!$this->shouldShowDepartment($entry['departmentID'], $entry['isAdmin']))
189
        {
190
            return null;
191
        }
192
        $entry['available'] = true;
193
        $this->doShiftTimeChecks($shift, $entry);
194
        if($entry['earlyLate'] != -1 && !$eeAvailable)
195
        {
196
            $entry['available'] = false;
197
            $entry['why'] = 'Shift requires early entry or late stay and you have not provided your legal name';
198
        }
199
        if(!isset($canDoRole[$entry['roleID']]))
200
        {
201
            $canDoRole[$entry['roleID']] = $this->canUserDoRole($profile, $roles[$entry['roleID']]);
202
        }
203
        if($canDoRole[$entry['roleID']] !== true)
204
        {
205
            $entry['available'] = false;
206
            $entry['why'] = $canDoRole[$entry['roleID']]['whyMsg'];
207
            $entry['whyClass'] = $canDoRole[$entry['roleID']]['whyClass'];
208
        }
209
        if($shift->isFilled())
210
        {
211
            $entry['volunteer'] = $this->getParticipantDiplayName($entry['participant']);
212
            if($entry['participant'] === $profile->uid)
0 ignored issues
show
Documentation introduced by
The property uid does not exist on object<VolunteerProfile>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
213
            {
214
                $entry['available'] = false;
215
                $entry['why'] = 'Shift is already taken, by you';
216
                $entry['whyClass'] = 'MINE';
217
            }
218
            else
219
            {
220
                $entry['available'] = false;
221
                $entry['why'] = 'Shift is already taken';
222
                $entry['whyClass'] = 'TAKEN';
223
            }
224
            if(!$entry['isAdmin'])
225
            {
226
                unset($entry['participant']);
227
            }
228
        }
229
        return $entry;
230
    }
231
232
    protected function processRole($entry, $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
233
    {
234
        $entry['isAdmin'] = $this->isAdminForRole($entry, $this->user);
235
        return $entry;
236
    }
237
}
238
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
239