Created
January 24, 2025 01:28
-
-
Save acbramley/53578b18b27466f1b508aedb12907b5e to your computer and use it in GitHub Desktop.
Third party settings legacyAdditionalModuleKey fix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
/** | |
* @file | |
* Post update hooks. | |
*/ | |
use Drupal\my_profile\MyProfileUpdateUtils; | |
use Drupal\Core\Entity\Query\QueryInterface; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; | |
use Drupal\node\Entity\Node; | |
/** | |
* Removes legacyAdditionalModuleKey from LB sections. | |
*/ | |
function my_profile_profile_post_update_remove_legacy_key(array &$sandbox): TranslatableMarkup { | |
$process = static function (Node $node): void { | |
$uuid = \Drupal::service('uuid'); | |
$resave_node = FALSE; | |
$layout = $node->get(OverridesSectionStorage::FIELD_NAME); | |
/** @var \Drupal\layout_builder\Section[] $sections */ | |
$sections = $layout->getSections(); | |
foreach ($sections as $section) { | |
// Get all components for the current section. | |
$components = $section->getComponents(); | |
foreach ($components as $component) { | |
// Get all variables of the current component. | |
$object_vars = get_object_vars($component); | |
// Validate: If there are no variables, then there certainly will not | |
// be any legacyAdditionalModuleKey variable. | |
if (empty($object_vars)) { | |
continue; | |
} | |
// We cannot simply use isset() because that does not work with binary | |
// strings like $object_vars["\x00*\x00legacyAdditionalModuleKey"]. | |
// Instead, convert to json string and see if that contains | |
// legacyAdditionalModuleKey. | |
$json = json_encode($object_vars); | |
// Validate. | |
if (!str_contains($json, '\u0000*\u0000legacyAdditionalModuleKey')) { | |
continue; | |
} | |
// If we are here, the $component has a legacyAdditionalModuleKey | |
// variable. To fix it, we convert the object to array and then create | |
// the object again from that array. | |
// This gets rid of the legacyAdditionalModuleKey. | |
$component_array = $component->toArray(); | |
$component_array['uuid'] = $uuid->generate(); | |
$new_component = $component->fromArray($component_array); | |
$section->insertAfterComponent($component->getUuid(), $new_component); | |
$section->removeComponent($component->getUuid()); | |
$resave_node = TRUE; | |
} | |
if ($resave_node) { | |
$node->setSyncing(TRUE)->save(); | |
} | |
} | |
}; | |
return MyProfileUpdateUtils::entityMigration( | |
entityTypeClass: Node::class, | |
sandbox: $sandbox, | |
process: $process, | |
query: static fn (QueryInterface $query) => $query | |
->condition('layout_builder__layout.section', '%legacyAdditionalModuleKey%', 'LIKE'), | |
revisions: TRUE, | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Drupal\my_profile; | |
use Drupal\Core\Entity\RevisionableStorageInterface; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
/** | |
* Utility functions for post update hooks. | |
*/ | |
final class MyProfileUpdateUtils { | |
/** | |
* Helper function to run entity migrations. | |
* | |
* @param class-string<T> $entityTypeClass | |
* The entity type class. The entity type's ID must be an auto-incrementing | |
* positive-only integer. | |
* @param array $sandbox | |
* The postupdate sandbox. | |
* @param callable $process | |
* A callable to apply for each entity. | |
* @param callable|null $query | |
* A callable to modify the processed entities. This must not change between | |
* iterations. Leave NULL if processing all entities. | |
* @param int $iterationSize | |
* Number of entities to process per batch. | |
* @param bool $revisions | |
* Whether to update entity revisions. | |
* | |
* @phpstan-param callable(T $entity): void $process | |
* @phpstan-param null|callable(\Drupal\Core\Entity\Query\QueryInterface $query): (void|\Drupal\Core\Entity\Query\QueryInterface) $query | |
* | |
* @return \Drupal\Core\StringTranslation\TranslatableMarkup | |
* The message for the current iteration. | |
* | |
* @template T of \Drupal\Core\Entity\EntityInterface | |
*/ | |
public static function entityMigration(string $entityTypeClass, array &$sandbox, callable $process, ?callable $query = NULL, int $iterationSize = 50, bool $revisions = FALSE): TranslatableMarkup { | |
// Setup. | |
$entityTypeRepo = \Drupal::service('entity_type.repository'); | |
$storage = \Drupal::entityTypeManager()->getStorage($entityTypeRepo->getEntityTypeFromClass($entityTypeClass)); | |
if (!isset($sandbox['total'])) { | |
$all = $storage->getQuery(); | |
$all->accessCheck(FALSE); | |
if ($query) { | |
$query($all); | |
} | |
if ($revisions) { | |
$all->allRevisions(); | |
} | |
$ids = $all->execute(); | |
$sandbox['ids'] = $revisions ? \array_keys($ids) : $ids; | |
$sandbox['total'] = \count($sandbox['ids']); | |
$sandbox['progress'] = 0; | |
} | |
$ids = \array_splice($sandbox['ids'], 0, $iterationSize); | |
if ($revisions) { | |
\assert($storage instanceof RevisionableStorageInterface); | |
$entities = $storage->loadMultipleRevisions($ids); | |
} | |
else { | |
$entities = $storage->loadMultiple($ids); | |
} | |
foreach ($entities as $entity) { | |
$process($entity); | |
} | |
$storage->resetCache($ids); | |
$sandbox['progress'] += \count($ids); | |
$sandbox['#finished'] = empty($sandbox['total']) ? 1 : ($sandbox['progress'] / $sandbox['total']); | |
return new TranslatableMarkup('Processed @entity_type_id entities (@count/@total): @ids', [ | |
'@ids' => \implode(', ', $ids), | |
'@count' => $sandbox['progress'], | |
'@total' => $sandbox['total'], | |
'@entity_type_id' => $storage->getEntityTypeId(), | |
]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment