private function decodeContentQuery($textquery, $inParameters = null)
{
$decoded = ['contenttypes' => [], 'return_single' => false, 'self_paginated' => true, 'order_callback' => false, 'queries' => [], 'parameters' => [], 'hydrate' => true];
list($metaParameters, $ctypeParameters) = $this->organizeQueryParameters($inParameters);
$this->parseTextQuery($textquery, $decoded, $metaParameters, $ctypeParameters);
// $decoded['contettypes'] gotten here
// get page nr. from url if has
$metaParameters['page'] = $this->app['pager']->getCurrentPage(implode('_', $decoded['contenttypes']));
$this->prepareDecodedQueryForUse($decoded, $metaParameters, $ctypeParameters);
$decoded['parameters'] = $metaParameters;
// for all the non-reserved parameters that are fields or taxonomies, we assume people want to do a 'where'
foreach ($ctypeParameters as $contenttypeslug => $actualParameters) {
$contenttype = $this->getContentType($contenttypeslug);
$tablename = $this->getContenttypeTablename($contenttype);
$where = [];
$order = [];
// Set the 'order', if specified in the meta_parameters.
if (!empty($metaParameters['order'])) {
$order[] = $this->getEscapedSortorder($metaParameters['order'], false);
}
$query = ['tablename' => $tablename, 'contenttype' => $contenttype, 'from' => sprintf('FROM %s', $tablename), 'where' => '', 'order' => '', 'params' => []];
if ($contenttype === false) {
/*
* We were logging here, but a couple of places like
* TwigExtension::menuHelper() would trigger lots of hits,
* filling logs and impacting performance as a result.
* @see #1799 https://github.com/bolt/bolt/issues/1799
*
* When we refactor we need to address the callers, as this is a
* valid error state.
*/
continue;
}
if (is_array($actualParameters)) {
// Set the 'FROM' part of the query, without the LEFT JOIN (i.e. no taxonomies..)
foreach ($actualParameters as $key => $value) {
if ($key == 'order') {
$orderValue = $this->decodeQueryOrder($contenttype, $value);
if ($orderValue !== false) {
$order[] = $orderValue;
}
continue;
}
if ($key == 'filter' && !empty($value)) {
$filterWhere = [];
foreach ($contenttype['fields'] as $name => $fieldconfig) {
if (in_array($fieldconfig['type'], ['text', 'textarea', 'html', 'markdown'])) {
$filterWhere[] = sprintf('%s.%s LIKE %s', $tablename, $name, $this->app['db']->quote('%' . $value . '%'));
}
}
if (count($filterWhere) > 0) {
$where[] = '(' . implode(' OR ', $filterWhere) . ')';
}
continue;
}
// build OR parts if key contains "|||"
if (strpos($key, " ||| ") !== false) {
$keyParts = explode(" ||| ", $key);
$valParts = explode(" ||| ", $value);
$orPart = '( ';
$countParts = count($keyParts);
for ($i = 0; $i < $countParts; $i++) {
if (in_array($keyParts[$i], $this->getContentTypeFields($contenttype['slug'])) || in_array($keyParts[$i], Content::getBaseColumns())) {
$rkey = $tablename . '.' . $keyParts[$i];
$fieldtype = $this->getContentTypeFieldType($contenttype['slug'], $keyParts[$i]);
$orPart .= ' (' . $this->parseWhereParameter($rkey, $valParts[$i], $fieldtype) . ') OR ';
}
}
if (strlen($orPart) > 2) {
$where[] = substr($orPart, 0, -4) . ') ';
}
}
// for all the parameters that are fields
if (in_array($key, $this->getContentTypeFields($contenttype['slug'])) || in_array($key, Content::getBaseColumns())) {
$rkey = $tablename . '.' . $key;
$fieldtype = $this->getContentTypeFieldType($contenttype['slug'], $key);
$where[] = $this->parseWhereParameter($rkey, $value, $fieldtype);
}
// for all the parameters that are taxonomies
if (array_key_exists($key, $this->getContentTypeTaxonomy($contenttype['slug']))) {
// check if we're trying to use "!" as a way of 'not'. If so, we need to do a 'NOT IN', instead
// of 'IN'. And, the parameter in the subselect needs to be without "!" as a consequence.
if (strpos($value, "!") !== false) {
$notin = "NOT ";
$value = str_replace("!", "", $value);
} else {
$notin = "";
}
// Set the extra '$where', with subselect for taxonomies.
$where[] = sprintf('%s %s IN (SELECT content_id AS id FROM %s where %s AND ( %s OR %s ) AND %s)', $this->app['db']->quoteIdentifier('id'), $notin, $this->getTablename('taxonomy'), $this->parseWhereParameter($this->getTablename('taxonomy') . '.taxonomytype', $key), $this->parseWhereParameter($this->getTablename('taxonomy') . '.slug', $value), $this->parseWhereParameter($this->getTablename('taxonomy') . '.name', $value), $this->parseWhereParameter($this->getTablename('taxonomy') . '.contenttype', $contenttype['slug']));
}
}
}
if (count($order) == 0) {
$order[] = $this->decodeQueryOrder($contenttype, false) ?: 'datepublish DESC';
}
if (count($where) > 0) {
$query['where'] = sprintf('WHERE (%s)', implode(' AND ', $where));
}
if (count($order) > 0) {
$order = implode(', ', $order);
if (!empty($order)) {
$query['order'] = sprintf('ORDER BY %s', $order);
}
}
$decoded['queries'][] = $query;
if (isset($inParameters['hydrate'])) {
$decoded['hydrate'] = $inParameters['hydrate'];
}
}
return $decoded;
}