‪TYPO3CMS  ‪main
Connection.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\Common\EventManager;
21 use Doctrine\DBAL\Configuration;
22 use Doctrine\DBAL\Driver;
23 use Doctrine\DBAL\Platforms\PostgreSQL94Platform as PostgreSqlPlatform;
24 use Doctrine\DBAL\Result;
25 use Psr\Log\LoggerAwareInterface;
26 use Psr\Log\LoggerAwareTrait;
31 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
34 
35 class ‪Connection extends \Doctrine\DBAL\Connection implements LoggerAwareInterface
36 {
37  use LoggerAwareTrait;
38 
42  public const ‪PARAM_NULL = \PDO::PARAM_NULL; // 0
43 
47  public const ‪PARAM_INT = \PDO::PARAM_INT; // 1
48 
52  public const ‪PARAM_STR = \PDO::PARAM_STR; // 2
53 
57  public const ‪PARAM_LOB = \PDO::PARAM_LOB; // 3
58 
62  public const ‪PARAM_STMT = \PDO::PARAM_STMT; // 4
63 
67  public const ‪PARAM_BOOL = \PDO::PARAM_BOOL; // 5
68 
70  protected ‪$_expr;
71 
75  private ‪$prepareConnectionCommands = [];
76 
87  public function ‪__construct(array $params, Driver $driver, Configuration $config = null, EventManager $em = null)
88  {
89  parent::__construct($params, $driver, $config, $em);
90  $this->_expr = GeneralUtility::makeInstance(ExpressionBuilder::class, $this);
91  }
92 
96  public function ‪connect(): bool
97  {
98  // Early return if the connection is already open and custom setup has been done.
99  if (!parent::connect()) {
100  return false;
101  }
102 
103  foreach ($this->prepareConnectionCommands as $command) {
104  $this->executeStatement($command);
105  }
106 
107  return true;
108  }
109 
113  public function ‪createQueryBuilder(): QueryBuilder
114  {
115  return GeneralUtility::makeInstance(QueryBuilder::class, $this);
116  }
117 
129  public function ‪quoteIdentifier(‪$identifier): string
130  {
131  if (‪$identifier === '*') {
132  return ‪$identifier;
133  }
134 
135  return parent::quoteIdentifier(‪$identifier);
136  }
137 
145  public function ‪quoteIdentifiers(array $input): array
146  {
147  return array_map([$this, 'quoteIdentifier'], $input);
148  }
149 
158  public function ‪quoteColumnValuePairs(array $input): array
159  {
160  return array_combine($this->‪quoteIdentifiers(array_keys($input)), array_values($input));
161  }
162 
168  protected function ‪quoteColumnTypes(array $input): array
169  {
170  if (!is_string(key($input))) {
171  return $input;
172  }
173 
174  return $this->‪quoteColumnValuePairs($input);
175  }
176 
184  public function ‪escapeLikeWildcards(string $value): string
185  {
186  return addcslashes($value, '_%');
187  }
188 
200  public function ‪insert($tableName, array $data, array $types = []): int
201  {
202  $this->‪ensureDatabaseValueTypes($tableName, $data, $types);
203  return parent::insert(
204  $this->‪quoteIdentifier($tableName),
205  $this->‪quoteColumnValuePairs($data),
206  $this->‪quoteColumnTypes($types)
207  );
208  }
209 
222  public function ‪bulkInsert(string $tableName, array $data, array $columns = [], array $types = []): int
223  {
224  $query = GeneralUtility::makeInstance(BulkInsertQuery::class, $this, $tableName, $columns);
225  foreach ($data as $values) {
226  $this->‪ensureDatabaseValueTypes($tableName, $values, $types);
227  $query->addValues($values, $types);
228  }
229 
230  return $query->execute();
231  }
232 
248  public function ‪select(
249  array $columns,
250  string $tableName,
251  array $identifiers = [],
252  array $groupBy = [],
253  array $orderBy = [],
254  int $limit = 0,
255  int $offset = 0
256  ) {
257  $query = $this->‪createQueryBuilder();
258  $query->select(...$columns)
259  ->from($tableName);
260 
261  foreach ($identifiers as ‪$identifier => $value) {
262  $query->andWhere($query->expr()->eq(‪$identifier, $query->createNamedParameter($value)));
263  }
264 
265  foreach ($orderBy as $fieldName => $order) {
266  $query->addOrderBy($fieldName, $order);
267  }
268 
269  if (!empty($groupBy)) {
270  $query->groupBy(...$groupBy);
271  }
272 
273  if ($limit > 0) {
274  $query->setMaxResults($limit);
275  $query->setFirstResult($offset);
276  }
277 
278  return $query->executeQuery();
279  }
280 
293  public function ‪update($tableName, array $data, array ‪$identifier, array $types = []): int
294  {
295  $this->‪ensureDatabaseValueTypes($tableName, $data, $types);
296  return parent::update(
297  $this->‪quoteIdentifier($tableName),
298  $this->‪quoteColumnValuePairs($data),
299  $this->‪quoteColumnValuePairs($identifier),
300  $this->‪quoteColumnTypes($types)
301  );
302  }
303 
315  public function delete($tableName, array ‪$identifier, array $types = []): int
316  {
317  return parent::delete(
318  $this->‪quoteIdentifier($tableName),
319  $this->‪quoteColumnValuePairs($identifier),
320  $this->‪quoteColumnTypes($types)
321  );
322  }
323 
334  public function ‪truncate(string $tableName, bool $cascade = false): int
335  {
336  return $this->executeStatement(
337  $this->getDatabasePlatform()->getTruncateTableSQL(
338  $this->‪quoteIdentifier($tableName),
339  $cascade
340  )
341  );
342  }
343 
353  public function ‪count(string $item, string $tableName, array $identifiers): int
354  {
355  $query = $this->‪createQueryBuilder();
356  $query->count($item)
357  ->from($tableName);
358 
359  foreach ($identifiers as ‪$identifier => $value) {
360  $query->andWhere($query->expr()->eq(‪$identifier, $query->createNamedParameter($value)));
361  }
362 
363  return (int)$query->executeQuery()->fetchOne();
364  }
365 
374  public function ‪getServerVersion(): string
375  {
376  $version = $this->getDatabasePlatform()->getName();
377  switch ($version) {
378  case 'mysql':
379  case 'pdo_mysql':
380  case 'drizzle_pdo_mysql':
381  $version = 'MySQL';
382  break;
383  case 'postgresql':
384  case 'pdo_postgresql':
385  $version = 'PostgreSQL';
386  break;
387  case 'oci8':
388  case 'pdo_oracle':
389  $version = 'Oracle';
390  break;
391  }
392 
393  // if clause can be removed with Doctrine DBAL 4.
394  if (method_exists($this->getWrappedConnection(), 'getServerVersion')) {
395  $version .= ' ' . $this->getWrappedConnection()->getServerVersion();
396  }
397 
398  return $version;
399  }
400 
404  public function ‪prepareConnection(string $commands)
405  {
406  if (empty($commands)) {
407  return;
408  }
409 
410  $this->prepareConnectionCommands = ‪GeneralUtility::trimExplode(
411  LF,
412  str_replace(
413  '\' . LF . \'',
414  LF,
415  $commands
416  ),
417  true
418  );
419  }
420 
429  public function ‪lastInsertId($tableName = null, string $fieldName = 'uid'): string
430  {
431  $databasePlatform = $this->getDatabasePlatform();
432  if ($databasePlatform instanceof PostgreSqlPlatform) {
433  return parent::lastInsertId(trim(implode('_', [$tableName, $fieldName, 'seq']), '_'));
434  }
435  return (string)parent::lastInsertId($tableName);
436  }
437 
443  public function ‪getExpressionBuilder()
444  {
445  return ‪$this->_expr;
446  }
447 
455  protected function ‪ensureDatabaseValueTypes(string $tableName, array &$data, array &$types): void
456  {
457  // If types are incoming already (meaning they're hand over to insert() for instance), don't auto-set them.
458  $setAllTypes = $types === [];
459  $tableDetails = $this->‪getSchemaInformation()->introspectTable($tableName);
460  array_walk($data, function (&$value, $key) use ($tableDetails, $setAllTypes, &$types) {
461  if ($tableDetails->hasColumn($key)) {
462  $type = $tableDetails->getColumn($key)->getType();
463  if ($setAllTypes) {
464  $types[$key] = $type->getBindingType();
465  }
466  $value = $this->convertToDatabaseValue($value, $type->getName());
467  }
468  });
469  }
470 
474  public function getSchemaInformation(): SchemaInformation
475  {
477  $coreCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('core');
478  return new SchemaInformation($this, $coreCache);
479  }
480 }
‪TYPO3\CMS\Core\Database\Connection\truncate
‪int truncate(string $tableName, bool $cascade=false)
Definition: Connection.php:332
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:916
‪TYPO3\CMS\Core\Database\Connection\PARAM_BOOL
‪const PARAM_BOOL
Definition: Connection.php:67
‪TYPO3\CMS\Core\Database\Connection\ensureDatabaseValueTypes
‪ensureDatabaseValueTypes(string $tableName, array &$data, array &$types)
Definition: Connection.php:453
‪TYPO3\CMS\Core\Database\Connection\quoteColumnValuePairs
‪quoteColumnValuePairs(array $input)
Definition: Connection.php:156
‪TYPO3\CMS\Core\Database\Connection\escapeLikeWildcards
‪string escapeLikeWildcards(string $value)
Definition: Connection.php:182
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:47
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:36
‪TYPO3\CMS\Core\Database\Connection\$_expr
‪ExpressionBuilder $_expr
Definition: Connection.php:69
‪TYPO3\CMS\Core\Database\Connection\bulkInsert
‪int bulkInsert(string $tableName, array $data, array $columns=[], array $types=[])
Definition: Connection.php:220
‪TYPO3\CMS\Core\Database\Connection\getServerVersion
‪getServerVersion()
Definition: Connection.php:372
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:25
‪TYPO3\CMS\Core\Database\Connection\insert
‪int insert($tableName, array $data, array $types=[])
Definition: Connection.php:198
‪TYPO3\CMS\Core\Database\Connection\quoteIdentifiers
‪quoteIdentifiers(array $input)
Definition: Connection.php:143
‪TYPO3\CMS\Core\Database\Schema\SchemaInformation
Definition: SchemaInformation.php:74
‪TYPO3\CMS\Core\Database\Connection\quoteIdentifier
‪string quoteIdentifier($identifier)
Definition: Connection.php:127
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:52
‪TYPO3\CMS\Core\Database\Connection\update
‪int update($tableName, array $data, array $identifier, array $types=[])
Definition: Connection.php:291
‪TYPO3\CMS\Core\Database\Connection\getSchemaInformation
‪getSchemaInformation()
Definition: Connection.php:472
‪TYPO3\CMS\Core\Database\Connection\select
‪Result select(array $columns, string $tableName, array $identifiers=[], array $groupBy=[], array $orderBy=[], int $limit=0, int $offset=0)
Definition: Connection.php:246
‪TYPO3\CMS\Core\Database\Connection\PARAM_STMT
‪const PARAM_STMT
Definition: Connection.php:62
‪TYPO3\CMS\Core\Database\Connection\getExpressionBuilder
‪ExpressionBuilder getExpressionBuilder()
Definition: Connection.php:441
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪createQueryBuilder()
Definition: Connection.php:111
‪TYPO3\CMS\Core\Database\Connection\lastInsertId
‪lastInsertId($tableName=null, string $fieldName='uid')
Definition: Connection.php:427
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Database\Connection\count
‪int count(string $item, string $tableName, array $identifiers)
Definition: Connection.php:351
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Database\Connection\prepareConnection
‪prepareConnection(string $commands)
Definition: Connection.php:402
‪TYPO3\CMS\Core\Database\Connection\connect
‪connect()
Definition: Connection.php:94
‪TYPO3\CMS\Core\Database\Query\BulkInsertQuery
Definition: BulkInsertQuery.php:35
‪TYPO3\CMS\Core\Database\Connection\PARAM_NULL
‪const PARAM_NULL
Definition: Connection.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Database\Connection\__construct
‪__construct(array $params, Driver $driver, Configuration $config=null, EventManager $em=null)
Definition: Connection.php:85
‪TYPO3\CMS\Core\Database\Connection\quoteColumnTypes
‪quoteColumnTypes(array $input)
Definition: Connection.php:166
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\Database
Definition: Connection.php:18
‪TYPO3\CMS\Core\Database\Connection\$prepareConnectionCommands
‪array $prepareConnectionCommands
Definition: Connection.php:73
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:57