Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
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 |
||
| 40 | class DoctrineDatabase extends Gateway |
||
| 41 | { |
||
| 42 | /** |
||
| 43 | * eZ Doctrine database handler. |
||
| 44 | * |
||
| 45 | * @var \eZ\Publish\Core\Persistence\Database\DatabaseHandler |
||
| 46 | */ |
||
| 47 | protected $dbHandler; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * The native Doctrine connection. |
||
| 51 | * |
||
| 52 | * Meant to be used to transition from eZ/Zeta interface to Doctrine. |
||
| 53 | * |
||
| 54 | * @var \Doctrine\DBAL\Connection |
||
| 55 | */ |
||
| 56 | protected $connection; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * Query builder. |
||
| 60 | * |
||
| 61 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase\QueryBuilder |
||
| 62 | */ |
||
| 63 | protected $queryBuilder; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Caching language handler. |
||
| 67 | * |
||
| 68 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\CachingHandler |
||
| 69 | */ |
||
| 70 | protected $languageHandler; |
||
| 71 | |||
| 72 | /** |
||
| 73 | * Language mask generator. |
||
| 74 | * |
||
| 75 | * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator |
||
| 76 | */ |
||
| 77 | protected $languageMaskGenerator; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * Creates a new gateway based on $db. |
||
| 81 | * |
||
| 82 | * @param \eZ\Publish\Core\Persistence\Database\DatabaseHandler $db |
||
| 83 | * @param \Doctrine\DBAL\Connection $connection |
||
| 84 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase\QueryBuilder $queryBuilder |
||
| 85 | * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $languageHandler |
||
| 86 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator $languageMaskGenerator |
||
| 87 | */ |
||
| 88 | public function __construct( |
||
| 89 | DatabaseHandler $db, |
||
| 90 | Connection $connection, |
||
| 91 | QueryBuilder $queryBuilder, |
||
| 92 | LanguageHandler $languageHandler, |
||
| 93 | LanguageMaskGenerator $languageMaskGenerator |
||
| 94 | ) { |
||
| 95 | $this->dbHandler = $db; |
||
| 96 | $this->connection = $connection; |
||
| 97 | $this->queryBuilder = $queryBuilder; |
||
| 98 | $this->languageHandler = $languageHandler; |
||
|
|
|||
| 99 | $this->languageMaskGenerator = $languageMaskGenerator; |
||
| 100 | } |
||
| 101 | |||
| 102 | /** |
||
| 103 | * Get context definition for external storage layers. |
||
| 104 | * |
||
| 105 | * @return array |
||
| 106 | */ |
||
| 107 | public function getContext() |
||
| 114 | |||
| 115 | /** |
||
| 116 | * Inserts a new content object. |
||
| 117 | * |
||
| 118 | * @param \eZ\Publish\SPI\Persistence\Content\CreateStruct $struct |
||
| 119 | * @param mixed $currentVersionNo |
||
| 120 | * |
||
| 121 | * @return int ID |
||
| 122 | */ |
||
| 123 | public function insertContentObject(CreateStruct $struct, $currentVersionNo = 1) |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Generates a language mask for $version. |
||
| 190 | * |
||
| 191 | * @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields |
||
| 192 | * @param string $initialLanguageCode |
||
| 193 | * @param bool $alwaysAvailable |
||
| 194 | * |
||
| 195 | * @return int |
||
| 196 | */ |
||
| 197 | protected function generateLanguageMask(array $fields, $initialLanguageCode, $alwaysAvailable) |
||
| 198 | { |
||
| 199 | $languages = array($initialLanguageCode => true); |
||
| 200 | View Code Duplication | foreach ($fields as $field) { |
|
| 201 | if (isset($languages[$field->languageCode])) { |
||
| 202 | continue; |
||
| 203 | } |
||
| 204 | |||
| 205 | $languages[$field->languageCode] = true; |
||
| 206 | } |
||
| 207 | |||
| 208 | if ($alwaysAvailable) { |
||
| 209 | $languages['always-available'] = true; |
||
| 210 | } |
||
| 211 | |||
| 212 | return $this->languageMaskGenerator->generateLanguageMask($languages); |
||
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Inserts a new version. |
||
| 217 | * |
||
| 218 | * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $versionInfo |
||
| 219 | * @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields |
||
| 220 | * |
||
| 221 | * @return int ID |
||
| 222 | */ |
||
| 223 | public function insertVersion(VersionInfo $versionInfo, array $fields) |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Updates an existing content identified by $contentId in respect to $struct. |
||
| 283 | * |
||
| 284 | * @param int $contentId |
||
| 285 | * @param \eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct $struct |
||
| 286 | * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $prePublishVersionInfo Provided on publish |
||
| 287 | */ |
||
| 288 | public function updateContent($contentId, MetadataUpdateStruct $struct, VersionInfo $prePublishVersionInfo = null) |
||
| 289 | { |
||
| 290 | $q = $this->dbHandler->createUpdateQuery(); |
||
| 291 | $q->update($this->dbHandler->quoteTable('ezcontentobject')); |
||
| 292 | |||
| 293 | if (isset($struct->name)) { |
||
| 294 | $q->set( |
||
| 295 | $this->dbHandler->quoteColumn('name'), |
||
| 296 | $q->bindValue($struct->name, null, \PDO::PARAM_STR) |
||
| 297 | ); |
||
| 298 | } |
||
| 299 | if (isset($struct->mainLanguageId)) { |
||
| 300 | $q->set( |
||
| 301 | $this->dbHandler->quoteColumn('initial_language_id'), |
||
| 302 | $q->bindValue($struct->mainLanguageId, null, \PDO::PARAM_INT) |
||
| 303 | ); |
||
| 304 | } |
||
| 305 | if (isset($struct->modificationDate)) { |
||
| 306 | $q->set( |
||
| 307 | $this->dbHandler->quoteColumn('modified'), |
||
| 308 | $q->bindValue($struct->modificationDate, null, \PDO::PARAM_INT) |
||
| 309 | ); |
||
| 310 | } |
||
| 311 | if (isset($struct->ownerId)) { |
||
| 312 | $q->set( |
||
| 313 | $this->dbHandler->quoteColumn('owner_id'), |
||
| 314 | $q->bindValue($struct->ownerId, null, \PDO::PARAM_INT) |
||
| 315 | ); |
||
| 316 | } |
||
| 317 | if (isset($struct->publicationDate)) { |
||
| 318 | $q->set( |
||
| 319 | $this->dbHandler->quoteColumn('published'), |
||
| 320 | $q->bindValue($struct->publicationDate, null, \PDO::PARAM_INT) |
||
| 321 | ); |
||
| 322 | } |
||
| 323 | if (isset($struct->remoteId)) { |
||
| 324 | $q->set( |
||
| 325 | $this->dbHandler->quoteColumn('remote_id'), |
||
| 326 | $q->bindValue($struct->remoteId, null, \PDO::PARAM_STR) |
||
| 327 | ); |
||
| 328 | } |
||
| 329 | if ($prePublishVersionInfo !== null) { |
||
| 330 | $languages = []; |
||
| 331 | foreach ($prePublishVersionInfo->languageCodes as $languageCodes) { |
||
| 332 | if (!isset($languages[$languageCodes])) { |
||
| 333 | $languages[$languageCodes] = true; |
||
| 334 | } |
||
| 335 | } |
||
| 336 | |||
| 337 | $languages['always-available'] = isset($struct->alwaysAvailable) ? $struct->alwaysAvailable : |
||
| 338 | $prePublishVersionInfo->contentInfo->alwaysAvailable; |
||
| 339 | |||
| 340 | $mask = $this->languageMaskGenerator->generateLanguageMask($languages); |
||
| 341 | |||
| 342 | $q->set( |
||
| 343 | $this->dbHandler->quoteColumn('language_mask'), |
||
| 344 | $q->bindValue($mask, null, \PDO::PARAM_INT) |
||
| 345 | ); |
||
| 346 | } |
||
| 347 | $q->where( |
||
| 348 | $q->expr->eq( |
||
| 349 | $this->dbHandler->quoteColumn('id'), |
||
| 350 | $q->bindValue($contentId, null, \PDO::PARAM_INT) |
||
| 351 | ) |
||
| 352 | ); |
||
| 353 | $q->prepare()->execute(); |
||
| 354 | |||
| 355 | // Handle alwaysAvailable flag update separately as it's a more complex task and has impact on several tables |
||
| 356 | if (isset($struct->alwaysAvailable) || isset($struct->mainLanguageId)) { |
||
| 357 | $this->updateAlwaysAvailableFlag($contentId, $struct->alwaysAvailable); |
||
| 358 | } |
||
| 359 | } |
||
| 360 | |||
| 361 | /** |
||
| 362 | * Updates version $versionNo for content identified by $contentId, in respect to $struct. |
||
| 363 | * |
||
| 364 | * @param int $contentId |
||
| 365 | * @param int $versionNo |
||
| 366 | * @param \eZ\Publish\SPI\Persistence\Content\UpdateStruct $struct |
||
| 367 | */ |
||
| 368 | public function updateVersion($contentId, $versionNo, UpdateStruct $struct) |
||
| 410 | |||
| 411 | /** |
||
| 412 | * Updates "always available" flag for Content identified by $contentId, in respect to |
||
| 413 | * Content's current main language and optionally new $alwaysAvailable state. |
||
| 414 | * |
||
| 415 | * @param int $contentId |
||
| 416 | * @param bool|null $alwaysAvailable New "always available" value or null if not defined |
||
| 417 | */ |
||
| 418 | public function updateAlwaysAvailableFlag($contentId, $alwaysAvailable = null) |
||
| 536 | |||
| 537 | /** |
||
| 538 | * Sets the status of the version identified by $contentId and $version to $status. |
||
| 539 | * |
||
| 540 | * The $status can be one of STATUS_DRAFT, STATUS_PUBLISHED, STATUS_ARCHIVED |
||
| 541 | * |
||
| 542 | * @param int $contentId |
||
| 543 | * @param int $version |
||
| 544 | * @param int $status |
||
| 545 | * |
||
| 546 | * @return bool |
||
| 547 | */ |
||
| 548 | public function setStatus($contentId, $version, $status) |
||
| 603 | |||
| 604 | /** |
||
| 605 | * Inserts a new field. |
||
| 606 | * |
||
| 607 | * Only used when a new field is created (i.e. a new object or a field in a |
||
| 608 | * new language!). After that, field IDs need to stay the same, only the |
||
| 609 | * version number changes. |
||
| 610 | * |
||
| 611 | * @param \eZ\Publish\SPI\Persistence\Content $content |
||
| 612 | * @param \eZ\Publish\SPI\Persistence\Content\Field $field |
||
| 613 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue $value |
||
| 614 | * |
||
| 615 | * @return int ID |
||
| 616 | */ |
||
| 617 | public function insertNewField(Content $content, Field $field, StorageFieldValue $value) |
||
| 635 | |||
| 636 | /** |
||
| 637 | * Inserts an existing field. |
||
| 638 | * |
||
| 639 | * Used to insert a field with an exsting ID but a new version number. |
||
| 640 | * |
||
| 641 | * @param Content $content |
||
| 642 | * @param Field $field |
||
| 643 | * @param StorageFieldValue $value |
||
| 644 | */ |
||
| 645 | public function insertExistingField(Content $content, Field $field, StorageFieldValue $value) |
||
| 658 | |||
| 659 | /** |
||
| 660 | * Sets field (ezcontentobject_attribute) values to the given query. |
||
| 661 | * |
||
| 662 | * @param \eZ\Publish\Core\Persistence\Database\InsertQuery $q |
||
| 663 | * @param Content $content |
||
| 664 | * @param Field $field |
||
| 665 | * @param StorageFieldValue $value |
||
| 666 | */ |
||
| 667 | protected function setInsertFieldValues(InsertQuery $q, Content $content, Field $field, StorageFieldValue $value) |
||
| 713 | |||
| 714 | /** |
||
| 715 | * Checks if $languageCode is always available in $content. |
||
| 716 | * |
||
| 717 | * @param \eZ\Publish\SPI\Persistence\Content $content |
||
| 718 | * @param string $languageCode |
||
| 719 | * |
||
| 720 | * @return bool |
||
| 721 | */ |
||
| 722 | protected function isLanguageAlwaysAvailable(Content $content, $languageCode) |
||
| 729 | |||
| 730 | /** |
||
| 731 | * Updates an existing field. |
||
| 732 | * |
||
| 733 | * @param Field $field |
||
| 734 | * @param StorageFieldValue $value |
||
| 735 | */ |
||
| 736 | public function updateField(Field $field, StorageFieldValue $value) |
||
| 756 | |||
| 757 | /** |
||
| 758 | * Sets update fields for $value on $q. |
||
| 759 | * |
||
| 760 | * @param \eZ\Publish\Core\Persistence\Database\UpdateQuery $q |
||
| 761 | * @param StorageFieldValue $value |
||
| 762 | */ |
||
| 763 | protected function setFieldUpdateValues(UpdateQuery $q, StorageFieldValue $value) |
||
| 784 | |||
| 785 | /** |
||
| 786 | * Updates an existing, non-translatable field. |
||
| 787 | * |
||
| 788 | * @param \eZ\Publish\SPI\Persistence\Content\Field $field |
||
| 789 | * @param \eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue $value |
||
| 790 | * @param int $contentId |
||
| 791 | */ |
||
| 792 | public function updateNonTranslatableField( |
||
| 819 | |||
| 820 | /** |
||
| 821 | * Loads data for a content object. |
||
| 822 | * |
||
| 823 | * Returns an array with the relevant data. |
||
| 824 | * |
||
| 825 | * @param mixed $contentId |
||
| 826 | * @param mixed $version |
||
| 827 | * @param string[] $translations |
||
| 828 | * |
||
| 829 | * @return array |
||
| 830 | */ |
||
| 831 | public function load($contentId, $version, array $translations = null) |
||
| 851 | |||
| 852 | /** |
||
| 853 | * @see loadContentInfo(), loadContentInfoByRemoteId(), loadContentInfoList() |
||
| 854 | * |
||
| 855 | * @param string $column |
||
| 856 | * @param array $ids Array of int, or if $bindype is set to Connection::PARAM_STR_ARRAY then array of string |
||
| 857 | * @param int $bindType One of Connection::PARAM_*_ARRAY constants. |
||
| 858 | * |
||
| 859 | * @return array |
||
| 860 | */ |
||
| 861 | private function internalLoadContentInfo(string $column, array $ids, int $bindType = Connection::PARAM_INT_ARRAY) : array |
||
| 862 | { |
||
| 863 | $q = $this->connection->createQueryBuilder(); |
||
| 864 | $q |
||
| 865 | ->select('c.*', 't.main_node_id AS ezcontentobject_tree_main_node_id') |
||
| 866 | ->from('ezcontentobject', 'c') |
||
| 867 | ->leftJoin( |
||
| 868 | 'c', |
||
| 869 | 'ezcontentobject_tree', |
||
| 870 | 't', |
||
| 871 | 'c.id = t.contentobject_id AND t.node_id = t.main_node_id' |
||
| 872 | )->where("c.${column} IN (:ids)") |
||
| 873 | ->setParameter('ids', $ids, $bindType); |
||
| 874 | |||
| 875 | return $q->execute()->fetchAll(); |
||
| 876 | } |
||
| 877 | |||
| 878 | /** |
||
| 879 | * Loads info for content identified by $contentId. |
||
| 880 | * Will basically return a hash containing all field values for ezcontentobject table plus some additional keys: |
||
| 881 | * - always_available => Boolean indicating if content's language mask contains alwaysAvailable bit field |
||
| 882 | * - main_language_code => Language code for main (initial) language. E.g. "eng-GB". |
||
| 883 | * |
||
| 884 | * @param int $contentId |
||
| 885 | * |
||
| 886 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
| 887 | * |
||
| 888 | * @return array |
||
| 889 | */ |
||
| 890 | View Code Duplication | public function loadContentInfo($contentId) |
|
| 891 | { |
||
| 892 | $results = $this->internalLoadContentInfo('id', [$contentId]); |
||
| 893 | if (empty($results)) { |
||
| 894 | throw new NotFound('content', "id: $contentId"); |
||
| 895 | } |
||
| 896 | |||
| 897 | return $results[0]; |
||
| 898 | } |
||
| 899 | |||
| 900 | /** |
||
| 901 | * @inheritDoc |
||
| 902 | */ |
||
| 903 | public function loadContentInfoList(array $contentIds) |
||
| 904 | { |
||
| 905 | return $this->internalLoadContentInfo('id', $contentIds); |
||
| 906 | } |
||
| 907 | |||
| 908 | /** |
||
| 909 | * Loads info for a content object identified by its remote ID. |
||
| 910 | * |
||
| 911 | * Returns an array with the relevant data. |
||
| 912 | * |
||
| 913 | * @param mixed $remoteId |
||
| 914 | * |
||
| 915 | * @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException |
||
| 916 | * |
||
| 917 | * @return array |
||
| 918 | */ |
||
| 919 | View Code Duplication | public function loadContentInfoByRemoteId($remoteId) |
|
| 920 | { |
||
| 921 | $results = $this->internalLoadContentInfo('remote_id', [$remoteId], Connection::PARAM_STR_ARRAY); |
||
| 922 | if (empty($results)) { |
||
| 923 | throw new NotFound('content', "remote_id: $remoteId"); |
||
| 924 | } |
||
| 925 | |||
| 926 | return $results[0]; |
||
| 927 | } |
||
| 928 | |||
| 929 | /** |
||
| 930 | * Loads version info for content identified by $contentId and $versionNo. |
||
| 931 | * Will basically return a hash containing all field values from ezcontentobject_version table plus following keys: |
||
| 932 | * - names => Hash of content object names. Key is the language code, value is the name. |
||
| 933 | * - 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. |
||
| 934 | * - initial_language_code => Language code for initial language in this version. |
||
| 935 | * |
||
| 936 | * @param int $contentId |
||
| 937 | * @param int $versionNo |
||
| 938 | * |
||
| 939 | * @return array |
||
| 940 | */ |
||
| 941 | View Code Duplication | public function loadVersionInfo($contentId, $versionNo) |
|
| 942 | { |
||
| 943 | $query = $this->queryBuilder->createVersionInfoFindQuery(); |
||
| 944 | $query->where( |
||
| 945 | $query->expr->lAnd( |
||
| 946 | $query->expr->eq( |
||
| 947 | $this->dbHandler->quoteColumn('contentobject_id', 'ezcontentobject_version'), |
||
| 948 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
| 949 | ), |
||
| 950 | $query->expr->eq( |
||
| 951 | $this->dbHandler->quoteColumn('version', 'ezcontentobject_version'), |
||
| 952 | $query->bindValue($versionNo, null, \PDO::PARAM_INT) |
||
| 953 | ) |
||
| 954 | ) |
||
| 955 | ); |
||
| 956 | $statement = $query->prepare(); |
||
| 957 | $statement->execute(); |
||
| 958 | |||
| 959 | return $statement->fetchAll(\PDO::FETCH_ASSOC); |
||
| 960 | } |
||
| 961 | |||
| 962 | /** |
||
| 963 | * Returns data for all versions with given status created by the given $userId. |
||
| 964 | * |
||
| 965 | * @param int $userId |
||
| 966 | * @param int $status |
||
| 967 | * |
||
| 968 | * @return string[][] |
||
| 969 | */ |
||
| 970 | public function listVersionsForUser($userId, $status = VersionInfo::STATUS_DRAFT) |
||
| 971 | { |
||
| 972 | $query = $this->queryBuilder->createVersionInfoFindQuery(); |
||
| 973 | $query->where( |
||
| 974 | $query->expr->lAnd( |
||
| 975 | $query->expr->eq( |
||
| 976 | $this->dbHandler->quoteColumn('status', 'ezcontentobject_version'), |
||
| 977 | $query->bindValue($status, null, \PDO::PARAM_INT) |
||
| 978 | ), |
||
| 979 | $query->expr->eq( |
||
| 980 | $this->dbHandler->quoteColumn('creator_id', 'ezcontentobject_version'), |
||
| 981 | $query->bindValue($userId, null, \PDO::PARAM_INT) |
||
| 982 | ) |
||
| 983 | ) |
||
| 984 | ); |
||
| 985 | |||
| 986 | return $this->listVersionsHelper($query); |
||
| 987 | } |
||
| 988 | |||
| 989 | /** |
||
| 990 | * Returns all version data for the given $contentId, optionally filtered by status. |
||
| 991 | * |
||
| 992 | * Result is returned with oldest version first (using version id as it has index and is auto increment). |
||
| 993 | * |
||
| 994 | * @param mixed $contentId |
||
| 995 | * @param mixed|null $status Optional argument to filter versions by status, like {@see VersionInfo::STATUS_ARCHIVED}. |
||
| 996 | * @param int $limit Limit for items returned, -1 means none. |
||
| 997 | * |
||
| 998 | * @return string[][] |
||
| 999 | */ |
||
| 1000 | public function listVersions($contentId, $status = null, $limit = -1) |
||
| 1001 | { |
||
| 1002 | $query = $this->queryBuilder->createVersionInfoFindQuery(); |
||
| 1003 | |||
| 1004 | $filter = $query->expr->eq( |
||
| 1005 | $this->dbHandler->quoteColumn('contentobject_id', 'ezcontentobject_version'), |
||
| 1006 | $query->bindValue($contentId, null, \PDO::PARAM_INT) |
||
| 1007 | ); |
||
| 1008 | |||
| 1009 | if ($status !== null) { |
||
| 1010 | $filter = $query->expr->lAnd( |
||
| 1011 | $filter, |
||
| 1012 | $query->expr->eq( |
||
| 1013 | $this->dbHandler->quoteColumn('status', 'ezcontentobject_version'), |
||
| 1014 | $query->bindValue($status, null, \PDO::PARAM_INT) |
||
| 1015 | ) |
||
| 1016 | ); |
||
| 1017 | } |
||
| 1018 | |||
| 1019 | $query->where($filter); |
||
| 1020 | |||
| 1021 | if ($limit > 0) { |
||
| 1022 | $query->limit($limit); |
||
| 1023 | } |
||
| 1024 | |||
| 1025 | return $this->listVersionsHelper($query); |
||
| 1026 | } |
||
| 1027 | |||
| 1028 | /** |
||
| 1029 | * Helper for {@see listVersions()} and {@see listVersionsForUser()} that filters duplicates |
||
| 1030 | * that are the result of the cartesian product performed by createVersionInfoFindQuery(). |
||
| 1031 | * |
||
| 1032 | * @param \eZ\Publish\Core\Persistence\Database\SelectQuery $query |
||
| 1033 | * |
||
| 1034 | * @return string[][] |
||
| 1035 | */ |
||
| 1036 | private function listVersionsHelper(SelectQuery $query) |
||
| 1058 | |||
| 1059 | /** |
||
| 1060 | * Returns all version numbers for the given $contentId. |
||
| 1061 | * |
||
| 1062 | * @param mixed $contentId |
||
| 1063 | * |
||
| 1064 | * @return int[] |
||
| 1065 | */ |
||
| 1066 | public function listVersionNumbers($contentId) |
||
| 1085 | |||
| 1086 | /** |
||
| 1087 | * Returns last version number for content identified by $contentId. |
||
| 1088 | * |
||
| 1089 | * @param int $contentId |
||
| 1090 | * |
||
| 1091 | * @return int |
||
| 1092 | */ |
||
| 1093 | public function getLastVersionNumber($contentId) |
||
| 1112 | |||
| 1113 | /** |
||
| 1114 | * Returns all IDs for locations that refer to $contentId. |
||
| 1115 | * |
||
| 1116 | * @param int $contentId |
||
| 1117 | * |
||
| 1118 | * @return int[] |
||
| 1119 | */ |
||
| 1120 | public function getAllLocationIds($contentId) |
||
| 1139 | |||
| 1140 | /** |
||
| 1141 | * Returns all field IDs of $contentId grouped by their type. |
||
| 1142 | * If $versionNo is set only field IDs for that version are returned. |
||
| 1143 | * |
||
| 1144 | * @param int $contentId |
||
| 1145 | * @param int|null $versionNo |
||
| 1146 | * |
||
| 1147 | * @return int[][] |
||
| 1148 | */ |
||
| 1149 | public function getFieldIdsByType($contentId, $versionNo = null) |
||
| 1186 | |||
| 1187 | /** |
||
| 1188 | * Deletes relations to and from $contentId. |
||
| 1189 | * If $versionNo is set only relations for that version are deleted. |
||
| 1190 | * |
||
| 1191 | * @param int $contentId |
||
| 1192 | * @param int|null $versionNo |
||
| 1193 | */ |
||
| 1194 | public function deleteRelations($contentId, $versionNo = null) |
||
| 1231 | |||
| 1232 | /** |
||
| 1233 | * Removes relations to Content with $contentId from Relation and RelationList field type fields. |
||
| 1234 | * |
||
| 1235 | * @param int $contentId |
||
| 1236 | */ |
||
| 1237 | public function removeReverseFieldRelations($contentId) |
||
| 1287 | |||
| 1288 | /** |
||
| 1289 | * Updates field value of RelationList field type identified by given $row data, |
||
| 1290 | * removing relations toward given $contentId. |
||
| 1291 | * |
||
| 1292 | * @param int $contentId |
||
| 1293 | * @param array $row |
||
| 1294 | */ |
||
| 1295 | protected function removeRelationFromRelationListField($contentId, array $row) |
||
| 1330 | |||
| 1331 | /** |
||
| 1332 | * Updates field value of Relation field type identified by given $row data, |
||
| 1333 | * removing relation data. |
||
| 1334 | * |
||
| 1335 | * @param array $row |
||
| 1336 | */ |
||
| 1337 | protected function removeRelationFromRelationField(array $row) |
||
| 1359 | |||
| 1360 | /** |
||
| 1361 | * Deletes the field with the given $fieldId. |
||
| 1362 | * |
||
| 1363 | * @param int $fieldId |
||
| 1364 | */ |
||
| 1365 | public function deleteField($fieldId) |
||
| 1379 | |||
| 1380 | /** |
||
| 1381 | * Deletes all fields of $contentId in all versions. |
||
| 1382 | * If $versionNo is set only fields for that version are deleted. |
||
| 1383 | * |
||
| 1384 | * @param int $contentId |
||
| 1385 | * @param int|null $versionNo |
||
| 1386 | */ |
||
| 1387 | public function deleteFields($contentId, $versionNo = null) |
||
| 1409 | |||
| 1410 | /** |
||
| 1411 | * Deletes all versions of $contentId. |
||
| 1412 | * If $versionNo is set only that version is deleted. |
||
| 1413 | * |
||
| 1414 | * @param int $contentId |
||
| 1415 | * @param int|null $versionNo |
||
| 1416 | */ |
||
| 1417 | public function deleteVersions($contentId, $versionNo = null) |
||
| 1439 | |||
| 1440 | /** |
||
| 1441 | * Deletes all names of $contentId. |
||
| 1442 | * If $versionNo is set only names for that version are deleted. |
||
| 1443 | * |
||
| 1444 | * @param int $contentId |
||
| 1445 | * @param int|null $versionNo |
||
| 1446 | */ |
||
| 1447 | public function deleteNames($contentId, $versionNo = null) |
||
| 1469 | |||
| 1470 | /** |
||
| 1471 | * Sets the name for Content $contentId in version $version to $name in $language. |
||
| 1472 | * |
||
| 1473 | * @param int $contentId |
||
| 1474 | * @param int $version |
||
| 1475 | * @param string $name |
||
| 1476 | * @param string $language |
||
| 1477 | */ |
||
| 1478 | public function setName($contentId, $version, $name, $language) |
||
| 1479 | { |
||
| 1480 | $language = $this->languageHandler->loadByLanguageCode($language); |
||
| 1481 | |||
| 1482 | // Is it an insert or an update ? |
||
| 1483 | $qSelect = $this->dbHandler->createSelectQuery(); |
||
| 1484 | $qSelect |
||
| 1485 | ->select( |
||
| 1486 | $qSelect->alias($qSelect->expr->count('*'), 'count') |
||
| 1487 | ) |
||
| 1488 | ->from($this->dbHandler->quoteTable('ezcontentobject_name')) |
||
| 1489 | ->where( |
||
| 1490 | $qSelect->expr->lAnd( |
||
| 1491 | $qSelect->expr->eq($this->dbHandler->quoteColumn('contentobject_id'), $qSelect->bindValue($contentId)), |
||
| 1492 | $qSelect->expr->eq($this->dbHandler->quoteColumn('content_version'), $qSelect->bindValue($version)), |
||
| 1493 | $qSelect->expr->eq($this->dbHandler->quoteColumn('content_translation'), $qSelect->bindValue($language->languageCode)) |
||
| 1494 | ) |
||
| 1495 | ); |
||
| 1496 | $stmt = $qSelect->prepare(); |
||
| 1497 | $stmt->execute(); |
||
| 1498 | $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
||
| 1499 | |||
| 1500 | $insert = $res[0]['count'] == 0; |
||
| 1501 | if ($insert) { |
||
| 1502 | $q = $this->dbHandler->createInsertQuery(); |
||
| 1503 | $q->insertInto($this->dbHandler->quoteTable('ezcontentobject_name')); |
||
| 1504 | } else { |
||
| 1505 | $q = $this->dbHandler->createUpdateQuery(); |
||
| 1506 | $q->update($this->dbHandler->quoteTable('ezcontentobject_name')) |
||
| 1507 | ->where( |
||
| 1508 | $q->expr->lAnd( |
||
| 1509 | $q->expr->eq($this->dbHandler->quoteColumn('contentobject_id'), $q->bindValue($contentId)), |
||
| 1510 | $q->expr->eq($this->dbHandler->quoteColumn('content_version'), $q->bindValue($version)), |
||
| 1511 | $q->expr->eq($this->dbHandler->quoteColumn('content_translation'), $q->bindValue($language->languageCode)) |
||
| 1512 | ) |
||
| 1513 | ); |
||
| 1514 | } |
||
| 1515 | |||
| 1516 | $q->set( |
||
| 1517 | $this->dbHandler->quoteColumn('contentobject_id'), |
||
| 1518 | $q->bindValue($contentId, null, \PDO::PARAM_INT) |
||
| 1519 | )->set( |
||
| 1520 | $this->dbHandler->quoteColumn('content_version'), |
||
| 1521 | $q->bindValue($version, null, \PDO::PARAM_INT) |
||
| 1522 | )->set( |
||
| 1523 | $this->dbHandler->quoteColumn('language_id'), |
||
| 1524 | '(' . $this->getLanguageQuery()->getQuery() . ')' |
||
| 1525 | )->set( |
||
| 1526 | $this->dbHandler->quoteColumn('content_translation'), |
||
| 1527 | $q->bindValue($language->languageCode) |
||
| 1528 | )->set( |
||
| 1529 | $this->dbHandler->quoteColumn('real_translation'), |
||
| 1530 | $q->bindValue($language->languageCode) |
||
| 1531 | )->set( |
||
| 1532 | $this->dbHandler->quoteColumn('name'), |
||
| 1533 | $q->bindValue($name) |
||
| 1534 | ); |
||
| 1535 | $q->bindValue($language->id, ':languageId', \PDO::PARAM_INT); |
||
| 1536 | $q->bindValue($contentId, ':contentId', \PDO::PARAM_INT); |
||
| 1537 | $q->prepare()->execute(); |
||
| 1538 | } |
||
| 1539 | |||
| 1540 | /** |
||
| 1541 | * Returns a language sub select query for setName. |
||
| 1542 | * |
||
| 1543 | * Return sub select query which gets proper language mask for alwaysAvailable Content. |
||
| 1544 | * |
||
| 1545 | * @return \eZ\Publish\Core\Persistence\Database\SelectQuery |
||
| 1546 | */ |
||
| 1547 | private function getLanguageQuery() |
||
| 1586 | |||
| 1587 | /** |
||
| 1588 | * Deletes the actual content object referred to by $contentId. |
||
| 1589 | * |
||
| 1590 | * @param int $contentId |
||
| 1591 | */ |
||
| 1592 | public function deleteContent($contentId) |
||
| 1605 | |||
| 1606 | /** |
||
| 1607 | * Loads relations from $contentId to published content, optionally only from $contentVersionNo. |
||
| 1608 | * |
||
| 1609 | * $relationType can also be filtered. |
||
| 1610 | * |
||
| 1611 | * @param int $contentId |
||
| 1612 | * @param int $contentVersionNo |
||
| 1613 | * @param int $relationType |
||
| 1614 | * |
||
| 1615 | * @return string[][] array of relation data |
||
| 1616 | */ |
||
| 1617 | public function loadRelations($contentId, $contentVersionNo = null, $relationType = null) |
||
| 1685 | |||
| 1686 | /** |
||
| 1687 | * Loads data that related to $toContentId. |
||
| 1688 | * |
||
| 1689 | * @param int $toContentId |
||
| 1690 | * @param int $relationType |
||
| 1691 | * |
||
| 1692 | * @return mixed[][] Content data, array structured like {@see \eZ\Publish\Core\Persistence\Legacy\Content\Gateway::load()} |
||
| 1693 | */ |
||
| 1694 | public function loadReverseRelations($toContentId, $relationType = null) |
||
| 1743 | |||
| 1744 | /** |
||
| 1745 | * Inserts a new relation database record. |
||
| 1746 | * |
||
| 1747 | * @param \eZ\Publish\SPI\Persistence\Content\Relation\CreateStruct $createStruct |
||
| 1748 | * |
||
| 1749 | * @return int ID the inserted ID |
||
| 1750 | */ |
||
| 1751 | View Code Duplication | public function insertRelation(RelationCreateStruct $createStruct) |
|
| 1782 | |||
| 1783 | /** |
||
| 1784 | * Deletes the relation with the given $relationId. |
||
| 1785 | * |
||
| 1786 | * @param int $relationId |
||
| 1787 | * @param int $type {@see \eZ\Publish\API\Repository\Values\Content\Relation::COMMON, |
||
| 1788 | * \eZ\Publish\API\Repository\Values\Content\Relation::EMBED, |
||
| 1789 | * \eZ\Publish\API\Repository\Values\Content\Relation::LINK, |
||
| 1790 | * \eZ\Publish\API\Repository\Values\Content\Relation::FIELD} |
||
| 1791 | */ |
||
| 1792 | public function deleteRelation($relationId, $type) |
||
| 1854 | |||
| 1855 | /** |
||
| 1856 | * Returns all Content IDs for a given $contentTypeId. |
||
| 1857 | * |
||
| 1858 | * @param int $contentTypeId |
||
| 1859 | * |
||
| 1860 | * @return int[] |
||
| 1861 | */ |
||
| 1862 | public function getContentIdsByContentTypeId($contentTypeId) |
||
| 1880 | |||
| 1881 | /** |
||
| 1882 | * Load name data for set of content id's and corresponding version number. |
||
| 1883 | * |
||
| 1884 | * @param array[] $rows array of hashes with 'id' and 'version' to load names for |
||
| 1885 | * |
||
| 1886 | * @return array |
||
| 1887 | */ |
||
| 1888 | public function loadVersionedNameData($rows) |
||
| 1911 | |||
| 1912 | /** |
||
| 1913 | * Batch method for copying all relation meta data for copied Content object. |
||
| 1914 | * |
||
| 1915 | * {@inheritdoc} |
||
| 1916 | * |
||
| 1917 | * @param int $originalContentId |
||
| 1918 | * @param int $copiedContentId |
||
| 1919 | * @param int|null $versionNo If specified only copy for a given version number, otherwise all. |
||
| 1920 | */ |
||
| 1921 | public function copyRelations($originalContentId, $copiedContentId, $versionNo = null) |
||
| 1941 | |||
| 1942 | /** |
||
| 1943 | * Remove the specified translation from the Content Object Version. |
||
| 1944 | * |
||
| 1945 | * @param int $contentId |
||
| 1946 | * @param string $languageCode language code of the translation |
||
| 1947 | * @throws \Doctrine\DBAL\DBALException |
||
| 1948 | */ |
||
| 1949 | public function removeTranslationFromContent($contentId, $languageCode) |
||
| 1967 | |||
| 1968 | /** |
||
| 1969 | * Delete translation from the ezcontentobject_attribute table. |
||
| 1970 | * |
||
| 1971 | * @param int $contentId |
||
| 1972 | * @param string $languageCode |
||
| 1973 | */ |
||
| 1974 | View Code Duplication | private function deleteTranslationFromContentAttributes($contentId, $languageCode) |
|
| 1991 | |||
| 1992 | /** |
||
| 1993 | * Delete translation from the ezcontentobject_name table. |
||
| 1994 | * |
||
| 1995 | * @param $contentId |
||
| 1996 | * @param $languageCode |
||
| 1997 | */ |
||
| 1998 | View Code Duplication | private function deleteTranslationFromContentNames($contentId, $languageCode) |
|
| 2015 | |||
| 2016 | /** |
||
| 2017 | * Remove language from language_mask of ezcontentobject. |
||
| 2018 | * |
||
| 2019 | * @param int $contentId |
||
| 2020 | * @param int $languageId |
||
| 2021 | * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException |
||
| 2022 | */ |
||
| 2023 | private function deleteTranslationFromContentObject($contentId, $languageId) |
||
| 2052 | |||
| 2053 | /** |
||
| 2054 | * Remove language from language_mask of ezcontentobject_version and update initialLanguageId |
||
| 2055 | * if it matches the removed one. |
||
| 2056 | * |
||
| 2057 | * @param int $contentId |
||
| 2058 | * @param int $languageId |
||
| 2059 | * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException |
||
| 2060 | */ |
||
| 2061 | private function deleteTranslationFromContentVersions($contentId, $languageId) |
||
| 2098 | } |
||
| 2099 |
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.