1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @copyright Copyright (C) eZ Systems AS. All rights reserved. |
5
|
|
|
* @license For full copyright and license information view LICENSE file distributed with this source code. |
6
|
|
|
*/ |
7
|
|
|
declare(strict_types=1); |
8
|
|
|
|
9
|
|
|
namespace eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler; |
10
|
|
|
|
11
|
|
|
use eZ\Publish\API\Repository\FieldTypeService; |
12
|
|
|
use eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter; |
13
|
|
|
use eZ\Publish\Core\Persistence\Database\DatabaseHandler; |
14
|
|
|
use eZ\Publish\API\Repository\Values\Content\Query\Criterion; |
15
|
|
|
use eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry as Registry; |
16
|
|
|
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException; |
17
|
|
|
use eZ\Publish\Core\Persistence\Database\SelectQuery; |
18
|
|
|
use eZ\Publish\SPI\Persistence\Content\Type\Handler as ContentTypeHandler; |
19
|
|
|
use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler; |
20
|
|
|
use eZ\Publish\Core\Persistence\Database\Expression; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Field criterion handler. |
24
|
|
|
*/ |
25
|
|
|
class FieldEmpty extends FieldBase |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* Field converter registry. |
29
|
|
|
* |
30
|
|
|
* @var \eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry |
31
|
|
|
*/ |
32
|
|
|
protected $fieldConverterRegistry; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var \eZ\Publish\API\Repository\FieldTypeService |
36
|
|
|
*/ |
37
|
|
|
protected $fieldTypeService; |
38
|
|
|
|
39
|
|
|
public function __construct( |
40
|
|
|
DatabaseHandler $dbHandler, |
41
|
|
|
ContentTypeHandler $contentTypeHandler, |
42
|
|
|
LanguageHandler $languageHandler, |
43
|
|
|
Registry $fieldConverterRegistry, |
44
|
|
|
FieldTypeService $fieldTypeService |
45
|
|
|
) { |
46
|
|
|
parent::__construct($dbHandler, $contentTypeHandler, $languageHandler); |
47
|
|
|
|
48
|
|
|
$this->fieldConverterRegistry = $fieldConverterRegistry; |
49
|
|
|
$this->fieldTypeService = $fieldTypeService; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Check if this criterion handler accepts to handle the given criterion. |
54
|
|
|
*/ |
55
|
|
|
public function accept(Criterion $criterion): bool |
56
|
|
|
{ |
57
|
|
|
return $criterion instanceof Criterion\IsFieldEmpty; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Returns relevant field information for the specified field. |
62
|
|
|
* |
63
|
|
|
* Returns an array of the attribute, |
64
|
|
|
* identifier and the sort column, which should be used. |
65
|
|
|
* |
66
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If no searchable fields are found for the given $fieldIdentifier. |
67
|
|
|
* @throws \RuntimeException if no converter is found |
68
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
69
|
|
|
*/ |
70
|
|
|
protected function getFieldsInformation(string $fieldIdentifier): array |
71
|
|
|
{ |
72
|
|
|
$fieldMapArray = []; |
73
|
|
|
$fieldMap = $this->contentTypeHandler->getSearchableFieldMap(); |
74
|
|
|
|
75
|
|
|
foreach ($fieldMap as $contentTypeIdentifier => $fieldIdentifierMap) { |
76
|
|
|
if (!isset($fieldIdentifierMap[$fieldIdentifier])) { |
77
|
|
|
continue; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$fieldTypeIdentifier = $fieldIdentifierMap[$fieldIdentifier]['field_type_identifier']; |
81
|
|
|
$fieldMapArray[$fieldTypeIdentifier]['ids'][] = $fieldIdentifierMap[$fieldIdentifier]['field_definition_id']; |
82
|
|
View Code Duplication |
if (!isset($fieldMapArray[$fieldTypeIdentifier]['column'])) { |
|
|
|
|
83
|
|
|
$fieldMapArray[$fieldTypeIdentifier]['column'] = $this->fieldConverterRegistry->getConverter($fieldTypeIdentifier)->getIndexColumn(); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
$fieldType = $this->fieldTypeService->getFieldType($fieldTypeIdentifier); |
87
|
|
|
$fieldMapArray[$fieldTypeIdentifier]['empty_value'] = $fieldType->getEmptyValue(); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if (empty($fieldMapArray)) { |
91
|
|
|
throw new InvalidArgumentException( |
92
|
|
|
'$criterion->target', |
93
|
|
|
"No searchable fields found for the given criterion target '{$fieldIdentifier}'." |
94
|
|
|
); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $fieldMapArray; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Generate query expression for a Criterion this handler accepts. |
102
|
|
|
* |
103
|
|
|
* accept() must be called before calling this method. |
104
|
|
|
* |
105
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotImplementedException If no searchable fields are found for the given criterion target. |
106
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException |
107
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException |
108
|
|
|
*/ |
109
|
|
|
public function handle( |
110
|
|
|
CriteriaConverter $converter, |
111
|
|
|
SelectQuery $query, |
112
|
|
|
Criterion $criterion, |
113
|
|
|
array $languageSettings |
114
|
|
|
): string { |
115
|
|
|
$fieldsInformation = $this->getFieldsInformation($criterion->target); |
116
|
|
|
|
117
|
|
|
$subSelect = $query->subSelect(); |
118
|
|
|
$subSelect->select( |
119
|
|
|
$this->dbHandler->quoteColumn('contentobject_id') |
120
|
|
|
)->from( |
121
|
|
|
$this->dbHandler->quoteTable('ezcontentobject_attribute') |
122
|
|
|
); |
123
|
|
|
|
124
|
|
|
$whereExpressions = []; |
125
|
|
|
|
126
|
|
|
foreach ($fieldsInformation as $fieldTypeIdentifier => $fieldsInfo) { |
127
|
|
|
if ($fieldsInfo['column'] === false) { |
128
|
|
|
continue; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
$filterPlaceholder = $subSelect->bindValue( |
132
|
|
|
$fieldsInfo['empty_value'], |
133
|
|
|
':fieldTypeIdentifier' |
134
|
|
|
); |
135
|
|
|
$filter = $criterion->value[0] |
136
|
|
|
? $subSelect->expr->eq($fieldsInfo['column'], $filterPlaceholder) |
137
|
|
|
: $subSelect->expr->neq($fieldsInfo['column'], $filterPlaceholder); |
138
|
|
|
|
139
|
|
|
$whereExpressions[] = $subSelect->expr->lAnd( |
140
|
|
|
$subSelect->expr->in( |
141
|
|
|
$this->dbHandler->quoteColumn('contentclassattribute_id'), |
142
|
|
|
$fieldsInfo['ids'] |
143
|
|
|
), |
144
|
|
|
$filter |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
return $this->getInExpressionWithFieldConditions( |
149
|
|
|
$query, |
150
|
|
|
$subSelect, |
151
|
|
|
$languageSettings, |
152
|
|
|
$whereExpressions, |
153
|
|
|
$fieldsInformation |
154
|
|
|
); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.