diff --git a/src/services/Assets.php b/src/services/Assets.php index e2f8ec0..e6002f6 100644 --- a/src/services/Assets.php +++ b/src/services/Assets.php @@ -4,10 +4,12 @@ use Craft; use craft\base\FieldInterface; +use craft\db\Query; use craft\db\Table; use craft\fields\Matrix; use craft\helpers\Db; use craft\helpers\ElementHelper; +use craft\helpers\Json; use lsst\cantodamassets\fields\CantoDamAsset; use lsst\cantodamassets\lib\laravel\Collection; use lsst\cantodamassets\models\CantoFieldData; @@ -167,21 +169,66 @@ protected function updateContent(string $value, CantoFieldData $cantoFieldData, { $columnKey = self::CONTENT_COLUMN_KEY_MAPPINGS[$columnKey] ?? null; foreach ($cantoDamAssetFields as $cantoDamAssetField) { + // Find any $queryColumn content column row that match $value, and update them with the data from $cantoFieldData $queryColumn = ElementHelper::fieldColumnFromField($cantoDamAssetField, $columnKey); - $columns = []; - foreach (self::CONTENT_COLUMN_KEY_MAPPINGS as $propertyName => $selectColumnKey) { - $columns[ElementHelper::fieldColumnFromField($cantoDamAssetField, $selectColumnKey)] = $cantoFieldData->$propertyName; - } if ($queryColumn) { + $columns = $this->getColumns($cantoDamAssetField, $cantoFieldData); try { $rows = Db::update($table, $columns, [$queryColumn => $value]); } catch (Exception $e) { Craft::error($e->getMessage(), __METHOD__); } } + // If the column we're updating is the `cantoId`, we need to search the JSON contents of `cantoAssetData` + // in order to update any canto assets contained within the JSON blobs as well + if ($columnKey === 'cantoId') { + $db = Craft::$app->getDb(); + // Get any existing Canto Assets fields that contain the asset ID we're updating + $cantoIdFieldName = ElementHelper::fieldColumnFromField($cantoDamAssetField, self::CONTENT_COLUMN_KEY_MAPPINGS['cantoId']); + $cantoAssetDataFieldName = ElementHelper::fieldColumnFromField($cantoDamAssetField, self::CONTENT_COLUMN_KEY_MAPPINGS['cantoAssetData']); + $jsonSearchNeedle = ['id' => $cantoFieldData->cantoId]; + $jsonSearchSql = ''; + if ($db->getIsMysql()) { + $jsonSearchSql = $this->mySqlJsonContains($cantoAssetDataFieldName, $jsonSearchNeedle); + } + if ($db->getIsPgsql()) { + $jsonSearchSql = $this->pgSqlJsonContains($cantoAssetDataFieldName, $jsonSearchNeedle); + } + $rows = (new Query()) + ->select([$cantoAssetDataFieldName]) + ->from([$table]) + ->where([$cantoIdFieldName => 0, $cantoAssetDataFieldName => $jsonSearchSql]) + ->all(); + } } } + /** + * Return a jsonContains expression properly formatted for MySQL + * + * @param string $targetSql + * @param mixed $value + * @return string + */ + private function mySqlJsonContains(string $targetSql, mixed $value): string + { + $value = Craft::$app->getDb()->quoteValue(Json::encode($value)); + return "JSON_CONTAINS($targetSql, $value)"; + } + + /** + * Return a jsonContains expression properly formatted for Postgres + * + * @param string $targetSql + * @param mixed $value + * @return string + */ + private function pgSqlJsonContains(string $targetSql, mixed $value): string + { + $value = Craft::$app->getDb()->quoteValue(Json::encode($value)); + return "($targetSql @> $value::jsonb)"; + } + /** * Block type fields have the same methods as Matrix * @@ -193,4 +240,21 @@ private function getBlockFields(string $fieldType): array /** @phpstan-ignore-next-line */ return Craft::$app->getFields()->getFieldsByType($fieldType); } + + /** + * Return the $cantoDamAssetField db columns to update with the values from the $cantoFieldData + * + * @param FieldInterface $cantoDamAssetField + * @param CantoFieldData $cantoFieldData + * @return array + */ + private function getColumns(FieldInterface $cantoDamAssetField, CantoFieldData $cantoFieldData): array + { + $columns = []; + foreach (self::CONTENT_COLUMN_KEY_MAPPINGS as $propertyName => $selectColumnKey) { + $columns[ElementHelper::fieldColumnFromField($cantoDamAssetField, $selectColumnKey)] = $cantoFieldData->$propertyName; + } + + return $columns; + } }