Completed
Push — FVSv2 ( 10d7ab...2b5aa4 )
by Patrick
01:37
created

Processor::processShift()   D

Complexity

Conditions 13
Paths 292

Size

Total Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
nc 292
nop 2
dl 0
loc 70
rs 4.3612
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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);
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
            $profile = new \VolunteerProfile($uid);
64
            $uids[$uid] = $profile->getDisplayName();
65
        }
66
        return $uids[$uid];
67
    }
68
69
    protected function isUserDepartmentLead($departmentID, $user)
70
    {
71
        static $deptCache = array();
72
        if(!isset($deptCache[$departmentID]))
73
        {
74
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'departments');
75
            $filter = new \Data\Filter('departmentID eq '.$departmentID);
76
            $depts = $dataTable->read($filter);
77
            if(empty($depts))
78
            {
79
                return false;
80
            }
81
            $deptCache[$departmentID] = $depts[0];
82
        }
83
        return $this->isUserDepartmentLead2($deptCache[$departmentID], $user);
84
    }
85
86
    protected function userIsLeadCached($user)
87
    {
88
        static $userIsLead = null;
89
        if($userIsLead === null)
90
        {
91
            $userIsLead = $user->isInGroupNamed('Leads');
92
        }
93
        return $userIsLead;
94
    }
95
96
    protected function isUserDepartmentLead2($dept, $user)
97
    {
98
        static $depts = array();
99
        if(!isset($depts[$dept['departmentID']]))
100
        {
101
            $depts[$dept['departmentID']] = array();
102
        }
103
        $deptCache = $depts[$dept['departmentID']];
104
        $uid = $user->uid;
105
        if(!isset($deptCache[$uid]))
106
        {
107
            if($this->userIsLeadCached($user) && in_array($dept['lead'], $user->title))
108
            {
109
                $deptCache[$uid] = true;
110
            }
111
            else if(!isset($dept['others']))
112
            {
113
                $deptCache[$uid] = false;
114
            }
115
            else
116
            {
117
                $email = $user->mail;
118
                $otherAdmins = explode(',', $dept['others']);
119
                $deptCache[$uid] = in_array($email, $otherAdmins);
120
            }
121
        }
122
        return $deptCache[$uid];
123
    }
124
125
    public function isAdminForShift($shift, $user)
126
    {
127
        if($this->isAdmin)
128
        {
129
            return true;
130
        }
131
        if($this->isUserDepartmentLead($shift['departmentID'], $user))
132
        {
133
            return true;
134
        }
135
        return false;
136
    }
137
138
    public function isAdminForRole($role, $user)
139
    {
140
        //Shift and Role use the same key for department ID...
141
        return $this->isAdminForShift($role, $user);
142
    }
143
144
    protected function shouldShowDepartment($deptId, $isAdmin)
145
    {
146
        static $privateDepts = null;
147
        if($privateDepts === null)
148
        {
149
            $privateDepts = VolunteerDepartment::getPrivateDepartments();
150
        }
151
        if($isAdmin)
152
        {
153
            return true;
154
        }
155
        return !in_array($deptId, $privateDepts);
156
    }
157
158
    protected function doShiftTimeChecks($shift, $entry)
159
    {
160
        $now = new DateTime();
161
        if($shift->startTime < $now)
162
        {
163
            $entry['available'] = false;
164
            $entry['why'] = 'Shift already started';
165
        }
166
        if($shift->endTime < $now)
167
        {
168
            $entry['available'] = false;
169
            $entry['why'] = 'Shift already ended';
170
        }
171
    }
172
173
    protected function processShift($entry, $request)
174
    {
175
        static $profile = null;
176
        static $eeAvailable = false;
177
        static $canDoRole = array();
178
        static $roles = array();
179
        if($this->isAdmin === null)
180
        {
181
            $this->isVolunteerAdmin($request);
182
        }
183
        if($profile === null)
184
        {
185
            $profile = new \VolunteerProfile($this->user->uid);
186
            $eeAvailable = $profile->isEEAvailable();
187
            $dataTable = DataSetFactory::getDataTableByNames('fvs', 'roles');
188
            $tmp = $dataTable->read();
189
            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...
190
            {
191
               $roles[$role['short_name']] = $role;
192
            }
193
        }
194
        $shift = new \VolunteerShift(false, $entry);
195
        $entry['isAdmin'] = $this->isAdminForShift($entry, $this->user);
196
        $entry['overlap'] = $shift->findOverlaps($this->user->uid, true);
197
        if(!$this->shouldShowDepartment($entry['departmentID'], $entry['isAdmin']))
198
        {
199
            return null;
200
        }
201
        $entry['available'] = true;
202
        $this->doShiftTimeChecks($shift, $entry);
203
        if($entry['earlyLate'] != -1 && !$eeAvailable)
204
        {
205
            $entry['available'] = false;
206
            $entry['why'] = 'Shift requires early entry or late stay and you have not provided your legal name';
207
        }
208
        if(!isset($canDoRole[$entry['roleID']]))
209
        {
210
            $canDoRole[$entry['roleID']] = $this->canUserDoRole($profile, $roles[$entry['roleID']]);
211
        }
212
        if($canDoRole[$entry['roleID']] !== true)
213
        {
214
            $entry['available'] = false;
215
            $entry['why'] = $canDoRole[$entry['roleID']]['whyMsg'];
216
            $entry['whyClass'] = $canDoRole[$entry['roleID']]['whyClass'];
217
        }
218
        if($shift->isFilled())
219
        {
220
            if($entry['participant'] !== '/dev/null')
221
            {
222
                $entry['volunteer'] = $this->getParticipantDiplayName($entry['participant']);
223
            }
224
            if($entry['participant'] === $profile->uid)
225
            {
226
                $entry['available'] = false;
227
                $entry['why'] = 'Shift is already taken, by you';
228
                $entry['whyClass'] = 'MINE';
229
            }
230
            else
231
            {
232
                $entry['available'] = false;
233
                $entry['why'] = 'Shift is already taken';
234
                $entry['whyClass'] = 'TAKEN';
235
            }
236
            if(!$entry['isAdmin'])
237
            {
238
                unset($entry['participant']);
239
            }
240
        }
241
        return $entry;
242
    }
243
244
    protected function processRole($entry, $request)
245
    {
246
        if($this->isAdmin === null)
247
        {
248
            $this->isVolunteerAdmin($request);
249
        }
250
        $entry['isAdmin'] = $this->isAdminForRole($entry, $this->user);
251
        return $entry;
252
    }
253
}
254
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
255