Skip to content

Commit

Permalink
Allow to sort and limit when matching contents, locations
Browse files Browse the repository at this point in the history
  • Loading branch information
gggeek committed Nov 25, 2018
1 parent b2c38b1 commit f910d10
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 40 deletions.
29 changes: 29 additions & 0 deletions API/SortingMatcherInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Kaliop\eZMigrationBundle\API;

interface SortingMatcherInterface extends MatcherInterface
{
/**
* Returns an array of items, or an array-like object, with all items which satisfy the conditions $conditions
*
* @param array $conditions
* @param array $sort
* @param int $offset
* @param int $limit
* @return array|\ArrayObject
*/
public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0);

/**
* Like match, but will throw an exception if there are 0 or more than 1 items matching
*
* @param array $conditions
* @param array $sort
* @param int $offset
* @param int $limit
* @return mixed
* @throws \Exception
*/
public function matchOne(array $conditions, array $sort = array(), $offset = 0, $limit = 0);
}
6 changes: 5 additions & 1 deletion Core/Executor/ContentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,11 @@ protected function matchContents($action, $step)
// convert the references passed in the match
$match = $this->resolveReferencesRecursively($match);

return $this->contentMatcher->match($match);
$offset = isset($step->dsl['match_offset']) ? $this->referenceResolver->resolveReference($step->dsl['match_offset']) : 0;
$limit = isset($step->dsl['match_limit']) ? $this->referenceResolver->resolveReference($step->dsl['match_limit']) : 0;
$sort = isset($step->dsl['match_sort']) ? $this->referenceResolver->resolveReference($step->dsl['match_sort']) : array();

return $this->contentMatcher->match($match, $sort, $offset, $limit);
}

/**
Expand Down
13 changes: 10 additions & 3 deletions Core/Executor/LocationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,11 @@ protected function matchLocations($action, $step)
// convert the references passed in the match
$match = $this->resolveReferencesRecursively($match);

return $this->locationMatcher->match($match);
$offset = isset($step->dsl['match_offset']) ? $this->referenceResolver->resolveReference($step->dsl['match_offset']) : 0;
$limit = isset($step->dsl['match_limit']) ? $this->referenceResolver->resolveReference($step->dsl['match_limit']) : 0;
$sort = isset($step->dsl['match_sort']) ? $this->referenceResolver->resolveReference($step->dsl['match_sort']) : array();

return $this->locationMatcher->match($match, $sort, $offset, $limit);
}

/**
Expand Down Expand Up @@ -416,7 +420,11 @@ protected function matchContents($action, $step)
}
}

return $this->contentMatcher->matchContent($match);
$offset = isset($step->dsl['match_offset']) ? $this->referenceResolver->resolveReference($step->dsl['match_offset']) : 0;
$limit = isset($step->dsl['match_limit']) ? $this->referenceResolver->resolveReference($step->dsl['match_limit']) : 0;
$sort = isset($step->dsl['match_sort']) ? $this->referenceResolver->resolveReference($step->dsl['match_sort']) : array();

return $this->contentMatcher->matchContent($match, $sort, $offset, $limit);
}

protected function setMainLocation(Location $location)
Expand Down Expand Up @@ -466,5 +474,4 @@ public function getSortOrder($newValue, $currentValue = null)

return $sortOrder;
}

}
16 changes: 15 additions & 1 deletion Core/Helper/SortConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ public function hash2SortField($value)
$sortField = null;

if ($value !== null) {
// make life nicer for users - we never use 'contentobject' or 'node' in yml...
if ($value == 'content_id') {
$value = 'contentobject_id';
}
if ($value == 'location_id') {
$value = 'node_id';
}
$sortFieldId = "SORT_FIELD_" . strtoupper($value);

$ref = new \ReflectionClass('eZ\Publish\API\Repository\Values\Content\Location');
Expand All @@ -35,7 +42,14 @@ public function sortField2Hash($value)
$ref = new \ReflectionClass('eZ\Publish\API\Repository\Values\Content\Location');
foreach($ref->getConstants() as $key => $val) {
if (strpos($key, 'SORT_FIELD_') === 0 && $val == $value) {
return strtolower(substr($key, 11));
$out = strtolower(substr($key, 11));
if ($out == 'contentobject_id') {
$out = 'content_id';
}
if ($out == 'node_id') {
$out = 'location_id';
}
return $out;
}
}

Expand Down
53 changes: 38 additions & 15 deletions Core/Matcher/ContentMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Query;
use Kaliop\eZMigrationBundle\API\Collection\ContentCollection;
use Kaliop\eZMigrationBundle\API\SortingMatcherInterface;

class ContentMatcher extends QueryBasedMatcher
class ContentMatcher extends QueryBasedMatcher implements SortingMatcherInterface
{
use FlexibleKeyMatcherTrait;

Expand All @@ -29,18 +30,34 @@ class ContentMatcher extends QueryBasedMatcher

/**
* @param array $conditions key: condition, value: int / string / int[] / string[]
* @param array $sort
* @param int $offset
* @param int $limit
* @return ContentCollection
*/
public function match(array $conditions)
public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
return $this->matchContent($conditions);
return $this->matchContent($conditions, $sort, $offset, $limit);
}

public function matchOne(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$results = $this->match($conditions, $sort, $offset, $limit);
$count = count($results);
if ($count !== 1) {
throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
}
return reset($results);
}

/**
* @param array $conditions key: condition, value: int / string / int[] / string[]
* @param array $sort
* @param int $offset
* @param int $limit
* @return ContentCollection
*/
public function matchContent(array $conditions)
public function matchContent(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$this->validateConditions($conditions);

Expand Down Expand Up @@ -84,20 +101,26 @@ public function matchContent(array $conditions)
}

$query = new Query();
$query->limit = self::INT_MAX_16BIT;
$query->limit = $limit != 0 ? $limit : self::INT_MAX_16BIT;
$query->offset = $offset;
if (isset($query->performCount)) $query->performCount = false;
$query->filter = $this->getQueryCriterion($key, $values);
switch ($key) {
case 'content_type_id':
case self::MATCH_CONTENT_TYPE_ID:
case 'content_type_identifier':
case self::MATCH_CONTENT_TYPE_IDENTIFIER:
// sort objects by depth, lower to higher, so that deleting them has less chances of failure
// NB: we only do this in eZP versions that allow depth sorting on content queries
if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
$query->sortClauses = array(new Query\SortClause\LocationDepth(Query::SORT_DESC));
}
if (!empty($sort)) {
$query->sortClauses = $this->getSortClauses($sort);
} else {
switch ($key) {
case 'content_type_id':
case self::MATCH_CONTENT_TYPE_ID:
case 'content_type_identifier':
case self::MATCH_CONTENT_TYPE_IDENTIFIER:
// sort objects by depth, lower to higher, so that deleting them has less chances of failure
// NB: we only do this in eZP versions that allow depth sorting on content queries
if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
$query->sortClauses = array(new Query\SortClause\LocationDepth(Query::SORT_DESC));
}
}
}

$results = $this->repository->getSearchService()->findContent($query);

$contents = [];
Expand Down
7 changes: 5 additions & 2 deletions Core/Matcher/ContentMatcherDirectLoad.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ class ContentMatcherDirectLoad extends ContentMatcher
* This has the advantage of not going through Solr, and hence having less problems with transactions and indexation delay.
*
* @param array $conditions
* @param array $sort
* @param int $offset
* @param int $limit
* @return ContentCollection
*/
public function matchContent(array $conditions)
public function matchContent(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$match = reset($conditions);
if (count($conditions) === 1 && in_array(($key = key($conditions)), array(self::MATCH_CONTENT_ID, self::MATCH_CONTENT_REMOTE_ID))) {
Expand All @@ -37,6 +40,6 @@ public function matchContent(array $conditions)
return new ContentCollection($contents);
}

return parent::matchContent($conditions);
return parent::matchContent($conditions, $sort, $offset, $limit);
}
}
33 changes: 27 additions & 6 deletions Core/Matcher/LocationMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Kaliop\eZMigrationBundle\Core\Matcher;

use eZ\Publish\API\Repository\Values\Content\Query;
use Kaliop\eZMigrationBundle\API\Collection\LocationCollection;
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
use eZ\Publish\API\Repository\Values\Content\Location;
use Kaliop\eZMigrationBundle\API\Collection\LocationCollection;
use Kaliop\eZMigrationBundle\API\SortingMatcherInterface;

class LocationMatcher extends QueryBasedMatcher
class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterface
{
use FlexibleKeyMatcherTrait;

Expand All @@ -31,25 +32,45 @@ class LocationMatcher extends QueryBasedMatcher

/**
* @param array $conditions key: condition, value: int / string / int[] / string[]
* @param array $sort
* @param int $offset
* @param int $limit
* @return LocationCollection
*/
public function match(array $conditions)
public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
return $this->matchLocation($conditions);
return $this->matchLocation($conditions, $sort, $offset, $limit);
}

public function matchOne(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$results = $this->match($conditions, $sort, $offset, $limit);
$count = count($results);
if ($count !== 1) {
throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
}
return reset($results);
}

/**
* @param array $conditions key: condition, value: value: int / string / int[] / string[]
* @param array $sort
* @param int $offset
* @param int $limit
* @return LocationCollection
*/
public function matchLocation(array $conditions)
public function matchLocation(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$this->validateConditions($conditions);

foreach ($conditions as $key => $values) {

$query = new LocationQuery();
$query->limit = self::INT_MAX_16BIT;
$query->limit = $limit != 0 ? $limit : self::INT_MAX_16BIT;
$query->offset = $offset;
if (!empty($sort)) {
$query->sortClauses = $this->getSortClauses($sort);
}
if (isset($query->performCount)) $query->performCount = false;
$query->filter = $this->getQueryCriterion($key, $values);
$results = $this->repository->getSearchService()->findLocations($query);
Expand Down
8 changes: 6 additions & 2 deletions Core/Matcher/LocationMatcherDirectLoad.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ class LocationMatcherDirectLoad extends LocationMatcher
* This has the advantage of not going through Solr, and hence having less problems with transactions and indexation delay.
*
* @param array $conditions
* @param array $sort
* @param int $offset
* @param int $limit
* @return LocationCollection
*/
public function matchLocation(array $conditions)
public function matchLocation(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
{
$match = reset($conditions);
if (count($conditions) === 1 && in_array(($key = key($conditions)), array(self::MATCH_LOCATION_ID, self::MATCH_LOCATION_REMOTE_ID))) {
Expand All @@ -37,6 +41,6 @@ public function matchLocation(array $conditions)
return new LocationCollection($locations);
}

return parent::matchLocation($conditions);
return parent::matchLocation($conditions, $sort, $offset, $limit);
}
}
Loading

0 comments on commit f910d10

Please sign in to comment.