Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative QueryController approach #1473

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Compiler;

use Exception;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
use ReflectionClass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -16,23 +17,28 @@
*/
class QueryTypePass implements CompilerPassInterface
{
/** @var \Symfony\Component\DependencyInjection\Reference[] */
private $queryTypeRefs = [];

public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('ezpublish.query_type.registry')) {
return;
}

$queryTypes = [];
$queryTypesRefs = [];

// array of QueryType classes. Used to prevent double handling between services & convention definitions.
$queryTypesClasses = [];

// tagged query types
$taggedServiceIds = $container->findTaggedServiceIds('ezpublish.query_type');
foreach ($taggedServiceIds as $taggedServiceId => $tags) {
foreach ($container->findTaggedServiceIds('ezpublish.query_type') as $taggedServiceId => $tags) {
$queryTypeDefinition = $container->getDefinition($taggedServiceId);
$queryTypeClass = $queryTypeDefinition->getClass();
$queryTypeClassName = $queryTypeDefinition->getClass();

for ($i = 0, $count = count($tags); $i < $count; ++$i) {
// TODO: Check for duplicates
$queryTypes[$queryTypeClass::getName()] = new Reference($taggedServiceId);
$queryTypesRefs[] = new Reference($taggedServiceId);
$queryTypesClasses[$queryTypeClassName] = true;
}
}

Expand All @@ -48,30 +54,48 @@ public function process(ContainerBuilder $container)
continue;
}

$queryTypeServices = [];
$conventionQueryTypeDefs = [];
$bundleQueryTypeNamespace = substr($bundleClass, 0, strrpos($bundleClass, '\\') + 1) . 'QueryType';
foreach (glob($bundleQueryTypesDir . DIRECTORY_SEPARATOR . '*QueryType.php') as $queryTypeFilePath) {
$queryTypeFileName = basename($queryTypeFilePath, '.php');
$queryTypeClassName = $bundleQueryTypeNamespace . '\\' . $queryTypeFileName;
if (isset($queryTypesClasses[$queryTypeClassName])) {
continue;
}
if (!class_exists($queryTypeClassName)) {
throw new Exception("Expected $queryTypeClassName to be defined in $queryTypeFilePath");
}

$queryTypeReflectionClass = new ReflectionClass($queryTypeClassName);
if (!$queryTypeReflectionClass->implementsInterface('eZ\Publish\Core\QueryType\QueryType')) {
throw new Exception("$queryTypeClassName needs to implement eZ\\Publish\\Core\\QueryType\\QueryType");
}
$this->checkInterface($queryTypeClassName);

$serviceId = 'ezpublish.query_type.convention.' . strtolower($bundleName) . '_' . strtolower($queryTypeFileName);
$queryTypeServices[$serviceId] = new Definition($queryTypeClassName);

$queryTypes[$queryTypeClassName::getName()] = new Reference($serviceId);
$queryTypeDefinition = new Definition($queryTypeClassName);
$conventionQueryTypeDefs[$serviceId] = $queryTypeDefinition;
$queryTypesRefs[] = new Reference($serviceId);
}
$container->addDefinitions($queryTypeServices);
$container->addDefinitions($conventionQueryTypeDefs);
}
}

$aggregatorDefinition = $container->getDefinition('ezpublish.query_type.registry');
$aggregatorDefinition->addMethodCall('addQueryTypes', [$queryTypes]);
$registryDef = $container->getDefinition('ezpublish.query_type.registry');
$registryDef->addMethodCall('addQueryTypes', [$queryTypesRefs]);
}

/**
* Checks that $queryTypeClassName implements the QueryType interface.
*
* @param string $queryTypeClassName
*
* @throws InvalidArgumentException
*/
private function checkInterface($queryTypeClassName)
{
$queryTypeReflectionClass = new ReflectionClass($queryTypeClassName);
if (!$queryTypeReflectionClass->implementsInterface('eZ\Publish\Core\QueryType\QueryType')) {
throw new InvalidArgumentException(
"QueryTypeClass $queryTypeClassName",
'needs to implement eZ\Publish\Core\QueryType\QueryType'
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Feature: The ez_query controller can be used in content views to get query results into a view template

Scenario: A content view that uses the query controller...
Given there is a blog content_view configuration
And it sets the controller to 'ez_query:contentAction'
And it sets the parameter "query" to a valid QueryType name
When a content matching the blog configuration is rendered
Then the view template has an 'items' variable
And the 'items' variable is an array with the results from the queryType

Scenario: The template variable search results are assigned to can be customized

Scenario: Parameters can be passed to the QueryType

Scenario: Parameters from the view object can be passed to the QueryType
103 changes: 103 additions & 0 deletions eZ/Bundle/EzPublishCoreBundle/Features/Context/NavigationContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace eZ\Bundle\EzPublishCoreBundle\Features\Context;

use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\MinkExtension\Context\MinkAwareContext;
use Behat\MinkExtension\Context\RawMinkContext;
use eZ\Publish\API\Repository\URLAliasService;
use eZ\Publish\API\Repository\Values\Content\Location;
use PHPUnit_Framework_Assert as Assertion;
use Symfony\Component\Routing\RouterInterface;

class NavigationContext extends RawMinkContext implements Context, SnippetAcceptingContext, MinkAwareContext
{
/**
* @var \Symfony\Component\Routing\RouterInterface
*/
private $router;

/**
* @var \eZ\Publish\API\Repository\URLAliasService
*/
private $urlAliasService;

/**
* @var \Symfony\Component\Routing\Route
*/
private $currentRoute;

public function __construct(RouterInterface $router, UrlAliasService $urlAliasService)
{
$this->router = $router;
$this->urlAliasService = $urlAliasService;
}

/**
* @Given /^there is a route "([^"]*)"$/
*/
public function thereIsARoute($routeIdentifier)
{
/** @var \Symfony\Component\Routing\RouterInterface $router */
$routeCollection = $this->router->getRouteCollection();
Assertion::assertNotNull(
$route = $routeCollection->get($routeIdentifier),
"Failed asserting that there is a route named $routeIdentifier"
);

$this->currentRoute = $route;
}

/**
* @Given /^that route has the default "([^"]*)" set to "([^"]*)"$/
*/
public function routeHasTheDefaultSetTo($defaultName, $defaultValue)
{
Assertion::assertNotNull($this->currentRoute, 'No currentRoute was set');

Assertion::assertTrue(
$this->currentRoute->hasDefault($defaultName),
"Failed asserting that the route has the default attribute '$defaultName'"
);

if (is_string($defaultValue)) {
Assertion::assertEquals(
$defaultValue,
$this->currentRoute->getDefault($defaultName),
"Failed asserting that the route has the default attribute '$defaultName' set to '$defaultValue'"
);
} elseif (is_array($defaultValue)) {
Assertion::assertArraySubset(
$defaultValue,
$this->currentRoute->getDefault($defaultName),
"Failed asserting that the route has the default attribute '$defaultName' with the given array items"
);
}
}

/**
* @Given /^that route has the default "([^"]*)" set to an array with the key "([^"]*)" set to "([^"]*)"$/
*/
public function routeHasTheDefaultSetToArray($defaultName, $arrayKey, $arrayValue)
{
$this->routeHasTheDefaultSetTo($defaultName, [$arrayKey => $arrayValue]);
}

/**
* @When /^I go to that route$/
*/
public function iGoToThatRoute()
{
Assertion::assertTrue(isset($this->currentRoute), 'No current Route was set');
$this->visitPath($this->currentRoute->getPath());
}

public function iVisitLocation(Location $location)
{
$urlAlias = $this->urlAliasService->reverseLookup($location);
$this->visitPath($urlAlias->path);
}
}
Loading