1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Kaliop\eZMigrationBundle\Core\Matcher; |
4
|
|
|
|
5
|
|
|
use eZ\Publish\API\Repository\Repository; |
6
|
|
|
use eZ\Publish\API\Repository\Values\Content\Content; |
7
|
|
|
use \eZ\Publish\API\Repository\Values\Content\VersionInfo; |
8
|
|
|
use eZ\Publish\Core\Base\Exceptions\NotFoundException; |
9
|
|
|
use Kaliop\eZMigrationBundle\API\MatcherInterface; |
10
|
|
|
use Kaliop\eZMigrationBundle\API\Collection\VersionInfoCollection; |
11
|
|
|
|
12
|
|
|
class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterface |
13
|
|
|
{ |
14
|
|
|
const MATCH_STATUS_DRAFT = 'draft'; |
15
|
|
|
const MATCH_STATUS_PUBLISHED = 'published'; |
16
|
|
|
const MATCH_STATUS_ARCHIVED = 'archived'; |
17
|
|
|
|
18
|
|
|
const MATCH_STATUS = 'version_status'; |
19
|
|
|
const MATCH_VERSION = 'version'; |
20
|
|
|
|
21
|
|
|
const STATUS_MAP = array( |
22
|
|
|
self::MATCH_STATUS_DRAFT => VersionInfo::STATUS_DRAFT, |
23
|
|
|
self::MATCH_STATUS_PUBLISHED => VersionInfo::STATUS_PUBLISHED, |
24
|
|
|
self::MATCH_STATUS_ARCHIVED => VersionInfo::STATUS_ARCHIVED |
25
|
|
|
); |
26
|
|
|
|
27
|
|
|
protected $allowedConditions = array( |
28
|
|
|
self::MATCH_ALL, self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT, |
29
|
|
|
self::MATCH_STATUS, self::MATCH_VERSION, |
30
|
|
|
// aliases |
31
|
|
|
'status' |
32
|
|
|
); |
33
|
|
|
protected $returns = 'VersionInfo'; |
34
|
|
|
|
35
|
|
|
protected $contentMatcher; |
36
|
|
|
|
37
|
80 |
|
public function __construct(Repository $repository, MatcherInterface $contentMatcher) |
38
|
|
|
{ |
39
|
80 |
|
$this->repository = $repository; |
40
|
80 |
|
$this->contentMatcher = $contentMatcher; |
41
|
80 |
|
} |
42
|
|
|
|
43
|
|
|
public function match(array $contentConditions, array $versionConditions = array(), $sort = array(), $offset = 0, $limit = 0) |
44
|
|
|
{ |
45
|
|
|
$versions = array(); |
46
|
|
|
|
47
|
|
|
$contentCollection = $this->contentMatcher->match($contentConditions, $sort, $offset, $limit); |
|
|
|
|
48
|
|
|
foreach($contentCollection as $content) { |
49
|
|
|
$versions = array_merge($versions, $this->matchContentVersions($versionConditions, $content)); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
return new VersionInfoCollection($versions); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Like match, but will throw an exception if there are 0 or more than 1 items matching |
57
|
|
|
* |
58
|
|
|
* @param array $conditions |
|
|
|
|
59
|
|
|
* @return mixed |
60
|
|
|
* @throws \Exception |
61
|
|
|
*/ |
62
|
|
|
public function matchOne(array $contentConditions, array $versionConditions = array(), $sort = array(), $offset = 0) |
63
|
|
|
{ |
64
|
|
|
$results = $this->match($contentConditions, $versionConditions, $sort, $offset, 2); |
65
|
|
|
$count = count($results); |
66
|
|
|
if ($count !== 1) { |
67
|
|
|
throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); |
68
|
|
|
} |
69
|
|
|
return reset($results); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @param array $versionConditions |
74
|
|
|
* @param Content $content |
75
|
|
|
* @return VersionInfo[] key: obj_id/version_no |
76
|
|
|
*/ |
77
|
|
|
public function matchContentVersions(array $versionConditions, Content $content) |
78
|
|
|
{ |
79
|
|
|
$this->validateConditions($versionConditions); |
80
|
|
|
|
81
|
|
|
foreach ($versionConditions as $key => $values) { |
82
|
|
|
|
83
|
|
|
if (!is_array($values)) { |
84
|
|
|
$values = array($values); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
switch ($key) { |
88
|
|
|
case 'status': |
89
|
|
|
case self::MATCH_STATUS: |
90
|
|
|
return $this->findContentVersionsByStatus($content, $values); |
91
|
|
|
|
92
|
|
|
case self::MATCH_VERSION: |
93
|
|
|
return $this->findContentVersionsByVersionNo($content, $values); |
94
|
|
|
|
95
|
|
|
case self::MATCH_ALL: |
96
|
|
|
return $this->findAllContentVersions($content); |
97
|
|
|
|
98
|
|
|
case self::MATCH_AND: |
99
|
|
|
return $this->matchAnd($values, $content); |
100
|
|
|
|
101
|
|
|
case self::MATCH_OR: |
102
|
|
|
return $this->matchOr($values, $content); |
103
|
|
|
|
104
|
|
|
case self::MATCH_NOT: |
105
|
|
|
return array_diff_key($this->findAllContentVersions($content), $this->matchContentVersions($values, $content)); |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
View Code Duplication |
protected function matchAnd(array $conditionsArray, $content = null) |
|
|
|
|
111
|
|
|
{ |
112
|
|
|
/// @todo introduce proper re-validation of all child conditions |
113
|
|
|
if (!is_array($conditionsArray) || !count($conditionsArray)) { |
114
|
|
|
throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'and' clause."); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
if (is_null($content)) { |
118
|
|
|
throw new \Exception($this->returns . " can not be matched because there was no content to match for 'and' clause."); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
foreach ($conditionsArray as $conditions) { |
122
|
|
|
$out = $this->matchContentVersions($conditions, $content); |
123
|
|
|
if (!isset($results)) { |
124
|
|
|
$results = $out; |
125
|
|
|
} else { |
126
|
|
|
$results = array_intersect_key($results, $out); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
return $results; |
|
|
|
|
131
|
|
|
} |
132
|
|
|
|
133
|
|
View Code Duplication |
protected function matchOr(array $conditionsArray, $content = null) |
|
|
|
|
134
|
|
|
{ |
135
|
|
|
/// @todo introduce proper re-validation of all child conditions |
136
|
|
|
if (!is_array($conditionsArray) || !count($conditionsArray)) { |
137
|
|
|
throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'or' clause."); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
if (is_null($content)) { |
141
|
|
|
throw new \Exception($this->returns . " can not be matched because there was no content to match for 'or' clause."); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$results = array(); |
145
|
|
|
foreach ($conditionsArray as $conditions) { |
146
|
|
|
$out = $this->matchContentVersions($conditions, $content); |
147
|
|
|
$results = array_replace($results, $out); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
return $results; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* @param Content $content |
155
|
|
|
* @param string[] $values |
156
|
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no. |
157
|
|
|
*/ |
158
|
|
|
protected function findContentVersionsByStatus(Content $content, array $values) |
159
|
|
|
{ |
160
|
|
|
$versions = array(); |
161
|
|
|
foreach ($this->findAllContentVersions($content) as $versionKey => $versionInfo) { |
162
|
|
|
foreach($values as $acceptedStatus) { |
163
|
|
|
if ($versionInfo->status == self::STATUS_MAP[$acceptedStatus]) { |
164
|
|
|
$versions[$versionKey] = $versionInfo; |
165
|
|
|
break; |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
return $versions; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @param Content $content |
174
|
|
|
* @param int[] $values |
175
|
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no. |
176
|
|
|
*/ |
177
|
|
|
protected function findContentVersionsByVersionNo(Content $content, array $values) |
178
|
|
|
{ |
179
|
|
|
$versions = array(); |
180
|
|
|
$contentVersions = $this->findAllContentVersions($content); |
181
|
|
|
$contentVersionsCount = count($contentVersions); |
182
|
|
|
$i = 0; |
183
|
|
|
foreach ($contentVersions as $versionKey => $versionInfo) { |
184
|
|
|
foreach($values as $acceptedVersionNo) { |
185
|
|
|
if ($acceptedVersionNo > 0 ) { |
186
|
|
|
if ($acceptedVersionNo == $versionInfo->versionNo) { |
187
|
|
|
$versions[$versionKey] = $versionInfo; |
188
|
|
|
break; |
189
|
|
|
} |
190
|
|
|
} else { |
191
|
|
|
// negative $acceptedVersionNo means 'leave the last X versions', eg: -1 = leave the last version |
192
|
|
|
if ($i < $contentVersionsCount + $acceptedVersionNo) { |
193
|
|
|
$versions[$versionKey] = $versionInfo; |
194
|
|
|
break; |
195
|
|
|
|
196
|
|
|
} |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
$i++; |
200
|
|
|
} |
201
|
|
|
return $versions; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* @param Content $content |
206
|
|
|
* @return VersionInfo[] key: obj_id/version_no, sorted in increasing version no. |
207
|
|
|
*/ |
208
|
|
|
protected function findAllContentVersions(Content $content) |
209
|
|
|
{ |
210
|
|
|
$contentVersions = $this->repository->getContentService()->loadVersions($content->contentInfo); |
211
|
|
|
// different eZ kernels apparently sort versions in different order... |
212
|
|
|
$sortedVersions = array(); |
213
|
|
|
foreach($contentVersions as $versionInfo) { |
214
|
|
|
$sortedVersions[$content->contentInfo->id . '/' . $versionInfo->versionNo] = $versionInfo; |
215
|
|
|
} |
216
|
|
|
ksort($sortedVersions); |
217
|
|
|
|
218
|
|
|
return $sortedVersions; |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.