SlayerBirden /
datamigration
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
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 Maketok\DataMigration\Storage\Db; |
||
| 4 | |||
| 5 | use Doctrine\DBAL\Driver as DriverInterface; |
||
| 6 | use Doctrine\DBAL\Driver\PDOMySql\Driver; |
||
| 7 | use Doctrine\DBAL\Schema\Schema; |
||
| 8 | use Maketok\DataMigration\Storage\Exception\ParsingException; |
||
| 9 | |||
| 10 | class DBALMysqlResource extends AbstractDBALResource |
||
| 11 | { |
||
| 12 | /** |
||
| 13 | * @var DriverInterface |
||
| 14 | */ |
||
| 15 | private $driver; |
||
| 16 | |||
| 17 | /** |
||
| 18 | * {@inheritdoc} |
||
| 19 | */ |
||
| 20 | 31 | protected function getDriverOptions() |
|
| 21 | { |
||
| 22 | return [ |
||
| 23 | 31 | \PDO::MYSQL_ATTR_LOCAL_INFILE => true, |
|
| 24 | 31 | \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' |
|
| 25 | 31 | ]; |
|
| 26 | } |
||
| 27 | |||
| 28 | /** |
||
| 29 | * {@inheritdoc} |
||
| 30 | */ |
||
| 31 | 2 | public function deleteUsingTempPK($deleteTable, $tmpTable, $primaryKey = 'id') |
|
| 32 | { |
||
| 33 | 2 | $sql = $this->getDeleteUsingTempPkSql($deleteTable, $tmpTable, $primaryKey); |
|
| 34 | 2 | return $this->connection->executeUpdate($sql); |
|
| 35 | } |
||
| 36 | |||
| 37 | /** |
||
| 38 | * @param string $deleteTable |
||
| 39 | * @param string $tmpTable |
||
| 40 | * @param string|string[] $primaryKey |
||
| 41 | * @return string |
||
| 42 | */ |
||
| 43 | 3 | public function getDeleteUsingTempPkSql($deleteTable, $tmpTable, $primaryKey) |
|
| 44 | { |
||
| 45 | 3 | $deleteTable = $this->connection->quoteIdentifier($deleteTable); |
|
| 46 | 3 | $tmpTable = $this->connection->quoteIdentifier($tmpTable); |
|
| 47 | 3 | if (!is_array($primaryKey)) { |
|
| 48 | 2 | $primaryKey = [$primaryKey]; |
|
| 49 | 2 | } |
|
| 50 | 3 | $primaryKey = array_map([$this->connection, 'quoteIdentifier'], $primaryKey); |
|
| 51 | 3 | $conditionParts = []; |
|
| 52 | 3 | foreach ($primaryKey as $key) { |
|
| 53 | 3 | $conditionParts[] = "`main_table`.$key=`tmp_table`.$key"; |
|
| 54 | 3 | } |
|
| 55 | 3 | $condition = implode('AND', $conditionParts); |
|
| 56 | return <<<MYSQL |
||
| 57 | DELETE main_table FROM $deleteTable AS main_table |
||
| 58 | 3 | JOIN $tmpTable AS tmp_table ON $condition |
|
| 59 | 3 | MYSQL; |
|
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * {@inheritdoc} |
||
| 64 | * @param string $delimiter |
||
| 65 | * @param string $enclosure |
||
| 66 | * @param string $escape |
||
| 67 | * @param string $termination |
||
| 68 | * @param bool $optionallyEnclosed |
||
| 69 | */ |
||
| 70 | 6 | public function loadData( |
|
|
0 ignored issues
–
show
|
|||
| 71 | $table, |
||
| 72 | $file, |
||
| 73 | $local = false, |
||
| 74 | array $columns = [], |
||
| 75 | array $set = [], |
||
| 76 | $delimiter = ",", |
||
| 77 | $enclosure = '"', |
||
| 78 | $escape = '\\', |
||
| 79 | $termination = '\n', |
||
| 80 | $optionallyEnclosed = true |
||
| 81 | ) { |
||
| 82 | 6 | $sql = $this->getLoadDataSql($table, $file, $local, $columns, $set, $delimiter, $enclosure, |
|
| 83 | 6 | $escape, $termination, $optionallyEnclosed); |
|
| 84 | 6 | return $this->connection->executeUpdate($sql); |
|
| 85 | } |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @param string $table |
||
| 89 | * @param string $file |
||
| 90 | * @param bool|false $local |
||
| 91 | * @param array $columns |
||
| 92 | * @param array $set |
||
| 93 | * @param string $delimiter |
||
| 94 | * @param string $enclosure |
||
| 95 | * @param string $escape |
||
| 96 | * @param string $termination |
||
| 97 | * @param bool|true $optionallyEnclosed |
||
| 98 | * @return string |
||
| 99 | */ |
||
| 100 | 7 | public function getLoadDataSql( |
|
|
0 ignored issues
–
show
This method has 10 parameters which exceeds the configured maximum of 10.
A high number of parameters is generally an indication that you should consider creating a dedicated object for the parameters. Let’s take a look at an example: <?php
class SomeClass
{
public function doSomething(A $a, B $b, C $c, D $d, E $e, F $f)
{
// ..
}
}
class AnotherClass
{
public function doSomething(A $a, B $b, C $c, D $d, E $e, F $f)
{
// ...
}
}
could be refactored to: class Context
{
private $a;
private $b;
private $c;
private $d;
private $e;
private $f;
public function __construct(A $a, B $b, C $c, D $d, E $e, F $f)
{
// ...
}
}
class SomeClass
{
public function doSomething(Context $context)
{
// ...
}
}
class AnotherClass
{
public function doSomething(Context $context)
{
// ...
}
}
Loading history...
|
|||
| 101 | $table, |
||
| 102 | $file, |
||
| 103 | $local = false, |
||
| 104 | array $columns = [], |
||
| 105 | array $set = [], |
||
| 106 | $delimiter = ",", |
||
| 107 | $enclosure = '"', |
||
| 108 | $escape = "\\", |
||
| 109 | $termination = '\n', |
||
| 110 | $optionallyEnclosed = true |
||
| 111 | ) { |
||
| 112 | 7 | $localKey = $local ? 'LOCAL' : ''; |
|
| 113 | 7 | $table = $this->connection->quoteIdentifier($table); |
|
| 114 | 7 | $optionalKey = $optionallyEnclosed ? 'OPTIONALLY' : ''; |
|
| 115 | 7 | if (!empty($columns)) { |
|
| 116 | 1 | $columns = '(' . implode(',', $columns) . ')'; |
|
| 117 | 1 | } else { |
|
| 118 | 6 | $columns = ''; |
|
| 119 | } |
||
| 120 | 7 | if (!empty($set)) { |
|
| 121 | 1 | $setParts = []; |
|
| 122 | 1 | foreach ($set as $key => $val) { |
|
| 123 | 1 | $setParts[] = "$key=$val"; |
|
| 124 | 1 | } |
|
| 125 | 1 | $set = 'SET ' . implode(',', $setParts); |
|
| 126 | 1 | } else { |
|
| 127 | 6 | $set = ''; |
|
| 128 | } |
||
| 129 | 7 | $escape = $this->connection->quote($escape); |
|
| 130 | return <<<MYSQL |
||
| 131 | 7 | LOAD DATA $localKey INFILE '$file' |
|
| 132 | 7 | INTO TABLE $table |
|
| 133 | CHARACTER SET UTF8 |
||
| 134 | FIELDS |
||
| 135 | 7 | TERMINATED BY '$delimiter' |
|
| 136 | 7 | $optionalKey ENCLOSED BY '$enclosure' |
|
| 137 | 7 | ESCAPED BY $escape |
|
| 138 | LINES |
||
| 139 | 7 | TERMINATED BY '$termination' |
|
| 140 | 7 | $columns |
|
| 141 | 7 | $set |
|
| 142 | 7 | MYSQL; |
|
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * {@inheritdoc} |
||
| 147 | */ |
||
| 148 | 9 | public function move( |
|
| 149 | $fromTable, |
||
| 150 | $toTable, |
||
| 151 | array $columns = [], |
||
| 152 | array $conditions = [], |
||
| 153 | array $orderBy = [], |
||
| 154 | $dir = 'ASC' |
||
| 155 | ) { |
||
| 156 | 9 | $sql = $this->getMoveSql($fromTable, $toTable, $columns, $conditions, $orderBy, $dir); |
|
| 157 | 9 | return $this->connection->executeUpdate($sql); |
|
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * @param string $fromTable |
||
| 162 | * @param string $toTable |
||
| 163 | * @param array $columns |
||
| 164 | * @param array $conditions |
||
| 165 | * @param array $orderBy |
||
| 166 | * @param string $dir |
||
| 167 | * @return string |
||
| 168 | */ |
||
| 169 | 18 | public function getMoveSql( |
|
| 170 | $fromTable, |
||
| 171 | $toTable, |
||
| 172 | array $columns = [], |
||
| 173 | array $conditions = [], |
||
| 174 | array $orderBy = [], |
||
| 175 | $dir = 'ASC' |
||
| 176 | ) { |
||
| 177 | 18 | $selectColumns = '*'; |
|
| 178 | 18 | $onDuplicate = ''; |
|
| 179 | 18 | $fromTable = $this->connection->quoteIdentifier($fromTable); |
|
| 180 | 18 | $toTable = $this->connection->quoteIdentifier($toTable); |
|
| 181 | 18 | if (!empty($columns)) { |
|
| 182 | 18 | $columns = array_map([$this->connection, 'quoteIdentifier'], $columns); |
|
| 183 | 18 | $selectColumns = implode(',', $columns); |
|
| 184 | 18 | $duplicateParts = array_map(function ($var) { |
|
| 185 | 18 | return "$var=VALUES($var)"; |
|
| 186 | 18 | }, $columns); |
|
| 187 | 18 | $columns = '(' . $selectColumns . ')'; |
|
| 188 | 18 | $onDuplicate = 'ON DUPLICATE KEY UPDATE ' . implode(',', $duplicateParts); |
|
| 189 | 18 | } else { |
|
| 190 | $columns = ''; |
||
| 191 | } |
||
| 192 | 18 | if (!empty($conditions)) { |
|
| 193 | 10 | $conditionParts = []; |
|
| 194 | 10 | foreach ($conditions as $key => $val) { |
|
| 195 | 10 | $key = $this->connection->quoteIdentifier($key); |
|
| 196 | 10 | if (is_array($val)) { |
|
| 197 | 9 | $conditionParts[] = $this->getParsedCondition("$fromTable.$key", $val); |
|
| 198 | 5 | } else { |
|
| 199 | 1 | $val = $this->connection->quote($val); |
|
| 200 | 1 | $conditionParts[] = "$fromTable.$key=$val"; |
|
| 201 | } |
||
| 202 | 6 | } |
|
| 203 | 6 | $conditions = 'WHERE ' . implode('AND', $conditionParts); |
|
| 204 | 6 | } else { |
|
| 205 | 8 | $conditions = ''; |
|
| 206 | } |
||
| 207 | 14 | if (!empty($orderBy)) { |
|
| 208 | 8 | $orderBy = array_map([$this->connection, 'quoteIdentifier'], $orderBy); |
|
| 209 | 8 | $orderBy = implode(',', $orderBy); |
|
| 210 | 8 | } else { |
|
| 211 | 6 | $orderBy = 'NULL'; |
|
| 212 | } |
||
| 213 | return <<<MYSQL |
||
| 214 | 14 | INSERT INTO $toTable $columns |
|
| 215 | 14 | SELECT $selectColumns FROM $fromTable |
|
| 216 | 14 | $conditions |
|
| 217 | 14 | ORDER BY $orderBy $dir |
|
| 218 | 14 | $onDuplicate |
|
| 219 | 14 | MYSQL; |
|
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Return valid condition |
||
| 224 | * @param $column |
||
| 225 | * @param array $value |
||
| 226 | * @throws ParsingException |
||
| 227 | * @return string |
||
| 228 | */ |
||
| 229 | 9 | protected function getParsedCondition($column, array $value) |
|
| 230 | { |
||
| 231 | 9 | if (count($value) > 1) { |
|
| 232 | 1 | throw new ParsingException("Condition should contain only 1 element"); |
|
| 233 | } |
||
| 234 | 8 | $operation = key($value); |
|
| 235 | 8 | $actualValue = current($value); |
|
| 236 | switch ($operation) { |
||
| 237 | 8 | case 'neq': |
|
| 238 | 1 | $string = "$column<>{$this->connection->quote($actualValue)}"; |
|
| 239 | 1 | break; |
|
| 240 | 7 | case 'eq': |
|
| 241 | 1 | $string = "$column={$this->connection->quote($actualValue)}"; |
|
| 242 | 1 | break; |
|
| 243 | 6 | case 'in': |
|
| 244 | 2 | if (!is_array($actualValue)) { |
|
| 245 | 1 | throw new ParsingException("Can not use 'in' operation with non array."); |
|
| 246 | } |
||
| 247 | 1 | $actualValue = array_map([$this->connection, 'quote'], $actualValue); |
|
| 248 | 1 | $glued = implode(',', $actualValue); |
|
| 249 | 1 | $string = "$column in ($glued)"; |
|
| 250 | 1 | break; |
|
| 251 | 4 | case 'nin': |
|
| 252 | 3 | if (!is_array($actualValue)) { |
|
| 253 | 1 | throw new ParsingException("Can not use 'nin' operation with non array."); |
|
| 254 | } |
||
| 255 | 2 | $actualValue = array_map([$this->connection, 'quote'], $actualValue); |
|
| 256 | 2 | $glued = implode(',', $actualValue); |
|
| 257 | 2 | $string = "$column not in ($glued)"; |
|
| 258 | 2 | break; |
|
| 259 | 1 | default: |
|
| 260 | 1 | throw new ParsingException(sprintf("Could not resolve condition operation %s.", $operation)); |
|
| 261 | 1 | } |
|
| 262 | 5 | return $string; |
|
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * {@inheritdoc} |
||
| 267 | */ |
||
| 268 | 3 | public function dumpData($table, array $columns = [], $limit = 1000, $offset = 0) |
|
| 269 | { |
||
| 270 | 3 | $sql = $this->getDumpDataSql($table, $columns); |
|
| 271 | 3 | $stmt = $this->connection->prepare($sql); |
|
| 272 | 3 | $stmt->bindValue(1, $limit, \PDO::PARAM_INT); |
|
| 273 | 3 | $stmt->bindValue(2, $offset, \PDO::PARAM_INT); |
|
| 274 | 3 | $res = $stmt->execute(); |
|
| 275 | 3 | if ($res === false) { |
|
| 276 | return false; |
||
| 277 | } |
||
| 278 | 3 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); |
|
| 279 | } |
||
| 280 | |||
| 281 | /** |
||
| 282 | * @param string $table |
||
| 283 | * @param array $columns |
||
| 284 | * @return string |
||
| 285 | */ |
||
| 286 | 4 | public function getDumpDataSql($table, array $columns = []) |
|
| 287 | { |
||
| 288 | 4 | $table = $this->connection->quoteIdentifier($table); |
|
| 289 | 4 | if (!empty($columns)) { |
|
| 290 | 4 | $columns = array_map([$this->connection, 'quoteIdentifier'], $columns); |
|
| 291 | 4 | $columns = implode(',', $columns); |
|
| 292 | 4 | } else { |
|
| 293 | 1 | $columns = '*'; |
|
| 294 | } |
||
| 295 | return <<<MYSQL |
||
| 296 | 4 | SELECT $columns FROM $table |
|
| 297 | 4 | LIMIT ? OFFSET ? |
|
| 298 | 4 | MYSQL; |
|
| 299 | } |
||
| 300 | |||
| 301 | /** |
||
| 302 | * {@inheritdoc} |
||
| 303 | */ |
||
| 304 | 11 | public function createTmpTable($name, array $columns) |
|
| 305 | { |
||
| 306 | 11 | $sql = $this->getCreateTableSql($name, $columns); |
|
| 307 | 11 | foreach ($sql as $directive) { |
|
| 308 | 11 | $this->connection->executeUpdate($directive); |
|
| 309 | 11 | } |
|
| 310 | 11 | return true; |
|
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * @param string $name |
||
| 315 | * @param array $columns |
||
| 316 | * @return array |
||
| 317 | * @throws \Doctrine\DBAL\DBALException |
||
| 318 | */ |
||
| 319 | 12 | public function getCreateTableSql($name, array $columns) |
|
| 320 | { |
||
| 321 | 12 | $schema = new Schema(); |
|
| 322 | 12 | $table = $schema->createTable($name); |
|
| 323 | 12 | foreach ($columns as $column => $definition) { |
|
| 324 | 12 | if (is_array($definition)) { |
|
| 325 | 8 | $type = array_shift($definition); |
|
| 326 | 8 | $options = array_shift($definition); |
|
| 327 | 8 | } else { |
|
| 328 | 5 | $type = $definition; |
|
| 329 | 5 | $options = []; |
|
| 330 | } |
||
| 331 | 12 | $table->addColumn($column, $type, $options); |
|
| 332 | 12 | } |
|
| 333 | 12 | if (!$this->config['db_debug']) { |
|
| 334 | 12 | $table->addOption('temporary', true); |
|
|
0 ignored issues
–
show
true is of type boolean, but the function expects a string.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 335 | 12 | } |
|
| 336 | 12 | return $this->connection->getDatabasePlatform()->getCreateTableSQL($table); |
|
| 337 | } |
||
| 338 | |||
| 339 | /** |
||
| 340 | * {@inheritdoc} |
||
| 341 | */ |
||
| 342 | 31 | protected function getDriver() |
|
| 343 | { |
||
| 344 | 31 | if (is_null($this->driver)) { |
|
| 345 | 31 | $driver = $this->config['db_driver']; |
|
| 346 | 31 | if ($driver && $driver instanceof DriverInterface) { |
|
| 347 | 13 | $this->driver = $driver; |
|
| 348 | 13 | } else { |
|
| 349 | 18 | $this->driver = new Driver(); |
|
| 350 | } |
||
| 351 | 31 | } |
|
| 352 | 31 | return $this->driver; |
|
| 353 | } |
||
| 354 | } |
||
| 355 |
A high number of parameters is generally an indication that you should consider creating a dedicated object for the parameters.
Let’s take a look at an example:
could be refactored to: