Completed
Push — 15.x ( cfc6bd...d1c769 )
by Tim
02:27
created

AbstractBaseProcessor::firstKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 0
cts 8
cp 0
rs 9.7998
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * TechDivision\Import\Actions\Processors\AbstractBaseProcessor
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Actions\Processors;
22
23
use TechDivision\Import\Utils\EntityStatus;
24
25
/**
26
 * An abstract processor implementation provide basic CRUD functionality.
27
 *
28
 * @author    Tim Wagner <[email protected]>
29
 * @copyright 2016 TechDivision GmbH <[email protected]>
30
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
31
 * @link      https://github.com/techdivision/import
32
 * @link      http://www.techdivision.com
33
 */
34
abstract class AbstractBaseProcessor extends AbstractProcessor
35
{
36
37
    /**
38
     * The array with the statements to be prepared.
39
     *
40
     * @var array
41
     */
42
    protected $statements = array();
43
44
    /**
45
     * The array with the prepared statements.
46
     *
47
     * @var array
48
     */
49
    protected $preparedStatements = array();
50
51
    /**
52
     * The default statement name.
53
     *
54
     * @var string
55
     */
56
    protected $defaultStatementName;
57
58
    /**
59
     * Return's the array with the SQL statements that has to be prepared.
60
     *
61
     * @return array The SQL statements to be prepared
62
     */
63
    protected function getStatements()
64
    {
65
        return $this->statements;
66
    }
67
68
    /**
69
     * Add's the prepared statement.
70
     *
71
     * @param string        $name              The unique name of the prepared statement
72
     * @param \PDOStatement $preparedStatement The prepared statement
73
     *
74
     * @return void
75
     */
76
    protected function addPreparedStatement($name, \PDOStatement $preparedStatement)
77
    {
78
        $this->preparedStatements[$name] = $preparedStatement;
79
    }
80
81
    /**
82
     * Return's the prepared statement with the passed name or the default one.
83
     *
84
     * @param string|null $name        The name of the prepared statement to return
85
     * @param string|null $defaultName The name of the default prepared statement
86
     *
87
     * @return \PDOStatement The prepared statement
88
     */
89
    protected function getPreparedStatement($name = null, $defaultName = null)
90
    {
91
92
        // try to load the prepared statement, or use the default one
93
        if (isset($this->preparedStatements[$name])) {
94
            return $this->preparedStatements[$name];
95
        }
96
97
        // return the default prepared statement
98
        return $this->preparedStatements[$defaultName];
99
    }
100
101
    /**
102
     * Qeuery whether or not the prepared statement is available or not.
103
     *
104
     * @param string $name The nqme of the prepared statement
105
     *
106
     * @return boolean TRUE if the prepared statement is available, else FALSE
107
     */
108
    protected function hasPreparedStatement($name)
109
    {
110
        return isset($this->preparedStatements[$name]);
111
    }
112
113
    /**
114
     * The array with the prepared statements.
115
     *
116
     * @return array The prepared statments
117
     */
118
    protected function getPreparedStatements()
119
    {
120
        return $this->preparedStatements;
121
    }
122
123
    /**
124
     * Prepare's and return's the passed row by removing the
125
     * entity status.
126
     *
127
     * @param array $row The row to prepare
128
     *
129
     * @return array The prepared row
130
     */
131
    protected function prepareRow(array $row)
132
    {
133
134
        // remove the entity status
135
        unset($row[EntityStatus::MEMBER_NAME]);
136
137
        // return the prepared row
138
        return $row;
139
    }
140
141
    /**
142
     * Return's the name of the processor's default statement.
143
     *
144
     * @return string The statement name
145
     */
146
    public function getDefaultStatementName()
147
    {
148
        return $this->defaultStatementName;
149
    }
150
151
    /**
152
     * Implements the CRUD functionality the processor is responsible for,
153
     * can be one of CREATE, READ, UPDATE or DELETE a entity.
154
     *
155
     * @param array       $row                  The row to persist
156
     * @param string|null $name                 The name of the prepared statement that has to be executed
157
     * @param string|null $primaryKeyMemberName The primary key member name of the entity to use
158
     *
159
     * @return void
160
     */
161
    public function execute($row, $name = null, $primaryKeyMemberName = null)
162
    {
163
        try {
164
            // finally execute the prepared statement
165
            $this->getPreparedStatement($name, $this->getDefaultStatementName())->execute($this->prepareRow($row));
166
        } catch (\PDOException $pdoe) {
167
            // initialize the SQL statement with the placeholders
168
            $sql = $this->getPreparedStatement($name, $this->getDefaultStatementName())->queryString;
169
170
            // replace the placeholders with the values
171
            foreach ($row as $key => $value) {
172
                $sql = str_replace(sprintf(':%s', $key), $value, $sql);
173
            }
174
175
            // prepare the error message itself
176
            $message = sprintf('%s when executing SQL "%s"', $pdoe->getMessage(), preg_replace('/\r\n\s\s+/', ' ', $sql));
177
178
            // re-throw the exception with a more detailed error message
179
            throw new \PDOException($message, null, $pdoe);
180
        }
181
    }
182
183
    /**
184
     * Initializes the proceessor with the prepared statements.
185
     *
186
     * @return void
187
     */
188
    public function init()
189
    {
190
191
        // load the statements
192
        $statements = $this->getStatements();
193
194
        // initialize the default statement name
195
        $this->defaultStatementName = $this->firstKey($statements);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->firstKey($statements) can also be of type integer. However, the property $defaultStatementName is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
196
197
        foreach ($statements as $name => $statement) {
198
            $this->addPreparedStatement($name, $this->getConnection()->prepare($statement));
199
        }
200
    }
201
202
    /**
203
     * Returns the first key of the passed array.
204
     *
205
     * This method has been used instead of the PHP function array_key_first, because
206
     * this function will be available with PHP >= 7.3.0.
207
     *
208
     * @param array $array The array to return the first key for
209
     *
210
     * @return mixed|NULL The first key or NULL
211
     * @link https://www.php.net/array_key_first
212
     */
213
    private function firstKey(array $array)
214
    {
215
216
        // load the array keys
217
        $keys = array_keys($array);
218
219
        // try to load and return the first key
220
        foreach($keys as $key) {
221
            return $key;
222
        }
223
224
        // return NULL otherwise
225
        return null;
226
    }
227
}
228