Issues (13)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Infrastructure/DBAL/DbalShiftMapper.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
$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
$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
$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
$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