Skip to content

Commit

Permalink
EZP-30567: Impl. ez_query:pagingQueryAction to handle pagination (#2651)
Browse files Browse the repository at this point in the history
* Implemented QueryController:pagingQueryAction to handle pagination

QueryController pagingQueryAction returns query results as a Pagerfanta instance.

Co-Authored-By: André R. <[email protected]>

* Added Behat tests coverage for QueryController:pagingQueryAction

Co-Authored-By: Andrew Longosz <[email protected]>
  • Loading branch information
jlchassaing and alongosz committed Oct 24, 2019
1 parent 4bbd25b commit 83b375d
Show file tree
Hide file tree
Showing 3 changed files with 406 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ public function addContentViewConfigurationBlock(PyStringNode $string)
$this->configurationContext->addConfiguration($configuration);
}

/**
* @Given /^the following content view configuration block with paging action:$/
*/
public function addContentViewConfigurationBlockWithPagingAction(PyStringNode $string)
{
$configurationBlock = array_merge(
Yaml::parse($string),
[
'template' => '@eZBehat/tests/dump.html.twig',
'match' => [
'Id\Content' => $this->matchedContent->id,
],
]
);

$configurationBlockName = 'behat_paging_query_controller_' . $this->matchedContent->id;

$configuration = [
'ezpublish' => [
'system' => [
'default' => [
'content_view' => [
'full' => [
$configurationBlockName => $configurationBlock,
],
],
],
],
],
];

$this->configurationContext->addConfiguration($configuration);
}

/**
* @Given /^a content item that matches the view configuration block below$/
*/
Expand All @@ -90,6 +124,18 @@ public function aContentItemThatMatchesTheViewConfigurationBlockBelow()
});
}

/**
* @Given :arg1 contents are created to test paging
*/
public function contentsAreCreatedToTestPaging2($numberOfContents)
{
for ($i = 0; $i < $numberOfContents; ++$i) {
$this->repository->sudo(function (Repository $repository) {
return $this->createFolder($repository);
});
}
}

/**
* @return Content
*/
Expand Down Expand Up @@ -121,7 +167,7 @@ private function createFolder(Repository $repository)
public function createPhpFile($phpFilePath, PyStringNode $phpFileContents)
{
$fs = new Filesystem();
$fs->mkdir(dirname($phpFilePath));
$fs->mkdir(\dirname($phpFilePath));
$fs->dumpFile($phpFilePath, $phpFileContents);
shell_exec('php bin/console --env=behat cache:clear');
}
Expand All @@ -144,7 +190,7 @@ public function visitMatchedContent()
$page = $this->getSession()->getPage();
$exceptionElements = $page->findAll('xpath', "//div[@class='text-exception']/h1");
$exceptionStackTraceItems = $page->findAll('xpath', "//ol[@id='traces-0']/li");
if (count($exceptionElements) > 0) {
if (\count($exceptionElements) > 0) {
$exceptionElement = $exceptionElements[0];
$exceptionLines = [$exceptionElement->getText(), ''];

Expand Down Expand Up @@ -210,4 +256,159 @@ public function theQueryResultsAreAssignedToTheTwigVariable($twigVariableName)
"The $twigVariableName twig variable was not set"
);
}

/**
* @Then the Query results assigned to the :arg1 twig variable is a :arg2 object
*/
public function theQueryResultsAssignedToTheTwigVariableIsAObject($twigVariableName, $className)
{
$variableFound = false;
$classNameFound = false;

$page = $this->getSession()->getPage();
$variableNodes = $page->findAll('css', 'pre.sf-dump > samp > span.sf-dump-key');
$valueNodes = $page->findAll('css', 'pre.sf-dump > samp > abbr.sf-dump-note');

/** @var NodeElement $variableNode */
foreach ($variableNodes as $variableNode) {
if ($variableNode->getText() === $twigVariableName) {
$variableFound = true;
}
}

/** @var NodeElement $valueNodes */
foreach ($valueNodes as $valueNode) {
if ($valueNode->getText() === $className) {
$classNameFound = true;
}
}

Assert::assertTrue(
$variableFound,
"The $twigVariableName twig variable was not set"
);

Assert::assertTrue(
$classNameFound,
"The $className twig variable object was not set"
);
}

/**
* @Given /^the following template defined in "([^"]*)":$/
*/
public function createTemplateFile($tplFilePath, PyStringNode $tplFileContents)
{
$fs = new Filesystem();
$fs->mkdir(\dirname($tplFilePath));
$fs->dumpFile($tplFilePath, $tplFileContents);
}

/**
* @Given the following content view configuration block with paging action and the template set above:
*/
public function theFollowingContentViewConfigurationBlockWithPagingActionAndTheTemplateSetAbove(PyStringNode $string)
{
$configurationBlock = array_merge(
Yaml::parse($string),
[
'match' => [
'Id\Content' => $this->matchedContent->id,
],
]
);

$configurationBlockName = 'behat_paging_query_controller_' . $this->matchedContent->id;

$configuration = [
'ezpublish' => [
'system' => [
'default' => [
'content_view' => [
'full' => [
$configurationBlockName => $configurationBlock,
],
],
],
],
],
];

$this->configurationContext->addConfiguration($configuration);
}

/**
* @When I view a content matched by the view configuration above on page :arg1 with the :arg2 parameter
*/
public function iViewAContentMatchedByTheViewConfigurationAboveOnPageWithTheParameter($pageNumber, $pageParam)
{
$urlAliasService = $this->repository->getURLAliasService();
$urlAlias = $urlAliasService->reverseLookup(
$this->repository->getLocationService()->loadLocation(
$this->matchedContent->contentInfo->mainLocationId
)
);

$this->visitPath($urlAlias->path . "?$pageParam=$pageNumber");

if ($this->getSession()->getStatusCode() !== 200) {
$page = $this->getSession()->getPage();
$exceptionElements = $page->findAll('xpath', "//div[@class='text-exception']/h1");
$exceptionStackTraceItems = $page->findAll('xpath', "//ol[@id='traces-0']/li");
if (\count($exceptionElements) > 0) {
$exceptionElement = $exceptionElements[0];
$exceptionLines = [$exceptionElement->getText(), ''];

foreach ($exceptionStackTraceItems as $stackTraceItem) {
$html = $stackTraceItem->getHtml();
$html = substr($html, 0, strpos($html, '<a href', 1));
$html = htmlspecialchars_decode(strip_tags($html));
$html = preg_replace('/\s+/', ' ', $html);
$html = str_replace(' (', '(', $html);
$html = str_replace(' ->', '->', $html);
$exceptionLines[] = trim($html);
}
$message = 'An exception occurred during rendering:' . implode("\n", $exceptionLines);
Assert::assertTrue(false, $message);
}
}
$this->assertSession()->statusCodeEquals(200);
}

/**
* @Then the Query results assigned to the twig variable is a Pagerfanta object and has limit :arg1 and selected page :arg2
*/
public function theQueryResultsAssignedToTheTwigVariableIsAObjectAndHasLimitAndCountParams($pageLimit, $pageValue)
{
$pageLimitFound = false;
$currentPageFound = false;

$page = $this->getSession()->getPage();
$maxPerPage = $page->findAll('css', 'div#maxPerPage');
$currentPage = $page->findAll('css', 'div#currentPage');

/** @var NodeElement $variableNode */
foreach ($maxPerPage as $variableNode) {
if ($variableNode->getText() === $pageLimit) {
$pageLimitFound = true;
}
}

/** @var NodeElement $valueNodes */
foreach ($currentPage as $valueNode) {
if ($valueNode->getText() === $pageValue) {
$currentPageFound = true;
}
}

Assert::assertTrue(
$pageLimitFound,
"The maxPerPage $pageLimit twig variable was not set"
);

Assert::assertTrue(
$currentPageFound,
"The currentPage $pageValue twig variable was not set"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,151 @@ Scenario: A content view can be configured to run and render a query
Then a LocationChildren Query is built from the LocationChildren QueryType
And a Location Search is executed with the LocationChildren Query
And the Query results are assigned to the "children" twig variable

Scenario: A content view can be configured to run and render a query and return a PagerFanta Object
Given a content item that matches the view configuration block below
And the following content view configuration block with paging action:
"""
controller: ez_query:pagingQueryAction
params:
query:
query_type: 'LocationChildren'
parameters:
parentLocationId: 2
assign_results_to: 'children'
"""
And a LocationChildren QueryType defined in "src/QueryType/LocationChildrenQueryType.php":
"""
<?php
namespace App\QueryType;
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId;
use eZ\Publish\Core\QueryType\QueryType;
class LocationChildrenQueryType implements QueryType
{
public function getQuery(array $parameters = [])
{
return new LocationQuery([
'filter' => new ParentLocationId($parameters['parentLocationId']),
]);
}
public function getSupportedParameters()
{
return ['parentLocationId'];
}
public static function getName()
{
return 'LocationChildren';
}
}
"""
When I view a content matched by the view configuration above
Then the Query results assigned to the "children" twig variable is a "Pagerfanta" object

Scenario: A content view can be configured to run and render a query return a PagerFanta Object and set limit and page name
Given a content item that matches the view configuration block below
And the following template defined in "templates/tests.html.twig":
"""
<div id='currentPage'>{{ children.currentPage }}</div>
<div id='maxPerPage'>{{ children.maxPerPage }}</div>
"""
And the following content view configuration block with paging action and the template set above:
"""
controller: ez_query:pagingQueryAction
template: tests.html.twig
params:
query:
query_type: 'LocationChildren'
parameters:
parentLocationId: 2
limit: 1
assign_results_to: 'children'
"""
And a LocationChildren QueryType defined in "src/QueryType/LocationChildrenQueryType.php":
"""
<?php
namespace App\QueryType;
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId;
use eZ\Publish\Core\QueryType\QueryType;
class LocationChildrenQueryType implements QueryType
{
public function getQuery(array $parameters = [])
{
return new LocationQuery([
'filter' => new ParentLocationId($parameters['parentLocationId']),
]);
}
public function getSupportedParameters()
{
return ['parentLocationId'];
}
public static function getName()
{
return 'LocationChildren';
}
}
"""
When I view a content matched by the view configuration above
Then the Query results assigned to the twig variable is a Pagerfanta object and has limit "1" and selected page "1"

Scenario: A content view can be configured to run and render a query and set a specific page
Given a content item that matches the view configuration block below
And "3" contents are created to test paging
And the following template defined in "templates/tests.html.twig":
"""
<div id='currentPage'>{{ children.currentPage }}</div>
<div id='maxPerPage'>{{ children.maxPerPage }}</div>
"""
And the following content view configuration block with paging action and the template set above:
"""
controller: ez_query:pagingQueryAction
template: tests.html.twig
params:
query:
query_type: 'LocationChildren'
parameters:
parentLocationId: 2
limit: 1
page_param: p
assign_results_to: 'children'
"""
And a LocationChildren QueryType defined in "src/QueryType/LocationChildrenQueryType.php":
"""
<?php
namespace App\QueryType;
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId;
use eZ\Publish\Core\QueryType\QueryType;
class LocationChildrenQueryType implements QueryType
{
public function getQuery(array $parameters = [])
{
return new LocationQuery([
'filter' => new ParentLocationId($parameters['parentLocationId']),
]);
}
public function getSupportedParameters()
{
return ['parentLocationId'];
}
public static function getName()
{
return 'LocationChildren';
}
}
"""
When I view a content matched by the view configuration above on page "2" with the "p" parameter
Then the Query results assigned to the twig variable is a Pagerfanta object and has limit "1" and selected page "2"
Loading

0 comments on commit 83b375d

Please sign in to comment.