DbalShiftMapper::doLoad()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 9.392
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace Scheduler\Infrastructure\DBAL;
4
5
use DateTimeImmutable;
6
use DateTimeInterface;
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\Driver\PDOStatement;
9
use Doctrine\DBAL\Statement;
10
use Doctrine\DBAL\Types\Type;
11
use Scheduler\Domain\Model\Shift\Shift;
12
use Scheduler\Domain\Model\Shift\ShiftMapper;
13
use Scheduler\Domain\Model\User\NullUser;
14
use Scheduler\Domain\Model\User\User;
15
use Scheduler\Domain\Model\User\UserMapper;
16
17
class DbalShiftMapper extends DbalMapper implements ShiftMapper
18
{
19
    const SHIFT_COLUMNS = "s.id, s.manager_id, s.employee_id, s.break,
20
                           s.start_time, s.end_time, s.created_at, s.updated_at";
21
22
    const MANAGER_COLUMNS = "m.name as m_name, m.role as m_role, m.email as m_email,
23
                             m.phone as m_phone, m.created_at as m_created_at,
24
                             m.updated_at as m_updated_at";
25
26
    const EMPLOYEE_COLUMNS = "e.name as e_name, e.role as e_role, e.email as e_email,
27
                              e.phone as e_phone, e.created_at as e_created_at,
28
                              e.updated_at as e_updated_at";
29
30
    private $userMapper;
31
32
    protected static function findStatement()
33
    {
34
        return sprintf(self::findWithAssociations(), "s.id = ?");
35
    }
36
37
    protected static function findByEmployeeIdStatement()
38
    {
39
        return sprintf(self::findWithAssociations(), "s.employee_id = ?");
40
    }
41
42
    protected static function findInTimePeriodStatement()
43
    {
44
        return sprintf(
45
            self::findWithAssociations(),
46
            "(start_time BETWEEN :start AND :end
47
                OR end_time BETWEEN :start and :end)"
48
        );
49
    }
50
51
    protected static function findInTimePeriodByEmployeeIdStatement()
52
    {
53
        return self::findInTimePeriodStatement() . " and s.employee_id = :employee_id";
54
    }
55
56
    protected static function findOpenShiftsStatement()
57
    {
58
        return sprintf(self::findWithManagerAssociation(), "s.employee_id is null");
59
    }
60
61
    protected static function findWithManagerAssociation()
62
    {
63
        return sprintf(
64
            "SELECT %s, %s
65
             FROM shifts s, users m
66
             WHERE %%s and s.manager_id = m.id",
67
            self::SHIFT_COLUMNS,
68
            self::MANAGER_COLUMNS
69
        );
70
    }
71
72
    protected static function findWithAssociations()
73
    {
74
        return sprintf(
75
            "SELECT %s, %s, %s
76
             FROM shifts s
77
                LEFT JOIN users m ON (s.manager_id = m.id)
78
                LEFT JOIN users e on (s.employee_id = e.id)
79
             WHERE %%s",
80
            self::SHIFT_COLUMNS,
81
            self::MANAGER_COLUMNS,
82
            self::EMPLOYEE_COLUMNS
83
        );
84
    }
85
86
    protected static function insertStatement()
87
    {
88
        return "INSERT INTO shifts VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
89
    }
90
91
    protected static function updateStatement()
92
    {
93
        return "UPDATE shifts
94
                SET employee_id = ?, start_time = ?, end_time = ?, updated_at = ?
95
                WHERE id = ?";
96
    }
97
98
    public function __construct(Connection $db, UserMapper $userMapper)
99
    {
100
        parent::__construct($db);
101
        $this->userMapper = $userMapper;
102
    }
103
104
    public function find($id)
105
    {
106
        if (! is_int($id)) {
107
            throw new \InvalidArgumentException("The id must be an integer");
108
        }
109
110
        return $this->abstractFind($id);
111
    }
112
113
    public function findOpenShifts()
114
    {
115
        $statement = $this->db->prepare(self::findOpenShiftsStatement());
116
        $statement->execute();
117
118
        return $this->loadAll($statement);
0 ignored issues
show
Compatibility introduced by
$statement of type object<Doctrine\DBAL\Driver\Statement> is not a sub-type of object<Doctrine\DBAL\Statement>. It seems like you assume a concrete implementation of the interface Doctrine\DBAL\Driver\Statement to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
119
    }
120
121 View Code Duplication
    public function findShiftsByEmployeeId($employee_id)
122
    {
123
        $statement = $this->db->prepare(self::findByEmployeeIdStatement());
124
        $statement->bindValue(1, $employee_id, \PDO::PARAM_INT);
125
        $statement->execute();
126
127
        return $this->loadAll($statement);
0 ignored issues
show
Compatibility introduced by
$statement of type object<Doctrine\DBAL\Driver\Statement> is not a sub-type of object<Doctrine\DBAL\Statement>. It seems like you assume a concrete implementation of the interface Doctrine\DBAL\Driver\Statement to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
128
    }
129
130 View Code Duplication
    public function findShiftsInTimePeriod(DateTimeInterface $start, DateTimeInterface $end)
131
    {
132
        $statement = $this->db->prepare(self::findInTimePeriodStatement());
133
        $statement->bindValue(":start", $start, Type::DATETIME);
134
        $statement->bindValue(":end", $end, Type::DATETIME);
135
        $statement->execute();
136
137
        return $this->loadAll($statement);
0 ignored issues
show
Compatibility introduced by
$statement of type object<Doctrine\DBAL\Driver\Statement> is not a sub-type of object<Doctrine\DBAL\Statement>. It seems like you assume a concrete implementation of the interface Doctrine\DBAL\Driver\Statement to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
138
    }
139
140 View Code Duplication
    public function findShiftsInTimePeriodByEmployeeId(DateTimeInterface $start, DateTimeInterface $end, $employeeId)
141
    {
142
        $statement = $this->db->prepare(self::findInTimePeriodByEmployeeIdStatement());
143
        $statement->bindValue(":start", $start, Type::DATETIME);
144
        $statement->bindValue(":end", $end, Type::DATETIME);
145
        $statement->bindValue(":employee_id", $employeeId, \PDO::PARAM_INT);
146
        $statement->execute();
147
148
        return $this->loadAll($statement);
0 ignored issues
show
Compatibility introduced by
$statement of type object<Doctrine\DBAL\Driver\Statement> is not a sub-type of object<Doctrine\DBAL\Statement>. It seems like you assume a concrete implementation of the interface Doctrine\DBAL\Driver\Statement to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
149
    }
150
151
    protected function doLoad($id, array $resultSet)
152
    {
153
        $id = (int) $resultSet["id"];
154
        $break = (float) $resultSet["break"];
155
        $start = new DateTimeImmutable($resultSet["start_time"]);
156
        $end = new DateTimeImmutable($resultSet["end_time"]);
157
        $created = new DateTimeImmutable($resultSet["created_at"]);
158
        $updated = new DateTimeImmutable($resultSet["updated_at"]);
159
160
        $manager = $this->userMapper->load([
161
            "id" => $resultSet["manager_id"],
162
            "name" => $resultSet["m_name"],
163
            "role" => $resultSet["m_role"],
164
            "email" => $resultSet["m_email"],
165
            "phone" => $resultSet["m_phone"],
166
            "created_at" => $resultSet["m_created_at"],
167
            "updated_at" => $resultSet["m_updated_at"]
168
        ]);
169
170
        $employee = isset($resultSet["employee_id"])
171
            ? $this->userMapper->load([
172
                "id" => $resultSet["employee_id"],
173
                "name" => $resultSet["e_name"],
174
                "role" => $resultSet["e_role"],
175
                "email" => $resultSet["e_email"],
176
                "phone" => $resultSet["e_phone"],
177
                "created_at" => $resultSet["e_created_at"],
178
                "updated_at" => $resultSet["e_updated_at"]
179
              ])
180
            : new NullUser();
181
182
        return new Shift($id, $manager, $employee, $break, $start, $end, $created, $updated);
183
    }
184
185
    /**
186
     * Insert a Shift instance into the database.
187
     *
188
     * @param  Shift  $shift The Shift instance to insert
189
     *
190
     * @return int           The id of the inserted Shift
191
     */
192
    public function insert(Shift $shift)
193
    {
194
        return $this->abstractInsert($shift);
195
    }
196
197
    /**
198
     * Bind query parameters and execute insert statement
199
     *
200
     * @param  Shift     $shift
201
     * @param  Statement $insertStatement The prepared insert statement
202
     *
203
     * @return int                        The id of the inserted row
204
     */
205
    protected function doInsert($shift, Statement $insertStatement)
206
    {
207
        $insertStatement->bindValue(1, null);
208
        $insertStatement->bindValue(2, $shift->getManager()->getId(), \PDO::PARAM_INT);
209
        $insertStatement->bindValue(3, $shift->getEmployee()->getId(), \PDO::PARAM_INT);
210
        $insertStatement->bindValue(4, $shift->getBreak(), \PDO::PARAM_STR);
211
        $insertStatement->bindValue(5, $shift->getStartTime(), Type::DATETIME);
212
        $insertStatement->bindValue(6, $shift->getEndTime(), Type::DATETIME);
213
        $insertStatement->bindValue(7, $shift->getCreated(), Type::DATETIME);
214
        $insertStatement->bindValue(8, $shift->getUpdated(), Type::DATETIME);
215
        $insertStatement->execute();
216
    }
217
218
    /**
219
     * Update a Shift instance
220
     *
221
     * @param  Shift  $shift
222
     *
223
     * @return void
224
     */
225
    public function update(Shift $shift)
226
    {
227
        $updateStatement = $this->db->prepare(self::updateStatement());
228
        $updateStatement->bindValue(1, $shift->getEmployee()->getId(), \PDO::PARAM_INT);
229
        $updateStatement->bindValue(2, $shift->getStartTime(), Type::DATETIME);
230
        $updateStatement->bindValue(3, $shift->getEndTime(), Type::DATETIME);
231
        $updateStatement->bindValue(4, new DateTimeImmutable(), Type::DATETIME);
232
        $updateStatement->bindValue(5, $shift->getId(), \PDO::PARAM_INT);
233
        $updateStatement->execute();
234
    }
235
}
236