Skip to content

Commit

Permalink
Merge branch '4.x' into feature/canonical
Browse files Browse the repository at this point in the history
  • Loading branch information
leofeyer committed Nov 4, 2021
2 parents e6f6fbd + 16f92d3 commit 2dd6e97
Show file tree
Hide file tree
Showing 6 changed files with 404 additions and 53 deletions.
5 changes: 4 additions & 1 deletion core-bundle/src/Resources/contao/drivers/DC_Table.php
Expand Up @@ -3837,7 +3837,10 @@ public function ajaxTreeView($id, $level)
protected function generateTree($table, $id, $arrPrevNext, $blnHasSorting, $intMargin=0, $arrClipboard=null, $blnCircularReference=false, $protectedPage=false, $blnNoRecursion=false, $arrFound=array())
{
// Must be either visible in the root trail or allowed by permissions (or their children)
if (!\in_array($id, $this->visibleRootTrails) && !\in_array($id, $this->root) && !\in_array($id, $this->rootChildren))
// In the extended tree view (mode 6) we have to check on the parent table only
$needsCheck = ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] ?? null) == 5 || $table !== $this->strTable;

if ($needsCheck && !\in_array($id, $this->visibleRootTrails) && !\in_array($id, $this->root) && !\in_array($id, $this->rootChildren))
{
return '';
}
Expand Down
137 changes: 87 additions & 50 deletions core-bundle/src/Resources/contao/library/Contao/Database/Statement.php
Expand Up @@ -12,7 +12,8 @@

use Contao\Database;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Driver\Result as DoctrineResult;
use Doctrine\DBAL\Exception\DriverException;

/**
* Create and execute queries
Expand Down Expand Up @@ -44,7 +45,7 @@ class Statement

/**
* Database statement
* @var ResultStatement
* @var DoctrineResult
*/
protected $statement;

Expand All @@ -55,27 +56,23 @@ class Statement
protected $strQuery;

/**
* Autocommit indicator
* @var boolean
* @var array
*/
protected $blnDisableAutocommit = false;
private $arrSetParams = array();

/**
* Result cache
* @var array
*/
protected static $arrCache = array();
private $arrLastUsedParams = array();

/**
* Validate the connection resource and store the query string
*
* @param Connection $resConnection The connection resource
* @param boolean $blnDisableAutocommit Optionally disable autocommitting
* @param Connection $resConnection The connection resource
*/
public function __construct(Connection $resConnection, $blnDisableAutocommit=false)
public function __construct(Connection $resConnection)
{
$this->resConnection = $resConnection;
$this->blnDisableAutocommit = $blnDisableAutocommit;
}

/**
Expand Down Expand Up @@ -124,27 +121,7 @@ public function prepare($strQuery)
}

$this->strQuery = trim($strQuery);

// Auto-generate the SET/VALUES subpart
if (strncasecmp($this->strQuery, 'INSERT', 6) === 0 || strncasecmp($this->strQuery, 'UPDATE', 6) === 0)
{
$this->strQuery = str_replace('%s', '%p', $this->strQuery);
}

// Replace wildcards
$arrChunks = preg_split("/('[^']*')/", $this->strQuery, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

foreach ($arrChunks as $k=>$v)
{
if (0 === strncmp($v, "'", 1))
{
continue;
}

$arrChunks[$k] = str_replace('?', '%s', $v);
}

$this->strQuery = implode('', $arrChunks);
$this->arrLastUsedParams = array();

return $this;
}
Expand All @@ -166,33 +143,50 @@ public function prepare($strQuery)
*/
public function set($arrParams)
{
$strQuery = '';
$arrParams = $this->escapeParams($arrParams);
if (substr_count($this->strQuery, '%s') !== 1 || !\in_array(strtoupper(substr($this->strQuery, 0, 6)), array('INSERT', 'UPDATE'), true))
{
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s()" is only supported for INSERT and UPDATE queries with the "%%s" placeholder. This will throw an exception in Contao 5.0.', __METHOD__);

return $this;
}

$this->arrSetParams = array_values($arrParams);

$arrParamNames = array_map(
static function ($strName)
{
if (!preg_match('/^[A-Za-z0-9_$]+$/', $strName))
{
throw new \RuntimeException(sprintf('Invalid column name "%s" in %s()', $strName, __METHOD__));
}

return Database::quoteIdentifier($strName);
},
array_keys($arrParams)
);

// INSERT
if (strncasecmp($this->strQuery, 'INSERT', 6) === 0)
{
$strQuery = sprintf(
'(%s) VALUES (%s)',
implode(', ', array_map('Database::quoteIdentifier', array_keys($arrParams))),
str_replace('%', '%%', implode(', ', $arrParams))
implode(', ', $arrParamNames),
implode(', ', array_fill(0, \count($arrParams), '?'))
);
}

// UPDATE
elseif (strncasecmp($this->strQuery, 'UPDATE', 6) === 0)
else
{
$arrSet = array();

foreach ($arrParams as $k=>$v)
if (!$arrParamNames)
{
$arrSet[] = Database::quoteIdentifier($k) . '=' . $v;
throw new \InvalidArgumentException('Set array must not be empty for UPDATE queries');
}

$strQuery = 'SET ' . str_replace('%', '%%', implode(', ', $arrSet));
$strQuery = 'SET ' . implode('=?, ', $arrParamNames) . '=?';
}

$this->strQuery = str_replace('%p', $strQuery, $this->strQuery);
$this->strQuery = str_replace('%s', $strQuery, $this->strQuery);

return $this;
}
Expand Down Expand Up @@ -238,14 +232,14 @@ public function execute()
{
$arrParams = \func_get_args();

if (!empty($arrParams) && \is_array($arrParams[0]))
if (\count($arrParams) === 1 && \is_array($arrParams[0]))
{
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s()" with an array parameter has been deprecated and will no longer work in Contao 5.0. Use argument unpacking via ... instead."', __METHOD__);

$arrParams = array_values($arrParams[0]);
}

$this->replaceWildcards($arrParams);

return $this->query();
return $this->query('', array_merge($this->arrSetParams, $arrParams));
}

/**
Expand All @@ -257,7 +251,7 @@ public function execute()
*
* @throws \Exception If the query string is empty
*/
public function query($strQuery='')
public function query($strQuery='', array $arrParams = array())
{
if (!empty($strQuery))
{
Expand All @@ -270,8 +264,39 @@ public function query($strQuery='')
throw new \Exception('Empty query string');
}

$arrParams = array_map(
static function ($varParam)
{
if (\is_string($varParam) || \is_bool($varParam) || \is_float($varParam) || \is_int($varParam) || $varParam === null)
{
return $varParam;
}

return serialize($varParam);
},
$arrParams
);

$this->arrLastUsedParams = $arrParams;

// Execute the query
$this->statement = $this->resConnection->executeQuery($this->strQuery);
try
{
$this->statement = $this->resConnection->executeQuery($this->strQuery, $arrParams);
}
catch (DriverException $exception)
{
if ($arrParams !== array(null))
{
throw $exception;
}

// Backwards compatibility for calling Statement::execute(null)
$this->statement = $this->resConnection->executeQuery($this->strQuery);

// Only trigger the deprecation if the parameter count was the reason for the exception and the previous call did not throw
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s::execute(null)" has been deprecated and will no longer work in Contao 5.0. Use "%s::execute() instead."', __CLASS__, __CLASS__);
}

// No result set available
if ($this->statement->columnCount() < 1)
Expand All @@ -289,9 +314,13 @@ public function query($strQuery='')
* @param array $arrValues The values array
*
* @throws \Exception If $arrValues has too few values to replace the wildcards in the query string
*
* @deprecated Deprecated since Contao 4.13, to be removed in Contao 5.0.
*/
protected function replaceWildcards($arrValues)
{
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s()" has been deprecated and will no longer work in Contao 5.0.', __METHOD__);

$arrValues = $this->escapeParams($arrValues);
$this->strQuery = preg_replace('/(?<!%)%([^bcdufosxX%])/', '%%$1', $this->strQuery);

Expand All @@ -308,9 +337,13 @@ protected function replaceWildcards($arrValues)
* @param array $arrValues The values array
*
* @return array The array with the escaped values
*
* @deprecated Deprecated since Contao 4.13, to be removed in Contao 5.0.
*/
protected function escapeParams($arrValues)
{
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s()" has been deprecated and will no longer work in Contao 5.0.', __METHOD__);

foreach ($arrValues as $k=>$v)
{
switch (\gettype($v))
Expand Down Expand Up @@ -341,10 +374,14 @@ protected function escapeParams($arrValues)
* Explain the current query
*
* @return string The explanation string
*
* @deprecated Deprecated since Contao 4.13, to be removed in Contao 5.0.
*/
public function explain()
{
return $this->resConnection->fetchAssociative('EXPLAIN ' . $this->strQuery);
trigger_deprecation('contao/core-bundle', '4.13', 'Using "%s()" has been deprecated and will no longer work in Contao 5.0.', __METHOD__);

return $this->resConnection->fetchAssociative('EXPLAIN ' . $this->strQuery, $this->arrLastUsedParams);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions core-bundle/src/Resources/contao/library/Contao/Model.php
Expand Up @@ -1072,7 +1072,7 @@ protected static function find(array $arrOptions)
}

$objStatement = static::preFind($objStatement);
$objResult = $objStatement->execute($arrOptions['value'] ?? null);
$objResult = $objStatement->execute(...(array) ($arrOptions['value'] ?? array()));

if ($objResult->numRows < 1)
{
Expand Down Expand Up @@ -1155,7 +1155,7 @@ public static function countBy($strColumn=null, $varValue=null, array $arrOption

$strQuery = static::buildCountQuery($arrOptions);

return (int) Database::getInstance()->prepare($strQuery)->execute($arrOptions['value'])->count;
return (int) Database::getInstance()->prepare($strQuery)->execute(...(array) ($arrOptions['value'] ?? array()))->count;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions core-bundle/src/Search/Indexer/DefaultIndexer.php
Expand Up @@ -43,6 +43,10 @@ public function index(Document $document): void
$this->throwBecause('Cannot index empty response.');
}

if (($canonical = $document->extractCanonicalUri()) && ((string) $canonical !== (string) $document->getUri())) {
$this->throwBecause(sprintf('Ignored because canonical URI "%s" does not match document URI.', $canonical));
}

try {
$title = $document->getContentCrawler()->filterXPath('//head/title')->first()->text(null, true);
} catch (\Exception $e) {
Expand Down

0 comments on commit 2dd6e97

Please sign in to comment.