mirror of
https://github.com/jbcr/ezmigrationbundle.git
synced 2026-03-24 08:52:08 +01:00
237 lines
8.5 KiB
PHP
237 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace Kaliop\eZMigrationBundle\Core\Matcher;
|
|
|
|
use eZ\Publish\API\Repository\Repository;
|
|
use eZ\Publish\API\Repository\Values\Content\Content;
|
|
use \eZ\Publish\API\Repository\Values\Content\VersionInfo;
|
|
use Kaliop\eZMigrationBundle\API\MatcherInterface;
|
|
use Kaliop\eZMigrationBundle\API\Collection\VersionInfoCollection;
|
|
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException;
|
|
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException;
|
|
|
|
class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterface
|
|
{
|
|
const MATCH_STATUS_DRAFT = 'draft';
|
|
const MATCH_STATUS_PUBLISHED = 'published';
|
|
const MATCH_STATUS_ARCHIVED = 'archived';
|
|
|
|
const MATCH_STATUS = 'version_status';
|
|
const MATCH_VERSION = 'version';
|
|
|
|
const STATUS_MAP = array(
|
|
self::MATCH_STATUS_DRAFT => VersionInfo::STATUS_DRAFT,
|
|
self::MATCH_STATUS_PUBLISHED => VersionInfo::STATUS_PUBLISHED,
|
|
self::MATCH_STATUS_ARCHIVED => VersionInfo::STATUS_ARCHIVED
|
|
);
|
|
|
|
protected $allowedConditions = array(
|
|
self::MATCH_ALL, self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
|
|
self::MATCH_STATUS, self::MATCH_VERSION,
|
|
// aliases
|
|
'status'
|
|
);
|
|
protected $returns = 'VersionInfo';
|
|
|
|
protected $contentMatcher;
|
|
|
|
public function __construct(Repository $repository, MatcherInterface $contentMatcher)
|
|
{
|
|
parent::__construct($repository);
|
|
$this->contentMatcher = $contentMatcher;
|
|
}
|
|
|
|
/**
|
|
* @param array $contentConditions
|
|
* @param array $versionConditions
|
|
* @param array $sort
|
|
* @param int $offset
|
|
* @param int $limit
|
|
* @return VersionInfoCollection
|
|
* @throws InvalidMatchConditionsException
|
|
*/
|
|
public function match(array $contentConditions, array $versionConditions = array(), $sort = array(), $offset = 0, $limit = 0)
|
|
{
|
|
$versions = array();
|
|
|
|
$contentCollection = $this->contentMatcher->match($contentConditions, $sort, $offset, $limit);
|
|
foreach($contentCollection as $content) {
|
|
$versions = array_merge($versions, $this->matchContentVersions($versionConditions, $content));
|
|
}
|
|
|
|
return new VersionInfoCollection($versions);
|
|
}
|
|
|
|
/**
|
|
* Like match, but will throw an exception if there are 0 or more than 1 items matching
|
|
*
|
|
* @param array $contentConditions
|
|
* @param array $versionConditions
|
|
* @param array $sort
|
|
* @param int $offset
|
|
* @return mixed
|
|
* @throws InvalidMatchConditionsException
|
|
* @throws InvalidMatchResultsNumberException
|
|
*/
|
|
public function matchOne(array $contentConditions, array $versionConditions = array(), $sort = array(), $offset = 0)
|
|
{
|
|
$results = $this->match($contentConditions, $versionConditions, $sort, $offset, 2);
|
|
$count = count($results);
|
|
if ($count !== 1) {
|
|
throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
|
|
}
|
|
return reset($results);
|
|
}
|
|
|
|
/**
|
|
* @param array $versionConditions
|
|
* @param Content $content
|
|
* @return VersionInfo[] key: obj_id/version_no
|
|
* @throws InvalidMatchConditionsException
|
|
*/
|
|
public function matchContentVersions(array $versionConditions, Content $content)
|
|
{
|
|
$this->validateConditions($versionConditions);
|
|
|
|
foreach ($versionConditions as $key => $values) {
|
|
|
|
if (!is_array($values)) {
|
|
$values = array($values);
|
|
}
|
|
|
|
switch ($key) {
|
|
case 'status':
|
|
case self::MATCH_STATUS:
|
|
return $this->findContentVersionsByStatus($content, $values);
|
|
|
|
case self::MATCH_VERSION:
|
|
return $this->findContentVersionsByVersionNo($content, $values);
|
|
|
|
case self::MATCH_ALL:
|
|
return $this->findAllContentVersions($content);
|
|
|
|
case self::MATCH_AND:
|
|
return $this->matchAnd($values, $content);
|
|
|
|
case self::MATCH_OR:
|
|
return $this->matchOr($values, $content);
|
|
|
|
case self::MATCH_NOT:
|
|
return array_diff_key($this->findAllContentVersions($content), $this->matchContentVersions($values, $content));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function matchAnd($conditionsArray, $content = null)
|
|
{
|
|
/// @todo introduce proper re-validation of all child conditions
|
|
if (!is_array($conditionsArray) || !count($conditionsArray)) {
|
|
throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'and' clause.");
|
|
}
|
|
|
|
if (is_null($content)) {
|
|
throw new InvalidMatchConditionsException($this->returns . " can not be matched because there was no content to match for 'and' clause.");
|
|
}
|
|
|
|
$results = array();
|
|
foreach ($conditionsArray as $conditions) {
|
|
$out = $this->matchContentVersions($conditions, $content);
|
|
if (!isset($results)) {
|
|
$results = $out;
|
|
} else {
|
|
$results = array_intersect_key($results, $out);
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
protected function matchOr($conditionsArray, $content = null)
|
|
{
|
|
/// @todo introduce proper re-validation of all child conditions
|
|
if (!is_array($conditionsArray) || !count($conditionsArray)) {
|
|
throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'or' clause.");
|
|
}
|
|
|
|
if (is_null($content)) {
|
|
throw new InvalidMatchConditionsException($this->returns . " can not be matched because there was no content to match for 'or' clause.");
|
|
}
|
|
|
|
$results = array();
|
|
foreach ($conditionsArray as $conditions) {
|
|
$out = $this->matchContentVersions($conditions, $content);
|
|
$results = array_replace($results, $out);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* @param Content $content
|
|
* @param string[] $values
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no.
|
|
*/
|
|
protected function findContentVersionsByStatus(Content $content, array $values)
|
|
{
|
|
$versions = array();
|
|
foreach ($this->findAllContentVersions($content) as $versionKey => $versionInfo) {
|
|
foreach($values as $acceptedStatus) {
|
|
if ($versionInfo->status == self::STATUS_MAP[$acceptedStatus]) {
|
|
$versions[$versionKey] = $versionInfo;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return $versions;
|
|
}
|
|
|
|
/**
|
|
* @param Content $content
|
|
* @param int[] $values
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no.
|
|
*/
|
|
protected function findContentVersionsByVersionNo(Content $content, array $values)
|
|
{
|
|
$versions = array();
|
|
$contentVersions = $this->findAllContentVersions($content);
|
|
$contentVersionsCount = count($contentVersions);
|
|
$i = 0;
|
|
foreach ($contentVersions as $versionKey => $versionInfo) {
|
|
foreach($values as $acceptedVersionNo) {
|
|
if ($acceptedVersionNo > 0 ) {
|
|
if ($acceptedVersionNo == $versionInfo->versionNo) {
|
|
$versions[$versionKey] = $versionInfo;
|
|
break;
|
|
}
|
|
} else {
|
|
// negative $acceptedVersionNo means 'leave the last X versions', eg: -1 = leave the last version
|
|
if ($i < $contentVersionsCount + $acceptedVersionNo) {
|
|
$versions[$versionKey] = $versionInfo;
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
$i++;
|
|
}
|
|
return $versions;
|
|
}
|
|
|
|
/**
|
|
* @param Content $content
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no.
|
|
*/
|
|
protected function findAllContentVersions(Content $content)
|
|
{
|
|
$contentVersions = $this->repository->getContentService()->loadVersions($content->contentInfo);
|
|
// different eZ kernels apparently sort versions in different order...
|
|
$sortedVersions = array();
|
|
foreach($contentVersions as $versionInfo) {
|
|
$sortedVersions[$content->contentInfo->id . '/' . $versionInfo->versionNo] = $versionInfo;
|
|
}
|
|
ksort($sortedVersions);
|
|
|
|
return $sortedVersions;
|
|
}
|
|
}
|