Complex classes like DoctrineDatabase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DoctrineDatabase, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
43 | class DoctrineDatabase extends Gateway |
||
44 | { |
||
45 | /** |
||
46 | * eZ Doctrine database handler. |
||
47 | * |
||
48 | * @var \eZ\Publish\Core\Persistence\Database\DatabaseHandler |
||
49 | * @deprecated Start to use DBAL $connection instead. |
||
50 | */ |
||
51 | protected $dbHandler; |
||
52 | |||
53 | /** |
||
54 | * The native Doctrine connection. |
||
55 | * |
||
56 | * Meant to be used to transition from eZ/Zeta interface to Doctrine. |
||
57 | * |
||
58 | * @var \Doctrine\DBAL\Connection |
||
59 | */ |
||
60 | protected $connection; |
||
61 | |||
62 | /** |
||
63 | * Query builder. |
||
64 | * |
||
65 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase\QueryBuilder |
||
66 | */ |
||
67 | protected $queryBuilder; |
||
68 | |||
69 | /** |
||
70 | * Caching language handler. |
||
71 | * |
||
72 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\CachingHandler |
||
73 | */ |
||
74 | protected $languageHandler; |
||
75 | |||
76 | /** |
||
77 | * Language mask generator. |
||
78 | * |
||
79 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator |
||
80 | */ |
||
81 | protected $languageMaskGenerator; |
||
82 | |||
83 | /** |
||
84 | * Creates a new gateway based on $db. |
||
85 | * |
||
86 | * @param \eZ\Publish\Core\Persistence\Database\DatabaseHandler $db |
||
87 | * @param \Doctrine\DBAL\Connection $connection |
||
88 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase\QueryBuilder $queryBuilder |
||
89 | * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $languageHandler |
||
90 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator $languageMaskGenerator |
||
91 | */ |
||
92 | public function __construct( |
||
93 | DatabaseHandler $db, |
||
94 | Connection $connection, |
||
95 | QueryBuilder $queryBuilder, |
||
96 | LanguageHandler $languageHandler, |
||
97 | LanguageMaskGenerator $languageMaskGenerator |
||
98 | ) { |
||
99 | $this->dbHandler = $db; |
||
100 | $this->connection = $connection; |
||
101 | $this->queryBuilder = $queryBuilder; |
||
102 | $this->languageHandler = $languageHandler; |
||
|
|||
103 | $this->languageMaskGenerator = $languageMaskGenerator; |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Get context definition for external storage layers. |
||
108 | * |
||
109 | * @return array |
||
110 | */ |
||
111 | public function getContext() |
||
112 | { |
||
113 | return [ |
||
114 | 'identifier' => 'LegacyStorage', |
||
115 | 'connection' => $this->dbHandler, |
||
116 | ]; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Inserts a new content object. |
||
121 | * |
||
122 | * @param \eZ\Publish\SPI\Persistence\Content\CreateStruct $struct |
||
123 | * @param mixed $currentVersionNo |
||
124 | * |
||
125 | * @return int ID |
||
126 | */ |
||
127 | public function insertContentObject(CreateStruct $struct, $currentVersionNo = 1) |
||
128 | { |
||
129 | $initialLanguageId = !empty($struct->mainLanguageId) ? $struct->mainLanguageId : $struct->initialLanguageId; |
||
130 | $initialLanguageCode = $this->languageHandler->load($initialLanguageId)->languageCode; |
||
131 | |||
132 | if (isset($struct->name[$initialLanguageCode])) { |
||
133 | $name = $struct->name[$initialLanguageCode]; |
||
134 | } else { |
||
135 | $name = ''; |
||
136 | } |
||
137 | |||
138 | $q = $this->dbHandler->createInsertQuery(); |
||
139 | $q->insertInto( |
||
140 | $this->dbHandler->quoteTable('ezcontentobject') |
||
141 | )->set( |
||
142 | $this->dbHandler->quoteColumn('id'), |
||
143 | $this->dbHandler->getAutoIncrementValue('ezcontentobject', 'id') |
||
144 | )->set( |
||
145 | $this->dbHandler->quoteColumn('current_version'), |
||
146 | $q->bindValue($currentVersionNo, null, \PDO::PARAM_INT) |
||
147 | )->set( |
||
148 | $this->dbHandler->quoteColumn('name'), |
||
149 | $q->bindValue($name, null, \PDO::PARAM_STR) |
||
150 | )->set( |
||
151 | $this->dbHandler->quoteColumn('contentclass_id'), |
||
152 | $q->bindValue($struct->typeId, null, \PDO::PARAM_INT) |
||
153 | )->set( |
||
154 | $this->dbHandler->quoteColumn('section_id'), |
||
155 | $q->bindValue($struct->sectionId, null, \PDO::PARAM_INT) |
||
156 | )->set( |
||
157 | $this->dbHandler->quoteColumn('owner_id'), |
||
158 | $q->bindValue($struct->ownerId, null, \PDO::PARAM_INT) |
||
159 | )->set( |
||
160 | $this->dbHandler->quoteColumn('initial_language_id'), |
||
161 | $q->bindValue($initialLanguageId, null, \PDO::PARAM_INT) |
||
162 | )->set( |
||
163 | $this->dbHandler->quoteColumn('remote_id'), |
||
164 | $q->bindValue($struct->remoteId, null, \PDO::PARAM_STR) |
||
165 | )->set( |
||
166 | $this->dbHandler->quoteColumn('modified'), |
||
167 | $q->bindValue(0, null, \PDO::PARAM_INT) |
||
168 | )->set( |
||
169 | $this->dbHandler->quoteColumn('published'), |
||
170 | $q->bindValue(0, null, \PDO::PARAM_INT) |
||
171 | )->set( |
||
172 | $this->dbHandler->quoteColumn('status'), |
||
173 | $q->bindValue(ContentInfo::STATUS_DRAFT, null, \PDO::PARAM_INT) |
||
174 | )->set( |
||
175 | $this->dbHandler->quoteColumn('language_mask'), |
||
176 | $q->bindValue( |
||
177 | $this->generateLanguageMask( |
||
178 | $struct->fields, |
||
179 | $initialLanguageCode, |
||
180 | $struct->alwaysAvailable |
||
181 | ), |
||
182 | null, |
||
183 | \PDO::PARAM_INT |
||
184 | ) |
||
185 | ); |
||
186 | |||
187 | $q->prepare()->execute(); |
||
188 | |||
189 | return $this->dbHandler->lastInsertId( |
||
190 | $this->dbHandler->getSequenceName('ezcontentobject', 'id') |
||
191 | ); |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Generates a language mask for $fields. |
||
196 | * |
||
197 | * @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields |
||
198 | * @param string $initialLanguageCode |
||
199 | * @param bool $isAlwaysAvailable |
||
200 | * |
||
201 | * @return int |
||
202 | */ |
||
203 | protected function generateLanguageMask(array $fields, string $initialLanguageCode, bool $isAlwaysAvailable): int |
||
204 | { |
||
205 | $languages = [$initialLanguageCode => true]; |
||
206 | foreach ($fields as $field) { |
||
207 | if (isset($languages[$field->languageCode])) { |
||
208 | continue; |
||
209 | } |
||
210 | |||
211 | $languages[$field->languageCode] = true; |
||
212 | } |
||
213 | |||
214 | return $this->languageMaskGenerator->generateLanguageMaskFromLanguageCodes(array_keys($languages), $isAlwaysAvailable); |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Inserts a new version. |
||
219 | * |
||
220 | * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $versionInfo |
||
221 | * @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields |
||
222 | * |
||
223 | * @return int ID |
||
224 | */ |
||
225 | public function insertVersion(VersionInfo $versionInfo, array $fields) |
||
282 | |||
283 | /** |
||
284 | * Updates an existing content identified by $contentId in respect to $struct. |
||
285 | * |
||
286 | * @param int $contentId |
||
287 | * @param \eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct $struct |
||
288 | * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $prePublishVersionInfo Provided on publish |
||
289 | */ |
||
290 | public function updateContent($contentId, MetadataUpdateStruct $struct, VersionInfo $prePublishVersionInfo = null) |
||
291 | { |
||
292 | $q = $this->dbHandler->createUpdateQuery(); |
||
293 | $q->update($this->dbHandler->quoteTable('ezcontentobject')); |
||
294 | |||
295 | if (isset($struct->name)) { |
||
296 | $q->set( |
||
297 | $this->dbHandler->quoteColumn('name'), |
||
298 | $q->bindValue($struct->name, null, \PDO::PARAM_STR) |
||
299 | ); |
||
300 | } |
||
301 | if (isset($struct->mainLanguageId)) { |
||
302 | $q->set( |
||
303 | $this->dbHandler->quoteColumn('initial_language_id'), |
||
304 | $q->bindValue($struct->mainLanguageId, null, \PDO::PARAM_INT) |
||
305 | ); |
||
306 | } |
||
307 | if (isset($struct->modificationDate)) { |
||
308 | $q->set( |
||
309 | $this->dbHandler->quoteColumn('modified'), |
||
310 | $q->bindValue($struct->modificationDate, null, \PDO::PARAM_INT) |
||
311 | ); |
||
312 | } |
||
313 | if (isset($struct->ownerId)) { |
||
314 | $q->set( |
||
315 | $this->dbHandler->quoteColumn('owner_id'), |
||
316 | $q->bindValue($struct->ownerId, null, \PDO::PARAM_INT) |
||
317 | ); |
||
318 | } |
||
319 | if (isset($struct->publicationDate)) { |
||
320 | $q->set( |
||
321 | $this->dbHandler->quoteColumn('published'), |
||
322 | $q->bindValue($struct->publicationDate, null, \PDO::PARAM_INT) |
||
323 | ); |
||
324 | } |
||
325 | if (isset($struct->remoteId)) { |
||
326 | $q->set( |
||
327 | $this->dbHandler->quoteColumn('remote_id'), |
||
328 | $q->bindValue($struct->remoteId, null, \PDO::PARAM_STR) |
||
329 | ); |
||
330 | } |
||
331 | if ($prePublishVersionInfo !== null) { |
||
332 | $mask = $this->languageMaskGenerator->generateLanguageMaskFromLanguageCodes( |
||
333 | $prePublishVersionInfo->languageCodes, |
||
334 | $struct->alwaysAvailable ?? $prePublishVersionInfo->contentInfo->alwaysAvailable |
||
335 | ); |
||
336 | |||
337 | $q->set( |
||
338 | $this->dbHandler->quoteColumn('language_mask'), |
||
339 | $q->bindValue($mask, null, \PDO::PARAM_INT) |
||
340 | ); |
||
341 | } |
||
342 | if (isset($struct->isHidden)) { |
||
343 | $q->set( |
||
344 | $this->dbHandler->quoteColumn('is_hidden'), |
||
345 | $q->bindValue($struct->isHidden, null, \PDO::PARAM_BOOL) |
||
346 | ); |
||
347 | } |
||
348 | $q->where( |
||
349 | $q->expr->eq( |
||
350 | $this->dbHandler->quoteColumn('id'), |
||
351 | $q->bindValue($contentId, null, \PDO::PARAM_INT) |
||
352 | ) |
||
353 | ); |
||
354 | $q->prepare()->execute(); |
||
355 | |||
356 | // Handle alwaysAvailable flag update separately as it's a more complex task and has impact on several tables |
||
357 | if (isset($struct->alwaysAvailable) || isset($struct->mainLanguageId)) { |
||
358 | $this->updateAlwaysAvailableFlag($contentId, $struct->alwaysAvailable); |
||
359 | } |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Updates version $versionNo for content identified by $contentId, in respect to $struct. |
||
364 | * |
||
365 | * @param int $contentId |
||
366 | * @param int $versionNo |
||
367 | * @param \eZ\Publish\SPI\Persistence\Content\UpdateStruct $struct |
||
368 | */ |
||
369 | public function updateVersion($contentId, $versionNo, UpdateStruct $struct) |
||
411 | |||
412 | /** |
||
413 | * Updates "always available" flag for Content identified by $contentId, in respect to |
||
414 | * Content's current main language and optionally new $alwaysAvailable state. |
||
415 | * |
||
416 | * @param int $contentId |
||
417 | * @param bool|null $alwaysAvailable New "always available" value or null if not defined |
||
418 | */ |
||
419 | public function updateAlwaysAvailableFlag($contentId, $alwaysAvailable = null) |
||
537 | |||
538 | /** |
||
539 | * Sets the status of the version identified by $contentId and $version to $status. |
||
540 | * |
||
541 | * The $status can be one of STATUS_DRAFT, STATUS_PUBLISHED, STATUS_ARCHIVED |
||
542 | * |
||
543 | * @param int $contentId |
||
544 | * @param int $version |
||
545 | * @param int $status |
||
546 | * |
||
547 | * @return bool |
||
548 | */ |
||
549 | public function setStatus($contentId, $version, $status) |
||
604 | |||
605 | public function setPublishedStatus(int $contentId, int $versionNo): void |
||
606 | { |
||
607 | $query = $this->getSetVersionStatusQuery( |
||
608 | $contentId, |
||
609 | $versionNo, |
||
630 | |||
631 | private function getSetVersionStatusQuery( |
||
650 | |||
651 | private function markContentAsPublished(int $contentId, int $versionNo): void |
||
652 | { |
||
653 | $query = $this->connection->createQueryBuilder(); |
||
654 | $query |
||
655 | ->update('ezcontentobject') |
||
656 | ->set('status', ':status') |
||
657 | ->set('current_version', ':versionNo') |
||
658 | ->where('id =:contentId') |
||
659 | ->setParameter('status', ContentInfo::STATUS_PUBLISHED, ParameterType::INTEGER) |
||
660 | ->setParameter('versionNo', $versionNo, ParameterType::INTEGER) |
||
661 | ->setParameter('contentId', $contentId, ParameterType::INTEGER); |
||
662 | $query->execute(); |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * Inserts a new field. |
||
667 | * |
||
668 | * Only used when a new field is created (i.e. a new object or a field in a |
||
669 | * new language!). After that, field IDs need to stay the same, only the |
||
670 | * version number changes. |
||
671 | * |
||
672 | * @param \eZ\Publish\SPI\Persistence\Content $content |
||
673 | * @param \eZ\Publish\SPI\Persistence\Content\Field $field |
||
674 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue $value |
||
675 | * |
||
676 | * @return int ID |
||
677 | */ |
||
678 | public function insertNewField(Content $content, Field $field, StorageFieldValue $value) |
||
696 | |||
697 | /** |
||
698 | * Inserts an existing field. |
||
699 | * |
||
700 | * Used to insert a field with an exsting ID but a new version number. |
||
701 | * |
||
702 | * @param Content $content |
||
703 | * @param Field $field |
||
704 | * @param StorageFieldValue $value |
||
705 | */ |
||
706 | public function insertExistingField(Content $content, Field $field, StorageFieldValue $value) |
||
719 | |||
720 | /** |
||
721 | * Sets field (ezcontentobject_attribute) values to the given query. |
||
722 | * |
||
723 | * @param \eZ\Publish\Core\Persistence\Database\InsertQuery $q |
||
724 | * @param Content $content |
||
725 | * @param Field $field |
||
726 | * @param StorageFieldValue $value |
||
727 | */ |
||
728 | protected function setInsertFieldValues(InsertQuery $q, Content $content, Field $field, StorageFieldValue $value) |
||
774 | |||
775 | /** |
||
776 | * Checks if $languageCode is always available in $content. |
||
777 | * |
||
778 | * @param \eZ\Publish\SPI\Persistence\Content $content |
||
779 | * @param string $languageCode |
||
780 | * |
||
781 | * @return bool |
||
782 | */ |
||
783 | protected function isLanguageAlwaysAvailable(Content $content, $languageCode) |
||
790 | |||
791 | /** |
||
792 | * Updates an existing field. |
||
793 | * |
||
794 | * @param Field $field |
||
795 | * @param StorageFieldValue $value |
||
796 | */ |
||
797 | public function updateField(Field $field, StorageFieldValue $value) |
||
817 | |||
818 | /** |
||
819 | * Sets update fields for $value on $q. |
||
820 | * |
||
821 | * @param \eZ\Publish\Core\Persistence\Database\UpdateQuery $q |
||
822 | * @param StorageFieldValue $value |
||
823 | */ |
||
824 | protected function setFieldUpdateValues(UpdateQuery $q, StorageFieldValue $value) |
||
845 | |||
846 | /** |
||
847 | * Updates an existing, non-translatable field. |
||
848 | * |
||
849 | * @param \eZ\Publish\SPI\Persistence\Content\Field $field |
||
850 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue $value |
||
851 | * @param int $contentId |
||
852 | */ |
||
853 | public function updateNonTranslatableField( |
||
880 | |||
881 | /** |
||
882 | * {@inheritdoc} |
||
883 | */ |
||
884 | public function load($contentId, $version = null, array $translations = null) |
||
888 | |||
889 | /** |
||
890 | * {@inheritdoc} |
||
891 | */ |
||
892 | public function loadContentList(array $contentIds, array $translations = null): array |
||
896 | |||
897 | /** |
||
898 | * @see load(), loadContentList() |
||
899 | * |
||
900 | * @param array $contentIds |
||
901 | * @param int|null $version |
||
902 | * @param string[]|null $translations |
||
903 | * |
||
904 | * @return array |
||
905 | */ |
||
906 | private function internalLoadContent(array $contentIds, int $version = null, array $translations = null): array |
||
992 | |||
993 | /** |
||
994 | * Get query builder to load Content Info data. |
||
995 | * |
||
996 | * @see loadContentInfo(), loadContentInfoByRemoteId(), loadContentInfoList(), loadContentInfoByLocationId() |
||
997 | * |
||
998 | * @param bool $joinMainLocation |
||
999 | * |
||
1000 | * @return \Doctrine\DBAL\Query\QueryBuilder |
||
1001 | */ |
||
1002 | private function createLoadContentInfoQueryBuilder(bool $joinMainLocation = true): DoctrineQueryBuilder |
||
1028 | |||
1029 | /** |
||
1030 | * Loads info for content identified by $contentId. |
||
1031 | * Will basically return a hash containing all field values for ezcontentobject table plus some additional keys: |
||
1032 | * - always_available => Boolean indicating if content's language mask contains alwaysAvailable bit field |
||
1033 | * - main_language_code => Language code for main (initial) language. E.g. "eng-GB". |
||
1034 | * |
||
1035 | * @param int $contentId |
||
1036 | * |
||
1037 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
1038 | * |
||
1039 | * @return array |
||
1040 | */ |
||
1041 | public function loadContentInfo($contentId) |
||
1042 | { |
||
1043 | $queryBuilder = $this->createLoadContentInfoQueryBuilder(); |
||
1044 | $queryBuilder |
||
1045 | ->where('c.id = :id') |
||
1046 | ->setParameter('id', $contentId, ParameterType::INTEGER); |
||
1047 | |||
1048 | $results = $queryBuilder->execute()->fetchAll(FetchMode::ASSOCIATIVE); |
||
1049 | if (empty($results)) { |
||
1050 | throw new NotFound('content', "id: $contentId"); |
||
1051 | } |
||
1052 | |||
1053 | return $results[0]; |
||
1054 | } |
||
1055 | |||
1056 | public function loadContentInfoList(array $contentIds) |
||
1065 | |||
1066 | /** |
||
1067 | * Loads info for a content object identified by its remote ID. |
||
1068 | * |
||
1069 | * Returns an array with the relevant data. |
||
1070 | * |
||
1071 | * @param mixed $remoteId |
||
1072 | * |
||
1073 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
1074 | * |
||
1075 | * @return array |
||
1076 | */ |
||
1077 | public function loadContentInfoByRemoteId($remoteId) |
||
1078 | { |
||
1079 | $queryBuilder = $this->createLoadContentInfoQueryBuilder(); |
||
1080 | $queryBuilder |
||
1081 | ->where('c.remote_id = :id') |
||
1082 | ->setParameter('id', $remoteId, ParameterType::STRING); |
||
1083 | |||
1084 | $results = $queryBuilder->execute()->fetchAll(FetchMode::ASSOCIATIVE); |
||
1085 | if (empty($results)) { |
||
1086 | throw new NotFound('content', "remote_id: $remoteId"); |
||
1087 | } |
||
1088 | |||
1089 | return $results[0]; |
||
1090 | } |
||
1091 | |||
1092 | /** |
||
1093 | * Loads info for a content object identified by its location ID (node ID). |
||
1094 | * |
||
1095 | * Returns an array with the relevant data. |
||
1096 | * |
||
1097 | * @param int $locationId |
||
1098 | * |
||
1099 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
1100 | * |
||
1101 | * @return array |
||
1102 | */ |
||
1103 | public function loadContentInfoByLocationId($locationId) |
||
1104 | { |
||
1105 | $queryBuilder = $this->createLoadContentInfoQueryBuilder(false); |
||
1106 | $queryBuilder |
||
1107 | ->where('t.node_id = :id') |
||
1108 | ->setParameter('id', $locationId, ParameterType::INTEGER); |
||
1109 | |||
1110 | $results = $queryBuilder->execute()->fetchAll(FetchMode::ASSOCIATIVE); |
||
1111 | if (empty($results)) { |
||
1112 | throw new NotFound('content', "node_id: $locationId"); |
||
1113 | } |
||
1114 | |||
1115 | return $results[0]; |
||
1116 | } |
||
1117 | |||
1118 | /** |
||
1119 | * Loads version info for content identified by $contentId and $versionNo. |
||
1120 | * Will basically return a hash containing all field values from ezcontentobject_version table plus following keys: |
||
1121 | * - names => Hash of content object names. Key is the language code, value is the name. |
||
1122 | * - languages => Hash of language ids. Key is the language code (e.g. "eng-GB"), value is the language numeric id without the always available bit. |
||
1123 | * - initial_language_code => Language code for initial language in this version. |
||
1124 | * |
||
1125 | * @param int $contentId |
||
1126 | * @param int|null $versionNo |
||
1127 | * |
||
1128 | * @return array |
||
1129 | */ |
||
1130 | public function loadVersionInfo($contentId, $versionNo = null) |
||
1142 | |||
1143 | /** |
||
1144 | * Returns the number of all versions with given status created by the given $userId for content which is not in Trash. |
||
1145 | * |
||
1146 | * @param int $userId |
||
1147 | * @param int $status |
||
1148 | * |
||
1149 | * @return int |
||
1150 | */ |
||
1151 | public function countVersionsForUser(int $userId, int $status = VersionInfo::STATUS_DRAFT): int |
||
1179 | |||
1180 | /** |
||
1181 | * Returns data for all versions with given status created by the given $userId. |
||
1182 | * |
||
1183 | * @param int $userId |
||
1184 | * @param int $status |
||
1185 | * |
||
1186 | * @return string[][] |
||
1187 | */ |
||
1188 | public function listVersionsForUser($userId, $status = VersionInfo::STATUS_DRAFT) |
||
1206 | |||
1207 | /** |
||
1208 | * {@inheritdoc} |
||
1209 | */ |
||
1210 | public function loadVersionsForUser($userId, $status = VersionInfo::STATUS_DRAFT, int $offset = 0, int $limit = -1): array |
||
1234 | |||
1235 | /** |
||
1236 | * Returns all version data for the given $contentId, optionally filtered by status. |
||
1237 | * |
||
1238 | * Result is returned with oldest version first (using version id as it has index and is auto increment). |
||
1239 | * |
||
1240 | * @param mixed $contentId |
||
1241 | * @param mixed|null $status Optional argument to filter versions by status, like {@see VersionInfo::STATUS_ARCHIVED}. |
||
1242 | * @param int $limit Limit for items returned, -1 means none. |
||
1243 | * |
||
1244 | * @return string[][] |
||
1245 | */ |
||
1246 | public function listVersions($contentId, $status = null, $limit = -1) |
||
1273 | |||
1274 | /** |
||
1275 | * Helper for {@see listVersions()} and {@see listVersionsForUser()} that filters duplicates |
||
1276 | * that are the result of the cartesian product performed by createVersionInfoFindQuery(). |
||
1277 | * |
||
1278 | * @param \eZ\Publish\Core\Persistence\Database\SelectQuery $query |
||
1279 | * |
||
1280 | * @return string[][] |
||
1281 | */ |
||
1282 | private function listVersionsHelper(SelectQuery $query) |
||
1304 | |||
1305 | /** |
||
1306 | * Returns all version numbers for the given $contentId. |
||
1307 | * |
||
1308 | * @param mixed $contentId |
||
1309 | * |
||
1310 | * @return int[] |
||
1311 | */ |
||
1312 | public function listVersionNumbers($contentId) |
||
1313 | { |
||
1314 | $query = $this->dbHandler->createSelectQuery(); |
||
1315 | $query->selectDistinct( |
||
1316 | $this->dbHandler->quoteColumn('version') |
||
1317 | )->from( |
||
1318 | $this->dbHandler->quoteTable('ezcontentobject_version') |
||
1319 | )->where( |
||
1320 | $query->expr->eq( |
||
1321 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1322 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1323 | ) |
||
1324 | ); |
||
1325 | |||
1326 | $statement = $query->prepare(); |
||
1327 | $statement->execute(); |
||
1328 | |||
1329 | return $statement->fetchAll(\PDO::FETCH_COLUMN); |
||
1330 | } |
||
1331 | |||
1332 | /** |
||
1333 | * Returns last version number for content identified by $contentId. |
||
1334 | * |
||
1335 | * @param int $contentId |
||
1336 | * |
||
1337 | * @return int |
||
1338 | */ |
||
1339 | public function getLastVersionNumber($contentId) |
||
1340 | { |
||
1341 | $query = $this->dbHandler->createSelectQuery(); |
||
1342 | $query->select( |
||
1343 | $query->expr->max($this->dbHandler->quoteColumn('version')) |
||
1344 | )->from( |
||
1345 | $this->dbHandler->quoteTable('ezcontentobject_version') |
||
1346 | )->where( |
||
1347 | $query->expr->eq( |
||
1348 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1349 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1350 | ) |
||
1351 | ); |
||
1352 | |||
1353 | $statement = $query->prepare(); |
||
1354 | $statement->execute(); |
||
1355 | |||
1356 | return (int)$statement->fetchColumn(); |
||
1357 | } |
||
1358 | |||
1359 | /** |
||
1360 | * Returns all IDs for locations that refer to $contentId. |
||
1361 | * |
||
1362 | * @param int $contentId |
||
1363 | * |
||
1364 | * @return int[] |
||
1365 | */ |
||
1366 | public function getAllLocationIds($contentId) |
||
1367 | { |
||
1368 | $query = $this->dbHandler->createSelectQuery(); |
||
1369 | $query->select( |
||
1370 | $this->dbHandler->quoteColumn('node_id') |
||
1371 | )->from( |
||
1372 | $this->dbHandler->quoteTable('ezcontentobject_tree') |
||
1373 | )->where( |
||
1374 | $query->expr->eq( |
||
1375 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1376 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1377 | ) |
||
1378 | ); |
||
1379 | |||
1380 | $statement = $query->prepare(); |
||
1381 | $statement->execute(); |
||
1382 | |||
1383 | return $statement->fetchAll(\PDO::FETCH_COLUMN); |
||
1384 | } |
||
1385 | |||
1386 | /** |
||
1387 | * Returns all field IDs of $contentId grouped by their type. |
||
1388 | * If $versionNo is set only field IDs for that version are returned. |
||
1389 | * If $languageCode is set, only field IDs for that language are returned. |
||
1390 | * |
||
1391 | * @param int $contentId |
||
1392 | * @param int|null $versionNo |
||
1393 | * @param string|null $languageCode |
||
1394 | * |
||
1395 | * @return int[][] |
||
1396 | */ |
||
1397 | public function getFieldIdsByType($contentId, $versionNo = null, $languageCode = null) |
||
1443 | |||
1444 | /** |
||
1445 | * Deletes relations to and from $contentId. |
||
1446 | * If $versionNo is set only relations for that version are deleted. |
||
1447 | * |
||
1448 | * @param int $contentId |
||
1449 | * @param int|null $versionNo |
||
1450 | */ |
||
1451 | public function deleteRelations($contentId, $versionNo = null) |
||
1452 | { |
||
1453 | $query = $this->dbHandler->createDeleteQuery(); |
||
1454 | $query->deleteFrom( |
||
1455 | $this->dbHandler->quoteTable('ezcontentobject_link') |
||
1456 | ); |
||
1457 | |||
1458 | if (isset($versionNo)) { |
||
1459 | $query->where( |
||
1460 | $query->expr->lAnd( |
||
1461 | $query->expr->eq( |
||
1462 | $this->dbHandler->quoteColumn('from_contentobject_id'), |
||
1463 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1464 | ), |
||
1465 | $query->expr->eq( |
||
1466 | $this->dbHandler->quoteColumn('from_contentobject_version'), |
||
1467 | $query->bindValue($versionNo, null, \PDO::PARAM_INT) |
||
1468 | ) |
||
1469 | ) |
||
1470 | ); |
||
1471 | } else { |
||
1472 | $query->where( |
||
1473 | $query->expr->lOr( |
||
1474 | $query->expr->eq( |
||
1475 | $this->dbHandler->quoteColumn('from_contentobject_id'), |
||
1476 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1477 | ), |
||
1478 | $query->expr->eq( |
||
1479 | $this->dbHandler->quoteColumn('to_contentobject_id'), |
||
1480 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1481 | ) |
||
1482 | ) |
||
1483 | ); |
||
1484 | } |
||
1485 | |||
1486 | $query->prepare()->execute(); |
||
1487 | } |
||
1488 | |||
1489 | /** |
||
1490 | * Removes relations to Content with $contentId from Relation and RelationList field type fields. |
||
1491 | * |
||
1492 | * @param int $contentId |
||
1493 | */ |
||
1494 | public function removeReverseFieldRelations($contentId) |
||
1544 | |||
1545 | /** |
||
1546 | * Updates field value of RelationList field type identified by given $row data, |
||
1547 | * removing relations toward given $contentId. |
||
1548 | * |
||
1549 | * @param int $contentId |
||
1550 | * @param array $row |
||
1551 | */ |
||
1552 | protected function removeRelationFromRelationListField($contentId, array $row) |
||
1587 | |||
1588 | /** |
||
1589 | * Updates field value of Relation field type identified by given $row data, |
||
1590 | * removing relation data. |
||
1591 | * |
||
1592 | * @param array $row |
||
1593 | */ |
||
1594 | protected function removeRelationFromRelationField(array $row) |
||
1616 | |||
1617 | /** |
||
1618 | * Deletes the field with the given $fieldId. |
||
1619 | * |
||
1620 | * @param int $fieldId |
||
1621 | */ |
||
1622 | public function deleteField($fieldId) |
||
1623 | { |
||
1624 | $query = $this->dbHandler->createDeleteQuery(); |
||
1625 | $query->deleteFrom( |
||
1626 | $this->dbHandler->quoteTable('ezcontentobject_attribute') |
||
1627 | )->where( |
||
1628 | $query->expr->eq( |
||
1629 | $this->dbHandler->quoteColumn('id'), |
||
1630 | $query->bindValue($fieldId, null, \PDO::PARAM_INT) |
||
1631 | ) |
||
1632 | ); |
||
1633 | |||
1634 | $query->prepare()->execute(); |
||
1635 | } |
||
1636 | |||
1637 | /** |
||
1638 | * Deletes all fields of $contentId in all versions. |
||
1639 | * If $versionNo is set only fields for that version are deleted. |
||
1640 | * |
||
1641 | * @param int $contentId |
||
1642 | * @param int|null $versionNo |
||
1643 | */ |
||
1644 | public function deleteFields($contentId, $versionNo = null) |
||
1645 | { |
||
1646 | $query = $this->dbHandler->createDeleteQuery(); |
||
1647 | $query->deleteFrom('ezcontentobject_attribute') |
||
1648 | ->where( |
||
1649 | $query->expr->eq( |
||
1650 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1651 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1652 | ) |
||
1653 | ); |
||
1654 | |||
1655 | if (isset($versionNo)) { |
||
1656 | $query->where( |
||
1657 | $query->expr->eq( |
||
1658 | $this->dbHandler->quoteColumn('version'), |
||
1659 | $query->bindValue($versionNo, null, \PDO::PARAM_INT) |
||
1660 | ) |
||
1661 | ); |
||
1662 | } |
||
1663 | |||
1664 | $query->prepare()->execute(); |
||
1665 | } |
||
1666 | |||
1667 | /** |
||
1668 | * Deletes all versions of $contentId. |
||
1669 | * If $versionNo is set only that version is deleted. |
||
1670 | * |
||
1671 | * @param int $contentId |
||
1672 | * @param int|null $versionNo |
||
1673 | */ |
||
1674 | public function deleteVersions($contentId, $versionNo = null) |
||
1675 | { |
||
1676 | $query = $this->dbHandler->createDeleteQuery(); |
||
1677 | $query->deleteFrom('ezcontentobject_version') |
||
1678 | ->where( |
||
1679 | $query->expr->eq( |
||
1680 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1681 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1682 | ) |
||
1683 | ); |
||
1684 | |||
1685 | if (isset($versionNo)) { |
||
1686 | $query->where( |
||
1687 | $query->expr->eq( |
||
1688 | $this->dbHandler->quoteColumn('version'), |
||
1689 | $query->bindValue($versionNo, null, \PDO::PARAM_INT) |
||
1690 | ) |
||
1691 | ); |
||
1692 | } |
||
1693 | |||
1694 | $query->prepare()->execute(); |
||
1695 | } |
||
1696 | |||
1697 | /** |
||
1698 | * Deletes all names of $contentId. |
||
1699 | * If $versionNo is set only names for that version are deleted. |
||
1700 | * |
||
1701 | * @param int $contentId |
||
1702 | * @param int|null $versionNo |
||
1703 | */ |
||
1704 | public function deleteNames($contentId, $versionNo = null) |
||
1705 | { |
||
1706 | $query = $this->dbHandler->createDeleteQuery(); |
||
1707 | $query->deleteFrom('ezcontentobject_name') |
||
1708 | ->where( |
||
1709 | $query->expr->eq( |
||
1710 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
1711 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
1712 | ) |
||
1713 | ); |
||
1714 | |||
1715 | if (isset($versionNo)) { |
||
1716 | $query->where( |
||
1717 | $query->expr->eq( |
||
1718 | $this->dbHandler->quoteColumn('content_version'), |
||
1719 | $query->bindValue($versionNo, null, \PDO::PARAM_INT) |
||
1720 | ) |
||
1721 | ); |
||
1722 | } |
||
1723 | |||
1724 | $query->prepare()->execute(); |
||
1725 | } |
||
1726 | |||
1727 | /** |
||
1728 | * Sets the name for Content $contentId in version $version to $name in $language. |
||
1729 | * |
||
1730 | * @param int $contentId |
||
1731 | * @param int $version |
||
1732 | * @param string $name |
||
1733 | * @param string $language |
||
1734 | */ |
||
1735 | public function setName($contentId, $version, $name, $language) |
||
1796 | |||
1797 | /** |
||
1798 | * Returns a language sub select query for setName. |
||
1799 | * |
||
1800 | * Return sub select query which gets proper language mask for alwaysAvailable Content. |
||
1801 | * |
||
1802 | * @return \eZ\Publish\Core\Persistence\Database\SelectQuery |
||
1803 | */ |
||
1804 | private function getLanguageQuery() |
||
1843 | |||
1844 | /** |
||
1845 | * Deletes the actual content object referred to by $contentId. |
||
1846 | * |
||
1847 | * @param int $contentId |
||
1848 | */ |
||
1849 | public function deleteContent($contentId) |
||
1850 | { |
||
1851 | $query = $this->dbHandler->createDeleteQuery(); |
||
1852 | $query->deleteFrom('ezcontentobject') |
||
1853 | ->where( |
||
1854 | $query->expr->eq( |
||
1855 | $this->dbHandler->quoteColumn('id'), |
||
1862 | |||
1863 | /** |
||
1864 | * Loads relations from $contentId to published content, optionally only from $contentVersionNo. |
||
1865 | * |
||
1866 | * $relationType can also be filtered. |
||
1867 | * |
||
1868 | * @param int $contentId |
||
1869 | * @param int $contentVersionNo |
||
1870 | * @param int $relationType |
||
1871 | * |
||
1872 | * @return string[][] array of relation data |
||
1873 | */ |
||
1874 | public function loadRelations($contentId, $contentVersionNo = null, $relationType = null) |
||
1942 | |||
1943 | /** |
||
1944 | * {@inheritdoc} |
||
1945 | */ |
||
1946 | public function countReverseRelations(int $toContentId, ?int $relationType = null): int |
||
1981 | |||
1982 | /** |
||
1983 | * Loads data that related to $toContentId. |
||
1984 | * |
||
1985 | * @param int $toContentId |
||
1986 | * @param int $relationType |
||
1987 | * |
||
1988 | * @return mixed[][] Content data, array structured like {@see \eZ\Publish\Core\Persistence\Legacy\Content\Gateway::load()} |
||
1989 | */ |
||
1990 | public function loadReverseRelations($toContentId, $relationType = null) |
||
2039 | |||
2040 | /** |
||
2041 | * {@inheritdoc} |
||
2042 | */ |
||
2043 | public function listReverseRelations(int $toContentId, int $offset = 0, int $limit = -1, ?int $relationType = null): array |
||
2081 | |||
2082 | /** |
||
2083 | * Inserts a new relation database record. |
||
2084 | * |
||
2085 | * @param \eZ\Publish\SPI\Persistence\Content\Relation\CreateStruct $createStruct |
||
2086 | * |
||
2087 | * @return int ID the inserted ID |
||
2088 | */ |
||
2089 | public function insertRelation(RelationCreateStruct $createStruct) |
||
2120 | |||
2121 | /** |
||
2122 | * Deletes the relation with the given $relationId. |
||
2123 | * |
||
2124 | * @param int $relationId |
||
2125 | * @param int $type {@see \eZ\Publish\API\Repository\Values\Content\Relation::COMMON, |
||
2126 | * \eZ\Publish\API\Repository\Values\Content\Relation::EMBED, |
||
2127 | * \eZ\Publish\API\Repository\Values\Content\Relation::LINK, |
||
2128 | * \eZ\Publish\API\Repository\Values\Content\Relation::FIELD} |
||
2129 | */ |
||
2130 | public function deleteRelation($relationId, $type) |
||
2192 | |||
2193 | /** |
||
2194 | * Returns all Content IDs for a given $contentTypeId. |
||
2195 | * |
||
2196 | * @param int $contentTypeId |
||
2197 | * |
||
2198 | * @return int[] |
||
2199 | */ |
||
2200 | public function getContentIdsByContentTypeId($contentTypeId) |
||
2218 | |||
2219 | /** |
||
2220 | * Load name data for set of content id's and corresponding version number. |
||
2221 | * |
||
2222 | * @param array[] $rows array of hashes with 'id' and 'version' to load names for |
||
2223 | * |
||
2224 | * @return array |
||
2225 | */ |
||
2226 | public function loadVersionedNameData($rows) |
||
2249 | |||
2250 | /** |
||
2251 | * Batch method for copying all relation meta data for copied Content object. |
||
2252 | * |
||
2253 | * {@inheritdoc} |
||
2254 | * |
||
2255 | * @param int $originalContentId |
||
2256 | * @param int $copiedContentId |
||
2257 | * @param int|null $versionNo If specified only copy for a given version number, otherwise all. |
||
2258 | */ |
||
2259 | public function copyRelations($originalContentId, $copiedContentId, $versionNo = null) |
||
2279 | |||
2280 | /** |
||
2281 | * Remove the specified translation from the Content Object Version. |
||
2282 | * |
||
2283 | * @param int $contentId |
||
2284 | * @param string $languageCode language code of the translation |
||
2285 | * @throws \Doctrine\DBAL\DBALException |
||
2286 | */ |
||
2287 | public function deleteTranslationFromContent($contentId, $languageCode) |
||
2303 | |||
2304 | /** |
||
2305 | * Delete Content fields (attributes) for the given Translation. |
||
2306 | * If $versionNo is given, fields for that Version only will be deleted. |
||
2307 | * |
||
2308 | * @param string $languageCode |
||
2309 | * @param int $contentId |
||
2310 | * @param int $versionNo (optional) filter by versionNo |
||
2311 | */ |
||
2312 | public function deleteTranslatedFields($languageCode, $contentId, $versionNo = null) |
||
2336 | |||
2337 | /** |
||
2338 | * Delete the specified Translation from the given Version. |
||
2339 | * |
||
2340 | * @param int $contentId |
||
2341 | * @param int $versionNo |
||
2342 | * @param string $languageCode |
||
2343 | * @throws \Doctrine\DBAL\DBALException |
||
2344 | */ |
||
2345 | public function deleteTranslationFromVersion($contentId, $versionNo, $languageCode) |
||
2360 | |||
2361 | /** |
||
2362 | * Delete translation from the ezcontentobject_name table. |
||
2363 | * |
||
2364 | * @param int $contentId |
||
2365 | * @param string $languageCode |
||
2366 | * @param int $versionNo optional, if specified, apply to this Version only. |
||
2367 | */ |
||
2368 | private function deleteTranslationFromContentNames($contentId, $languageCode, $versionNo = null) |
||
2392 | |||
2393 | /** |
||
2394 | * Remove language from language_mask of ezcontentobject. |
||
2395 | * |
||
2396 | * @param int $contentId |
||
2397 | * @param int $languageId |
||
2398 | * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException |
||
2399 | */ |
||
2400 | private function deleteTranslationFromContentObject($contentId, $languageId) |
||
2429 | |||
2430 | /** |
||
2431 | * Remove language from language_mask of ezcontentobject_version and update initialLanguageId |
||
2432 | * if it matches the removed one. |
||
2433 | * |
||
2434 | * @param int $contentId |
||
2435 | * @param int $languageId |
||
2436 | * @param int $versionNo optional, if specified, apply to this Version only. |
||
2437 | * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException |
||
2438 | */ |
||
2439 | private function deleteTranslationFromContentVersions($contentId, $languageId, $versionNo = null) |
||
2483 | |||
2484 | /** |
||
2485 | * Get query builder for content version objects, used for version loading w/o fields. |
||
2486 | * |
||
2487 | * Creates a select query with all necessary joins to fetch a complete |
||
2488 | * content object. Does not apply any WHERE conditions, and does not contain |
||
2489 | * name data as it will lead to large result set {@see createNamesQuery}. |
||
2490 | * |
||
2491 | * @return \Doctrine\DBAL\Query\QueryBuilder |
||
2492 | */ |
||
2493 | private function createVersionInfoFindQueryBuilder(): DoctrineQueryBuilder |
||
2546 | |||
2547 | /** |
||
2548 | * Creates a select query for content relations. |
||
2549 | * |
||
2550 | * @return \Doctrine\DBAL\Query\QueryBuilder |
||
2551 | */ |
||
2552 | public function createRelationFindQuery(): DoctrineQueryBuilder |
||
2570 | } |
||
2571 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.