Processor   F
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 283
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 140
c 6
b 0
f 0
dl 0
loc 283
rs 3.36
wmc 63

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getParticipantDiplayName() 0 16 3
A userIsLeadCached() 0 8 2
B canUserDoRole() 0 41 9
A certCheck() 0 7 4
A isUserDepartmentLead() 0 15 3
A isAdminForShift() 0 11 3
A isAdminForRole() 0 4 1
A shouldShowDepartment() 0 12 3
B isUserDepartmentLead2() 0 31 9
A processRole() 0 8 2
F processShift() 0 70 16
A cleanupNonDBFields() 0 13 4
A doShiftTimeChecks() 0 17 4

How to fix   Complexity   

Complex Class

Complex classes like Processor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Processor, and based on these observations, apply Extract Interface, too.

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
    protected abstract function isVolunteerAdmin($request);
14
15
    public function canUserDoRole($user, $role)
16
    {
17
        static $certs = null;
18
        static $certCount = 0;
19
        if($certs === null)
20
        {
21
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'certifications');
22
            $certs = $dataTable->read();
23
            $certCount = count($certs);
0 ignored issues
show
Bug introduced by
It seems like $certs can also be of type boolean; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

23
            $certCount = count(/** @scrutinizer ignore-type */ $certs);
Loading history...
24
        }
25
        if($role['publicly_visible'] === true)
26
        {
27
            return true;
28
        }
29
        $requirements = array();
30
        if(isset($role['requirements']))
31
        {
32
            $requirements = $role['requirements'];
33
        }
34
        $userCerts = $user->certs;
35
        if(count($requirements) === 0)
36
        {
37
            //Bugged role...
38
            return true;
39
        }
40
        if(isset($requirements['email_list']))
41
        {
42
            $emails = explode(',', $requirements['email_list']);
43
            if(!$user->userInEmailList($emails))
44
            {
45
                return array('whyClass' => 'INVITE', 'whyMsg' => 'Shift is invite only.');
46
            }
47
        }
48
        for($i = 0; $i < $certCount; $i++)
49
        {
50
            if($this->certCheck($requirements, $userCerts, $certs[$i]['certID']))
51
            {
52
                return array('whyClass' => 'CERT', 'whyMsg' => 'Shift requires '.$certs[$i]['name'].' and you do not have that certification');
53
            }
54
        }
55
        return true;
56
    }
57
58
    protected function getParticipantDiplayName($uid)
59
    {
60
        static $uids = array();
61
        if(!isset($uids[$uid]))
62
        {
63
            try
64
            {
65
                $profile = new \VolunteerProfile($uid);
66
                $uids[$uid] = $profile->getDisplayName();
67
            }
68
            catch(Exception $e)
69
            {
70
                $uids[$uid] = $uid;
71
            }
72
        }
73
        return $uids[$uid];
74
    }
75
76
    protected function isUserDepartmentLead($departmentID, $user)
77
    {
78
        static $deptCache = array();
79
        if(!isset($deptCache[$departmentID]))
80
        {
81
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'departments');
82
            $filter = new \Data\Filter('departmentID eq '.$departmentID);
83
            $depts = $dataTable->read($filter);
84
            if(empty($depts))
85
            {
86
                return false;
87
            }
88
            $deptCache[$departmentID] = $depts[0];
89
        }
90
        return $this->isUserDepartmentLead2($deptCache[$departmentID], $user);
91
    }
92
93
    protected function userIsLeadCached($user)
94
    {
95
        static $userIsLead = null;
96
        if($userIsLead === null)
97
        {
98
            $userIsLead = $user->isInGroupNamed('Leads');
99
        }
100
        return $userIsLead;
101
    }
102
103
    protected function isUserDepartmentLead2($dept, $user)
104
    {
105
        static $depts = array();
106
        if(!isset($depts[$dept['departmentID']]))
107
        {
108
            $depts[$dept['departmentID']] = array();
109
        }
110
        $deptCache = $depts[$dept['departmentID']];
111
        $uid = $user->uid;
112
        if(!isset($deptCache[$uid]))
113
        {
114
            if(isset($dept['lead']) && $this->userIsLeadCached($user) && is_array($user->title) && in_array($dept['lead'], $user->title))
115
            {
116
                $deptCache[$uid] = true;
117
            }
118
            else if(!isset($dept['others']))
119
            {
120
                $deptCache[$uid] = false;
121
            }
122
            else
123
            {
124
                $email = $user->mail;
125
                $otherAdmins = $dept['others'];
126
                if(!is_array($dept['others']))
127
                {
128
                    $otherAdmins = explode(',', $dept['others']);
129
                }
130
                $deptCache[$uid] = in_array($email, $otherAdmins);
131
            }
132
        }
133
        return $deptCache[$uid];
134
    }
135
136
    public function isAdminForShift($shift, $user)
137
    {
138
        if($this->isAdmin)
139
        {
140
            return true;
141
        }
142
        if($this->isUserDepartmentLead($shift['departmentID'], $user))
143
        {
144
            return true;
145
        }
146
        return false;
147
    }
148
149
    public function isAdminForRole($role, $user)
150
    {
151
        //Shift and Role use the same key for department ID...
152
        return $this->isAdminForShift($role, $user);
153
    }
154
155
    protected function shouldShowDepartment($deptId, $isAdmin)
156
    {
157
        static $privateDepts = null;
158
        if($privateDepts === null)
159
        {
160
            $privateDepts = VolunteerDepartment::getPrivateDepartments();
161
        }
162
        if($isAdmin)
163
        {
164
            return true;
165
        }
166
        return !in_array($deptId, $privateDepts);
167
    }
168
169
    protected function doShiftTimeChecks($shift, &$entry)
170
    {
171
        $now = new DateTime();
172
        if($shift->startTime < $now)
173
        {
174
            $entry['available'] = false;
175
            $entry['why'] = 'Shift already started';
176
        }
177
        if($shift->endTime < $now)
178
        {
179
            $entry['available'] = false;
180
            $entry['why'] = 'Shift already ended';
181
        }
182
        if(strpbrk($entry['startTime'], 'Z+') === false)
183
        {
184
            $entry['startTime'] = $shift->startTime->format('c');
185
            $entry['endTime'] = $shift->endTime->format('c');
186
        }
187
    }
188
189
    protected function cleanupNonDBFields(&$entry)
190
    {
191
        if(isset($entry['volunteer']))
192
        {
193
            unset($entry['volunteer']);
194
        }
195
        if(isset($entry['why']))
196
        {
197
            unset($entry['why']);
198
        }
199
        if(isset($entry['whyClass']))
200
        {
201
            unset($entry['whyClass']);
202
        }
203
    }
204
205
    protected function processShift($entry, $request)
206
    {
207
        static $profile = null;
208
        static $eeAvailable = false;
209
        static $canDoRole = array();
210
        static $roles = array();
211
        if($this->isAdmin === null)
212
        {
213
            $this->isVolunteerAdmin($request);
214
        }
215
        if($profile === null)
216
        {
217
            $profile = new \VolunteerProfile($this->user->uid);
218
            $eeAvailable = $profile->isEEAvailable();
219
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
220
            $tmp = $dataTable->read();
221
            foreach($tmp as $role)
222
            {
223
                $roles[$role['short_name']] = $role;
224
            }
225
        }
226
        $this->cleanupNonDBFields($entry);
227
        $shift = new \VolunteerShift(false, $entry);
228
        $entry['isAdmin'] = $this->isAdminForShift($entry, $this->user);
229
        $entry['overlap'] = $shift->findOverlaps($this->user->uid, true);
230
        if(!$this->shouldShowDepartment($entry['departmentID'], $entry['isAdmin']))
231
        {
232
            return null;
233
        }
234
        $entry['available'] = true;
235
        $this->doShiftTimeChecks($shift, $entry);
236
        if($entry['earlyLate'] != -1 && !$eeAvailable)
237
        {
238
            $entry['available'] = false;
239
            $entry['why'] = 'Shift requires early entry or late stay and you have not provided your legal name';
240
        }
241
        if(!isset($canDoRole[$entry['roleID']]))
242
        {
243
            $canDoRole[$entry['roleID']] = $this->canUserDoRole($profile, $roles[$entry['roleID']]);
244
        }
245
        if($canDoRole[$entry['roleID']] !== true)
246
        {
247
            $entry['available'] = false;
248
            $entry['why'] = $canDoRole[$entry['roleID']]['whyMsg'];
249
            $entry['whyClass'] = $canDoRole[$entry['roleID']]['whyClass'];
250
        }
251
        if($shift->isFilled())
252
        {
253
            if(isset($entry['participant']) && ($entry['participant'] !== '/dev/null' || $entry['participant'] !== ''))
254
            {
255
                $entry['volunteer'] = $this->getParticipantDiplayName($entry['participant']);
256
            }
257
            if(isset($entry['participant']) && $entry['participant'] === $profile->uid)
258
            {
259
                $entry['available'] = false;
260
                $entry['why'] = 'Shift is already taken, by you';
261
                $entry['whyClass'] = 'MINE';
262
            }
263
            else
264
            {
265
                $entry['available'] = false;
266
                $entry['why'] = 'Shift is already taken';
267
                $entry['whyClass'] = 'TAKEN';
268
            }
269
            if(!$entry['isAdmin'])
270
            {
271
                unset($entry['participant']);
272
            }
273
        }
274
        return $entry;
275
    }
276
277
    protected function processRole($entry, $request)
278
    {
279
        if($this->isAdmin === null)
280
        {
281
            $this->isVolunteerAdmin($request);
282
        }
283
        $entry['isAdmin'] = $this->isAdminForRole($entry, $this->user);
284
        return $entry;
285
    }
286
}
287
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
288