diff --git a/config/bolt/contenttypes.yaml b/config/bolt/contenttypes.yaml index c447bb2f..1da55172 100644 --- a/config/bolt/contenttypes.yaml +++ b/config/bolt/contenttypes.yaml @@ -138,7 +138,7 @@ entries: listing_template: listing.twig listing_records: 10 default_status: published - sort: -datepublish + sort: -publishedAt recordsperpage: 20 icon_many: "fa:file-alt" icon_one: "fa:file-alt" diff --git a/config/services.yaml b/config/services.yaml index fdb876a3..bd95b0b0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -41,6 +41,27 @@ services: arguments: ["@knp_menu.factory"] tags: - { name: knp_menu.menu_builder, method: createSidebarMenu, alias: sidebar } # The alias is what is used to retrieve the menu - # config/services.yaml - Twig\Extension\StringLoaderExtension: \ No newline at end of file + Twig\Extension\StringLoaderExtension: + + # Needed for SetContent from bolt/bolt + Bolt\Storage\Query\Query: + calls: + - + method: addScope + arguments: [ 'frontend', '@Bolt\Storage\Query\FrontendQueryScope' ] + Bolt\Storage\Query\ContentQueryParser: + calls: + - + method: addService + arguments: [ 'select', '@Bolt\Storage\Query\SelectQuery' ] + - + method: addService + arguments: [ 'search', '@Bolt\Storage\Query\SearchQuery' ] + - + method: addService + arguments: [ 'search_weighter', '@Bolt\Storage\Query\SearchWeighter' ] + - + method: addService + arguments: [ 'search_config', '@Bolt\Storage\Query\SearchConfig' ] + Doctrine\ORM\Query\Expr: diff --git a/src/Repository/ContentRepository.php b/src/Repository/ContentRepository.php index 16071ca2..b2483aa5 100644 --- a/src/Repository/ContentRepository.php +++ b/src/Repository/ContentRepository.php @@ -26,7 +26,7 @@ class ContentRepository extends ServiceEntityRepository parent::__construct($registry, Content::class); } - private function getQueryBuilder(): QueryBuilder + public function getQueryBuilder(): QueryBuilder { return $this->createQueryBuilder('content'); } diff --git a/src/Storage/Query/ContentQueryParser.php b/src/Storage/Query/ContentQueryParser.php index f7c48512..508f7395 100644 --- a/src/Storage/Query/ContentQueryParser.php +++ b/src/Storage/Query/ContentQueryParser.php @@ -4,8 +4,9 @@ namespace Bolt\Storage\Query; use Bolt\Events\QueryEvent; use Bolt\Events\QueryEvents; +use Bolt\Repository\ContentRepository; use Bolt\Storage\Entity\Content; -use Bolt\Storage\EntityManager; +//use Bolt\Storage\EntityManager; use Bolt\Storage\Query\Directive\GetQueryDirective; use Bolt\Storage\Query\Directive\HydrateDirective; use Bolt\Storage\Query\Directive\LimitDirective; @@ -27,11 +28,12 @@ use Bolt\Storage\Query\Handler\SelectQueryHandler; * object representation. * * @author Ross Riley + * @author Xiao-Hu Tai */ class ContentQueryParser { - /** @var EntityManager */ - protected $em; + /** @var ContentRepository */ + protected $repo; /** @var string */ protected $query; /** @var array */ @@ -58,12 +60,12 @@ class ContentQueryParser /** * Constructor. * - * @param EntityManager $em - * @param QueryInterface $queryHandler + * @param ContentRepository $repo + * @param QueryInterface $queryHandler */ - public function __construct(EntityManager $em, QueryInterface $queryHandler = null) + public function __construct(ContentRepository $repo, QueryInterface $queryHandler = null) { - $this->em = $em; + $this->repo = $repo; if ($queryHandler !== null) { $this->addService('select', $queryHandler); @@ -250,13 +252,13 @@ class ContentQueryParser } /** - * Gets the object EntityManager. + * Gets the content repository. * - * @return EntityManager + * @return ContentRepository */ - public function getEntityManager() + public function getContentRepository() { - return $this->em; + return $this->repo; } /** @@ -442,12 +444,14 @@ class ContentQueryParser public function fetch() { $this->parse(); - $parseEvent = new QueryEvent($this); - $this->getEntityManager()->getEventManager()->dispatch(QueryEvents::PARSE, $parseEvent); - + // $parseEvent = new QueryEvent($this); + // $this->getEntityManager()->getEventManager()->dispatch(QueryEvents::PARSE, $parseEvent); +if (! empty($this->getOperation)) $result = call_user_func($this->handlers[$this->getOperation()], $this); - $executeEvent = new QueryEvent($this, $result); - $this->getEntityManager()->getEventManager()->dispatch(QueryEvents::EXECUTE, $executeEvent); +else + $result = call_user_func($this->handlers['select'], $this);; + // $executeEvent = new QueryEvent($this, $result); + // $this->getEntityManager()->getEventManager()->dispatch(QueryEvents::EXECUTE, $executeEvent); return $result; } diff --git a/src/Storage/Query/Directive/OrderDirective.php b/src/Storage/Query/Directive/OrderDirective.php index a15d828d..8823b6d9 100644 --- a/src/Storage/Query/Directive/OrderDirective.php +++ b/src/Storage/Query/Directive/OrderDirective.php @@ -7,7 +7,7 @@ use Bolt\Storage\Query\QueryInterface; /** * Directive to alter query based on 'order' parameter. * - * eg: 'pages', ['order'=>'-datepublish'] + * eg: 'pages', ['order'=>'-publishedAt'] */ class OrderDirective { @@ -22,7 +22,7 @@ class OrderDirective } // remove default order - $query->getQueryBuilder()->resetQueryPart('orderBy'); + $query->getQueryBuilder()->resetDQLPart('orderBy'); $separatedOrders = $this->getOrderBys($order); foreach ($separatedOrders as $order) { @@ -36,7 +36,7 @@ class OrderDirective } else { $direction = null; } - $query->getQueryBuilder()->addOrderBy($order, $direction); + $query->getQueryBuilder()->addOrderBy('content.' . $order, $direction); } } diff --git a/src/Storage/Query/Filter.php b/src/Storage/Query/Filter.php index 289bdd31..b73d3e4e 100644 --- a/src/Storage/Query/Filter.php +++ b/src/Storage/Query/Filter.php @@ -2,7 +2,7 @@ namespace Bolt\Storage\Query; -use Doctrine\DBAL\Query\Expression\CompositeExpression; +use Doctrine\ORM\Query\Expr\Composite; /** * This class represents a single filter that converts to an expression along @@ -14,7 +14,7 @@ use Doctrine\DBAL\Query\Expression\CompositeExpression; class Filter { protected $key; - /** @var CompositeExpression */ + /** @var Composite */ protected $expression; /** @var array */ protected $parameters = []; @@ -53,9 +53,9 @@ class Filter /** * Allows replacing the expression object with a modified one. * - * @param CompositeExpression $expression + * @param Composite $expression */ - public function setExpression(CompositeExpression $expression) + public function setExpression(Composite $expression) { $this->expression = $expression; } @@ -65,7 +65,7 @@ class Filter * only needed for on the fly modification, to get the compiled * expression use getExpression(). * - * @return CompositeExpression + * @return Composite */ public function getExpressionObject() { diff --git a/src/Storage/Query/FrontendQueryScope.php b/src/Storage/Query/FrontendQueryScope.php index 36b383c3..db4ddfa2 100644 --- a/src/Storage/Query/FrontendQueryScope.php +++ b/src/Storage/Query/FrontendQueryScope.php @@ -2,7 +2,7 @@ namespace Bolt\Storage\Query; -use Bolt\Config; +use Bolt\Configuration\Config; use Bolt\Storage\Query\Directive\OrderDirective; /** @@ -52,7 +52,7 @@ class FrontendQueryScope implements QueryScopeInterface { $contentTypes = $this->config->get('contenttypes'); foreach ($contentTypes as $type => $values) { - $sort = $values['sort'] ?: '-datepublish'; + $sort = $values['sort'] ?: '-publishedAt'; $this->orderBys[$type] = $sort; if (isset($values['singular_slug'])) { $this->orderBys[$values['singular_slug']] = $sort; @@ -68,7 +68,7 @@ class FrontendQueryScope implements QueryScopeInterface $ct = $query->getContentType(); // Setup default ordering of queries on a per-contenttype basis - if (empty($query->getQueryBuilder()->getQueryPart('orderBy')) && isset($this->orderBys[$ct])) { + if (empty($query->getQueryBuilder()->getParameter('orderBy')) && isset($this->orderBys[$ct])) { $handler = new OrderDirective(); $handler($query, $this->orderBys[$ct]); } @@ -76,7 +76,7 @@ class FrontendQueryScope implements QueryScopeInterface // Setup status to only published unless otherwise specified $status = $query->getParameter('status'); if (!$status) { - $query->setParameter('status', 'published'); + $query->setParameter('status', 'published'); // no work?? } } } diff --git a/src/Storage/Query/Handler/SelectQueryHandler.php b/src/Storage/Query/Handler/SelectQueryHandler.php index 19c91705..4974fcff 100644 --- a/src/Storage/Query/Handler/SelectQueryHandler.php +++ b/src/Storage/Query/Handler/SelectQueryHandler.php @@ -27,9 +27,19 @@ class SelectQueryHandler foreach ($contentQuery->getContentTypes() as $contentType) { $contentType = str_replace('-', '_', $contentType); - $repo = $contentQuery->getEntityManager()->getRepository($contentType); - $query->setQueryBuilder($repo->createQueryBuilder('_' . $contentType)); - $query->setContentType($contentType); + + $repo = $contentQuery->getContentRepository(); + $query->setQueryBuilder($repo + ->getQueryBuilder() + // ->where('content.contentType = :ct') + // ->setParameter('ct', $contentType) + ); + // $query->setContentType($contentType); + $query->setContentType('content'); + + // $repo = $contentQuery->getEntityManager()->getRepository($contentType); + // $query->setQueryBuilder($repo->createQueryBuilder('_' . $contentType)); + // $query->setContentType($contentType); /** Run the parameters through the whitelister. If we get a false back from this method it's because there * is no need to continue with the query. @@ -38,13 +48,22 @@ class SelectQueryHandler if (!$params && count($contentQuery->getParameters())) { continue; } - +//$params['contentType'] = $contentType; /** Continue and run the query add the results to the set */ $query->setParameters($params); $contentQuery->runScopes($query); $contentQuery->runDirectives($query); +// dd($query->build()); + // $query is of Bolt\Storage\Query\SelectQuery + // dd($query->getQueryBuilder()->getQuery()); + + $test = $query->build() + ->andWhere('content.contentType = :ct') + ->setParameter('ct', $contentType) + ->getQuery() + ; + $result = $test->getResult(); - $result = $repo->queryWith($query); if ($result) { $set->setOriginalQuery($contentType, $query->getQueryBuilder()); $set->add($result, $contentType); @@ -73,10 +92,27 @@ class SelectQueryHandler * * @return bool|array $cleanParams */ - public function whitelistParameters(array $queryParams, Repository $repo) + public function whitelistParameters(array $queryParams, $repo) { - $metadata = $repo->getClassMetadata(); - $allowedParams = array_keys($metadata->getFieldMappings()); + // $metadata = $repo->getClassMetadata(); + // $allowedParams = array_keys($metadata->getFieldMappings()); + $allowedParams = [ + 0 => "id", + 1 => "slug", + 2 => "datecreated", + 3 => "datechanged", + 4 => "datepublish", + 5 => "datedepublish", + 6 => "ownerid", + 7 => "status", + 8 => "templatefields", + 9 => "title", + 10 => "image", + 11 => "teaser", + 12 => "content", + 13 => "contentlink", + 14 => "incomingrelation", + ]; $cleanParams = []; foreach ($queryParams as $fieldSelect => $valueSelect) { $stack = []; diff --git a/src/Storage/Query/Query.php b/src/Storage/Query/Query.php index 166ff01f..cfa50f2b 100644 --- a/src/Storage/Query/Query.php +++ b/src/Storage/Query/Query.php @@ -24,6 +24,7 @@ class Query { $this->parser = $parser; $this->recordsView = $recordsView; + $this->scopes = []; } /** diff --git a/src/Storage/Query/QueryParameterParser.php b/src/Storage/Query/QueryParameterParser.php index ad387b9c..2f97e796 100644 --- a/src/Storage/Query/QueryParameterParser.php +++ b/src/Storage/Query/QueryParameterParser.php @@ -2,8 +2,7 @@ namespace Bolt\Storage\Query; -use Bolt\Exception\QueryParseException; -use Doctrine\DBAL\Query\Expression\ExpressionBuilder; +use Doctrine\ORM\Query\Expr; /** * Handler class to convert the DSL for content query parameters @@ -32,7 +31,7 @@ class QueryParameterParser * * @param ExpressionBuilder $expr */ - public function __construct(ExpressionBuilder $expr = null) + public function __construct(Expr $expr) { $this->expr = $expr; $this->setupDefaults(); @@ -77,15 +76,12 @@ class QueryParameterParser * @param string $key * @param mixed $value * - * @throws QueryParseException - * @throws QueryParseException - * * @return Filter|null */ public function getFilter($key, $value = null) { - if (!$this->expr instanceof ExpressionBuilder) { - throw new QueryParseException('Cannot call method without an Expression Builder parameter set', 1); + if (!$this->expr instanceof Expr) { + throw new \Exception('Cannot call method without an Expression Builder parameter set', 1); } /** @var callable $callback */ @@ -106,8 +102,6 @@ class QueryParameterParser * @param string $value * @param ExpressionBuilder $expr * - * @throws QueryParseException - * * @return null */ public function incorrectQueryHandler($key, $value, $expr) @@ -116,7 +110,7 @@ class QueryParameterParser return null; } if (strpos($value, '&&') && strpos($value, '||')) { - throw new QueryParseException('Mixed && and || operators are not supported', 1); + throw new \Exception('Mixed && and || operators are not supported', 1); } } @@ -129,8 +123,6 @@ class QueryParameterParser * @param string $value * @param ExpressionBuilder $expr * - * @throws QueryParseException - * * @return Filter|null */ public function multipleKeyAndValueHandler($key, $value, $expr) @@ -185,8 +177,6 @@ class QueryParameterParser * @param string $value * @param ExpressionBuilder $expr * - * @throws QueryParseException - * * @return Filter|null */ public function multipleValueHandler($key, $value, $expr) @@ -237,8 +227,6 @@ class QueryParameterParser * @param string|array $value * @param ExpressionBuilder $expr * - * @throws QueryParseException - * * @return Filter */ public function defaultFilterHandler($key, $value, $expr) @@ -287,8 +275,6 @@ class QueryParameterParser * * @param string $value Value to process * - * @throws QueryParseException - * * @return array Parsed values */ public function parseValue($value) @@ -309,7 +295,7 @@ class QueryParameterParser } } - throw new QueryParseException(sprintf('No matching value found for "%s"', $value)); + throw new \Exception(sprintf('No matching value found for "%s"', $value)); } /** diff --git a/src/Storage/Query/SearchConfig.php b/src/Storage/Query/SearchConfig.php index c4993d4d..db7e5b2a 100644 --- a/src/Storage/Query/SearchConfig.php +++ b/src/Storage/Query/SearchConfig.php @@ -2,7 +2,7 @@ namespace Bolt\Storage\Query; -use Bolt\Config; +use Bolt\Configuration\Config; /** * This class takes an overall config array as input and parses into values @@ -17,10 +17,8 @@ class SearchConfig protected $config = []; /** @var array */ protected $searchableTypes = []; - /** @var array */ protected $invisibleTypes = []; - /** @var array */ protected $joins = []; diff --git a/src/Storage/Query/SearchQuery.php b/src/Storage/Query/SearchQuery.php index 0efff273..ab141a38 100644 --- a/src/Storage/Query/SearchQuery.php +++ b/src/Storage/Query/SearchQuery.php @@ -32,7 +32,7 @@ class SearchQuery extends SelectQuery * @param QueryParameterParser $parser * @param SearchConfig $config */ - public function __construct(QueryBuilder $qb, QueryParameterParser $parser, SearchConfig $config) + public function __construct(QueryBuilder $qb = null, QueryParameterParser $parser, SearchConfig $config) { parent::__construct($qb, $parser); $this->config = $config; diff --git a/src/Storage/Query/SelectQuery.php b/src/Storage/Query/SelectQuery.php index 6b39744c..db90e4a0 100644 --- a/src/Storage/Query/SelectQuery.php +++ b/src/Storage/Query/SelectQuery.php @@ -2,9 +2,9 @@ namespace Bolt\Storage\Query; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Query\Expression\CompositeExpression; -use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\ORM\Connection; +use Doctrine\ORM\Query\Expression\CompositeExpression; +use Doctrine\ORM\Query\QueryBuilder; /** * This query class coordinates a select query build from Bolt's @@ -29,6 +29,7 @@ class SelectQuery implements ContentQueryInterface protected $params; /** @var Filter[] */ protected $filters = []; + /** @var array */ protected $replacements = []; /** @var bool */ protected $singleFetchMode = false; @@ -39,7 +40,7 @@ class SelectQuery implements ContentQueryInterface * @param QueryBuilder $qb * @param QueryParameterParser $parser */ - public function __construct(QueryBuilder $qb, QueryParameterParser $parser) + public function __construct(QueryBuilder $qb = null, QueryParameterParser $parser) { $this->qb = $qb; $this->parser = $parser; @@ -115,7 +116,6 @@ class SelectQuery implements ContentQueryInterface if (!count($this->filters)) { return null; } - $expr = $this->qb->expr()->andX(); foreach ($this->filters as $filter) { $expr = $expr->add($filter->getExpression()); @@ -223,7 +223,7 @@ class SelectQuery implements ContentQueryInterface * * @param QueryBuilder $qb */ - public function setQueryBuilder(QueryBuilder $qb) + public function setQueryBuilder($qb) { $this->qb = $qb; } @@ -269,7 +269,9 @@ class SelectQuery implements ContentQueryInterface { $this->filters = []; foreach ($this->params as $key => $value) { - $this->parser->setAlias('_' . $this->contentType); + // $this->parser // Bolt\Storage\Query\QueryParameterParser + // $this->parser->setAlias('_' . $this->contentType); + $this->parser->setAlias('content'); $filter = $this->parser->getFilter($key, $value); if ($filter) { $this->addFilter($filter); diff --git a/src/Twig/Node/SetcontentNode.php b/src/Twig/Node/SetcontentNode.php index 6df1d3ce..1d649616 100644 --- a/src/Twig/Node/SetcontentNode.php +++ b/src/Twig/Node/SetcontentNode.php @@ -48,7 +48,7 @@ class SetcontentNode extends Node ->write("\$context['") ->raw($this->getAttribute('name')) ->raw("'] = ") - ->raw("\$this->env->getRuntime('" . SetcontentRuntime::class . "')->getContent(") + ->raw("\$this->env->getRuntime('" . SetcontentRuntime::class . "')->getQueryEngine()->getContentForTwig(") ->subcompile($this->getAttribute('contenttype')) ->raw(', ') ->subcompile($arguments) diff --git a/src/Twig/Runtime/SetcontentRuntime.php b/src/Twig/Runtime/SetcontentRuntime.php index 9903adac..2c117d18 100644 --- a/src/Twig/Runtime/SetcontentRuntime.php +++ b/src/Twig/Runtime/SetcontentRuntime.php @@ -4,71 +4,30 @@ declare(strict_types=1); namespace Bolt\Twig\Runtime; -use Bolt\Configuration\Config; -use Bolt\Repository\ContentRepository; +use Bolt\Storage\Query\Query; class SetcontentRuntime { - /** @var Config $config */ - private $config; - /** @var ContentRepository $repo */ - private $repo; + /** @var Query $queryEngine */ + private $queryEngine; + /** @var MetadataDriver $metadataDriver */ + private $metadataDriver; /** - * @param Config $config - * @param ContentRepository $repo + * @param Query $queryEngine + * @param MetadataDriver $metadataDriver */ - public function __construct(Config $config, ContentRepository $repo) + public function __construct(Query $queryEngine, MetadataDriver $metadataDriver = null) { - $this->config = $config; - $this->repo = $repo; + $this->queryEngine = $queryEngine; + $this->metadataDriver = $metadataDriver; // still needed? } /** - * @return ContentRepository + * @return Query */ - public function getContentRepository() + public function getQueryEngine() { - return $this->repo; - } - - /** - * @param string $textQuery - * @param array $parameters - */ - public function getContent($textQuery, array $parameters = []) - { - // fix BC break - if (func_num_args() === 3) { - $whereparameters = func_get_arg(2); - if (is_array($whereparameters) && !empty($whereparameters)) { - $parameters = array_merge($parameters, $whereparameters); - } - } - - $qb = $this->repo->createQueryBuilder('content') - ->addSelect('a') - ->innerJoin('content.author', 'a') - ->orderBy('content.modifiedAt', 'DESC') - ; - - $contentType = explode('/', $textQuery)[0]; - - if ($contentType) { - $qb - ->where('content.contentType = :ct') - ->setParameter('ct', $contentType) - ; - } - - return $qb - ->getQuery() - ->getResult() - ; - // return $this->createPaginator($qb->getQuery(), $page); - - // return $this->recordsView->createView( - // $this->getContentByScope('frontend', $textQuery, $parameters) - // ); + return $this->queryEngine; } } diff --git a/src/Twig/TwigRecordsView.php b/src/Twig/TwigRecordsView.php index 0588ffa6..8448e61f 100644 --- a/src/Twig/TwigRecordsView.php +++ b/src/Twig/TwigRecordsView.php @@ -2,11 +2,11 @@ namespace Bolt\Twig; -use Bolt\Storage\Entity\Content; -use Bolt\Storage\Field\Collection\FieldCollection; +// use Bolt\Storage\Entity\Content; +// use Bolt\Storage\Field\Collection\FieldCollection; use Bolt\Storage\Mapping\MetadataDriver; use Bolt\Storage\Query\QueryResultset; -use ParsedownExtra; +// use ParsedownExtra; use Twig\Markup; /** @@ -14,6 +14,7 @@ use Twig\Markup; * so appropriate transformation can occur. * * @author Ross Riley + * @author Xiao-Hu Tai */ class TwigRecordsView { @@ -27,7 +28,7 @@ class TwigRecordsView * * @param MetadataDriver $metadata */ - public function __construct(MetadataDriver $metadata) + public function __construct(MetadataDriver $metadata = null) { $this->metadata = $metadata; $this->setupDefaults(); @@ -55,20 +56,20 @@ class TwigRecordsView return new Markup($value, 'UTF-8'); }); - $this->addTransformer('repeater', function ($value) { - /** @var FieldCollection $collection */ - foreach ($value as $collection) { - foreach ($collection as $field) { - $field->setValue($this->transform($field->getValue(), $field->getFieldType())); - } - } + // $this->addTransformer('repeater', function ($value) { + // /** @var FieldCollection $collection */ + // foreach ($value as $collection) { + // foreach ($collection as $field) { + // $field->setValue($this->transform($field->getValue(), $field->getFieldType())); + // } + // } - return $value; - }); + // return $value; + // }); - $this->addTransformer('block', function ($value) { - return $this->transform($value, 'repeater'); - }); + // $this->addTransformer('block', function ($value) { + // return $this->transform($value, 'repeater'); + // }); } /**