diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f4d0ef..69157b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.2.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/default-content@1.1.4...@-amazeelabs/default-content@1.2.0) (2022-04-27) + + +### Features + +* a way to update already imported default content ([f9d7a43](https://github.com/AmazeeLabs/silverback-mono/commit/f9d7a4329243de0adee530f8946e525f2589c569)) + + + + + ## [1.1.4](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/default-content@1.1.3...@-amazeelabs/default-content@1.1.4) (2022-04-06) diff --git a/composer.json b/composer.json index 6db3f10..509fe2b 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Helpers for managing the Drupal's default content.", "type": "package", "license": "GPL-2.0-or-later", - "version": "1.1.4", + "version": "1.2.0", "require": { "amazeelabs/proxy-default-content": "^1.1" }, diff --git a/package.json b/package.json index 1baacbb..e774c78 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@-amazeelabs/default-content", "author": "Amazee Labs ", - "version": "1.1.4", + "version": "1.2.0", "scripts": { "version": "sync-composer-version" }, @@ -14,5 +14,5 @@ "repository": "git@github.com:AmazeeLabs/default-content.git", "branch": "main" }, - "gitHead": "bf77c2e91aca0a22e68e3e6fb890e728e7276a94" + "gitHead": "499f53863135ee9e8e4efc571997ca033267197f" } diff --git a/src/AmazeeLabs/DefaultContent/Base.php b/src/AmazeeLabs/DefaultContent/Base.php new file mode 100644 index 0000000..e8f75b2 --- /dev/null +++ b/src/AmazeeLabs/DefaultContent/Base.php @@ -0,0 +1,17 @@ +getPath($module) . + DIRECTORY_SEPARATOR . + 'content'; + } + +} diff --git a/src/AmazeeLabs/DefaultContent/Export.php b/src/AmazeeLabs/DefaultContent/Export.php index 6447b6e..eb690b6 100644 --- a/src/AmazeeLabs/DefaultContent/Export.php +++ b/src/AmazeeLabs/DefaultContent/Export.php @@ -4,16 +4,10 @@ use Drupal\Core\Entity\ContentEntityType; -abstract class Export { +abstract class Export extends Base { public static function run(string $module, array $excludedContentEntityTypes): void { - /** @var \Drupal\Core\Extension\ModuleExtensionList $extensionList */ - $extensionList = \Drupal::service('extension.list.module'); - $dir = DRUPAL_ROOT . - DIRECTORY_SEPARATOR . - $extensionList->getPath($module) . - DIRECTORY_SEPARATOR . - 'content'; + $dir = self::getContentDir($module); self::rrmdir($dir); /** @var \Drupal\default_content\ExporterInterface $exporter */ $exporter = \Drupal::service('default_content.exporter'); diff --git a/src/AmazeeLabs/DefaultContent/Import.php b/src/AmazeeLabs/DefaultContent/Import.php index 58bef8a..7292ba9 100644 --- a/src/AmazeeLabs/DefaultContent/Import.php +++ b/src/AmazeeLabs/DefaultContent/Import.php @@ -2,7 +2,10 @@ namespace AmazeeLabs\DefaultContent; -abstract class Import { +use Drupal\Component\Utility\DiffArray; +use Drupal\Core\Serialization\Yaml; + +abstract class Import extends Base { public static function run(string $module): void { /** @var \Drupal\default_content\ImporterInterface $importer */ @@ -10,4 +13,96 @@ public static function run(string $module): void { $importer->importContent($module); } + /** + * Same as "run", but also updates the already imported content. + * + * It was introduced to solve the following problem: + * There is too much of the default content, the import takes too long. + * How to solve it: + * - Put the default content into the Drupal install cache + * - Use this method instead of the "run" one + */ + public static function runWithUpdate(string $module): void { + $dir = self::getContentDir($module); + /** @var \Drupal\default_content\ExporterInterface $exporter */ + $exporter = \Drupal::service('default_content.exporter'); + $stats = [ + 'updated' => [], + 'removed' => [], + ]; + + $map = []; + if (file_exists($dir) && is_dir($dir)) { + foreach (scandir($dir) as $dirName) { + if ( + $dirName !== '.' && + $dirName !== '..' && + is_dir($dir . DIRECTORY_SEPARATOR . $dirName) && + !is_link($dir . DIRECTORY_SEPARATOR . $dirName) + ) { + $entityType = $dirName; + foreach (scandir($dir . DIRECTORY_SEPARATOR . $dirName) as $fileName) { + if ( + $dirName !== '.' && + $dirName !== '..' && + is_file($dir . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName) && + !is_link($dir . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName) + ) { + [$uuid, $extension] = explode('.', $fileName); + if ($extension === 'yml') { + $map[$entityType][$uuid] = $dir . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName; + } + } + } + } + } + } + + // Find entities which need an update. + foreach ($map as $entityType => $data) { + /** @var \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository */ + $entityRepository = \Drupal::service('entity.repository'); + foreach ($data as $uuid => $path) { + $entity = $entityRepository->loadEntityByUuid($entityType, $uuid); + if ($entity) { + $imported = $exporter->exportContentWithReferences($entityType, $entity->id()); + $imported = reset($imported); + $imported = reset($imported); + $exported = file_get_contents($path); + if ($imported !== $exported) { + $imported = Yaml::decode($imported); + $exported = Yaml::decode($exported); + $diff = DiffArray::diffAssocRecursive($imported, $exported); + if ($diff) { + // Instead of messing with the entity update, we delete it. + $entity->delete(); + if (!isset($stats['updated'][$entityType])) { + $stats['updated'][$entityType] = 0; + } + $stats['updated'][$entityType]++; + } + } + } + } + + // Delete entities not existing in the exported content. + $uuidKey = \Drupal::entityTypeManager()->getDefinition($entityType)->getKey('uuid') ?: 'uuid'; + $query = \Drupal::entityQuery($entityType)->condition($uuidKey, array_keys($data), 'NOT IN'); + if ($entityType === 'user') { + $query->condition('uid', [0, 1], 'NOT IN'); + } + $ids = $query->execute(); + if ($ids) { + $storage = \Drupal::entityTypeManager()->getStorage($entityType); + $storage->delete($storage->loadMultiple($ids)); + $stats['removed'][$entityType] = count($ids); + } + } + + echo "Default content update stats:\n"; + var_dump($stats); + + self::run($module); + } + }