Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
72 / 72
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ProcessStatusFree
100.00% covered (success)
100.00%
72 / 72
100.00% covered (success)
100.00%
3 / 3
18
100.00% covered (success)
100.00%
1 / 1
 readFreeProcesses
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
8
 readReservedProcesses
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
 writeEntityReserved
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3namespace BO\Zmsdb;
4
5use BO\Zmsentities\Process as Entity;
6use BO\Zmsentities\Collection\ProcessList as Collection;
7
8/**
9 * @SuppressWarnings(Coupling)
10 */
11class ProcessStatusFree extends Process
12{
13    public function readFreeProcesses(
14        \BO\Zmsentities\Calendar $calendar,
15        \DateTimeInterface $now,
16        $slotType = 'public',
17        $slotsRequired = null,
18        $groupData = false
19    ) {
20        $calendar = (new Calendar())->readResolvedEntity($calendar, $now, true);
21        $dayquery = new Day();
22        $dayquery->writeTemporaryScopeList($calendar, $slotsRequired);
23        $selectedDate = $calendar->getFirstDay();
24        $processList = new Collection();
25        $days = [$selectedDate];
26        $scopeList = [];
27
28        if ($calendar->getLastDay(false)) {
29            $days = [];
30            while ($selectedDate <= $calendar->getLastDay(false)) {
31                $days[] = $selectedDate;
32                $selectedDate = $selectedDate->modify('+1 day');
33            }
34        }
35
36        $processData = $this->fetchHandle(
37            sprintf(
38                Query\ProcessStatusFree::QUERY_SELECT_PROCESSLIST_DAYS,
39                Query\ProcessStatusFree::buildDaysCondition($days)
40            )
41            . ($groupData ? Query\ProcessStatusFree::GROUPBY_SELECT_PROCESSLIST_DAY : ''),
42            [
43                'slotType' => $slotType,
44                'forceRequiredSlots' =>
45                    ($slotsRequired === null || $slotsRequired < 1) ? 1 : intval($slotsRequired),
46            ]
47        );
48
49        while ($item = $processData->fetch(\PDO::FETCH_ASSOC)) {
50            $process = new \BO\Zmsentities\Process($item);
51            $process->requests = $calendar->requests;
52            $process->appointments->getFirst()->setDateByString(
53                $process->appointments->getFirst()->date,
54                'Y-m-d H:i:s'
55            );
56
57            if (! isset($scopeList[$process->scope->id])) {
58                $scopeList[$process->scope->id] = $calendar->scopes->getEntity($process->scope->id);
59            }
60
61            $process->scope = $scopeList[$process->scope->id];
62            $process->queue['withAppointment'] = 1;
63            $process->appointments->getFirst()->scope = $process->scope;
64            $processList->addEntity($process);
65        }
66        $processData->closeCursor();
67        unset($dayquery); // drop temporary scope list
68        return $processList;
69    }
70
71
72    public function readReservedProcesses($resolveReferences = 2)
73    {
74        $processList = new Collection();
75        $query = new Query\Process(Query\Base::SELECT);
76        $query
77            ->addResolvedReferences($resolveReferences)
78            ->addEntityMapping()
79            ->addConditionAssigned()
80            ->addConditionIsReserved();
81        $resultData = $this->fetchList($query, new Entity());
82        foreach ($resultData as $process) {
83            if (2 == $resolveReferences) {
84                $process['requests'] = (new Request())->readRequestByProcessId($process->id, $resolveReferences);
85                $process['scope'] = (new Scope())->readEntity($process->getScopeId(), $resolveReferences);
86            }
87            if ($process instanceof Entity) {
88                $processList->addEntity($process);
89            }
90        }
91        return $processList;
92    }
93
94    /**
95     * Insert a new process if there are free slots
96     *
97     * @param \BO\Zmsentities\Process $process
98     * @param \DateTimeInterface $now
99     * @param String $slotType
100     * @param Int $slotsRequired we cannot use process.appointments.0.slotCount, because setting slotsRequired is
101     *        a priviliged operation. Just using the input would be a security flaw to get a wider selection of times
102     *        If slotsRequired = 0, readFreeProcesses() uses the slotsRequired based on request-provider relation
103     */
104    public function writeEntityReserved(
105        \BO\Zmsentities\Process $process,
106        \DateTimeInterface $now,
107        $slotType = "public",
108        $slotsRequired = 0,
109        $resolveReferences = 0,
110        $userAccount = null
111    ) {
112        $process = clone $process;
113        $process->status = 'reserved';
114        $appointment = $process->getAppointments()->getFirst();
115        $slotList = (new Slot())->readByAppointment($appointment, $slotsRequired, (null !== $userAccount));
116        $freeProcessList = $this->readFreeProcesses($process->toCalendar(), $now, $slotType, $slotsRequired);
117
118        if (!$freeProcessList->getAppointmentList()->hasAppointment($appointment) || ! $slotList) {
119            throw new Exception\Process\ProcessReserveFailed();
120        }
121
122        foreach ($slotList as $slot) {
123            if ($process->id > 99999) {
124                $newProcess = clone $process;
125                $newProcess->getFirstAppointment()->setTime($slot->time);
126                $this->writeNewProcess($newProcess, $now, $process->id, 0, true, $userAccount);
127            } elseif ($process->id === 0) {
128                $process = $this->writeNewProcess($process, $now, 0, count($slotList) - 1, true, $userAccount);
129            } else {
130                throw new \Exception("SQL UPDATE error on inserting new $process on $slot");
131            }
132        }
133        $this->writeRequestsToDb($process);
134        return $this->readEntity($process->getId(), new Helper\NoAuth(), $resolveReferences);
135    }
136}