From 25a2d0de52758d4a3736b796db2b15109016569e Mon Sep 17 00:00:00 2001 From: "Dennis A. Torres Rodriguez" Date: Tue, 5 Dec 2023 11:36:32 +0000 Subject: [PATCH 1/4] fix: runtime warnings (invalid array offset) --- src/Commands/Vocabulary.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Commands/Vocabulary.php b/src/Commands/Vocabulary.php index fa11e90..f83eff3 100644 --- a/src/Commands/Vocabulary.php +++ b/src/Commands/Vocabulary.php @@ -84,22 +84,21 @@ public function generateVocabularies($options = ['update' => FALSE]) { $vocabularies = $vocab_storage->loadMultiple(); foreach ($vocab_types as $index => $vocab) { $vocab_name = $vocab['vid']; - $vocan_url_alias = $vocab['url_alias_pattern']; - $type = $vocab['type']; - if ($vocabularies[$vocab['vid']]) { - $this->generatePathautoPattern($vocab_name, $vocan_url_alias, $entity); + $vocab_url_alias = $vocab['url_alias_pattern']; + if (!empty($vocabularies[$vocab['vid']])) { + $this->generatePathautoPattern($vocab_name, $vocab_url_alias, $entity); if ($this->updateMode && $data[$index][$this->implementationFlagColumn] === $this->updateFlag) { $this->updateEntityType($vocabularies[$vocab['vid']], $vocab); - $this->io()->success("Vocabulary $vocab_name updated."); + $this->io()->success("Vocabulary {$vocab_name} updated."); continue; } - $this->io()->warning("Vocabulary $vocab_name Already exists. Skipping creation..."); + $this->io()->warning("Vocabulary {$vocab_name} Already exists. Skipping creation..."); continue; } $status = $vocab_storage->create($vocab)->save(); if ($status === SAVED_NEW) { - $this->io()->success("Vocabulary $type is successfully created..."); - $this->generatePathautoPattern($vocab_name, $vocan_url_alias, $entity); + $this->io()->success("Vocabulary {$vocab_name} is successfully created..."); + $this->generatePathautoPattern($vocab_name, $vocab_url_alias, $entity); } } From 089fa377d89cac61826296919507d58166fd9e31 Mon Sep 17 00:00:00 2001 From: "Dennis A. Torres Rodriguez" Date: Tue, 5 Dec 2023 11:46:46 +0000 Subject: [PATCH 2/4] fix: invalid array offset in menu --- src/Commands/Menu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/Menu.php b/src/Commands/Menu.php index 4968200..5b88eda 100644 --- a/src/Commands/Menu.php +++ b/src/Commands/Menu.php @@ -70,7 +70,7 @@ public function generateMenus($options = ['update' => FALSE]) { $menus = $menu_storage->loadMultiple(); foreach ($menus_data as $index => $menu) { $menu_name = $menu['label']; - if ($menus[$menu['id']]) { + if (!empty($menus[$menu['id']])) { if ($this->updateMode && $data[$index][$this->implementationFlagColumn] === $this->updateFlag) { $this->updateEntityType($menus[$menu['id']], $menu); $this->io()->success("Menu $menu_name updated."); From 5da0769bd4678a8c80e8d30bd9dc3b24e63dbce2 Mon Sep 17 00:00:00 2001 From: "Dennis A. Torres Rodriguez" Date: Tue, 19 Dec 2023 14:44:56 +0000 Subject: [PATCH 3/4] feat: allow URL pattern to be update or skipped Fixes: #1, #2 --- src/BaseEntityGenerate.php | 167 ++++++++++++++++++++++++++---------- src/Commands/Vocabulary.php | 2 +- 2 files changed, 122 insertions(+), 47 deletions(-) diff --git a/src/BaseEntityGenerate.php b/src/BaseEntityGenerate.php index bf19563..ea69aad 100644 --- a/src/BaseEntityGenerate.php +++ b/src/BaseEntityGenerate.php @@ -2,9 +2,13 @@ namespace Drupal\dst_entity_generate; +use BadMethodCallException; +use Drupal; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\pathauto\PathautoPatternInterface; use Drush\Commands\DrushCommands; +use Exception; /** * Base class for all entity generate commands. @@ -13,6 +17,8 @@ abstract class BaseEntityGenerate extends DrushCommands { use StringTranslationTrait; + protected const SKIP_VALUE = '-'; + /** * Machine name of entity which is going to import. * @@ -70,7 +76,7 @@ abstract class BaseEntityGenerate extends DrushCommands { * @throws \Exception */ public function validateGoogleSheetCreds() { - $keyValueStorage = \Drupal::service('keyvalue'); + $keyValueStorage = Drupal::service('keyvalue'); $googleSheetStorage = $keyValueStorage->get('dst_google_sheet_storage'); @@ -78,7 +84,7 @@ public function validateGoogleSheetCreds() { foreach ($requiredConfigs as $config) { if (empty($googleSheetStorage->get($config))) { - throw new \Exception("Please configure $config in google sheet credentials configurations."); + throw new Exception("Please configure $config in google sheet credentials configurations."); } } } @@ -91,7 +97,7 @@ public function validateGoogleSheetCreds() { * @param string $entity * Entity name on which exception occurred. */ - public function displayAndLogException(\Exception $exception, string $entity) { + public function displayAndLogException(Exception $exception, string $entity) { $message = $this->t('Exception occurred while generating @entity: @exception', [ '@exception' => $exception->getMessage(), '@entity' => $entity, @@ -108,7 +114,7 @@ public function displayAndLogException(\Exception $exception, string $entity) { * @throws \Exception */ public function validateEntityForImport() { - $enabled_entities = \Drupal::configFactory()->get('dst_entity_generate.settings')->get('sync_entities'); + $enabled_entities = Drupal::configFactory()->get('dst_entity_generate.settings')->get('sync_entities'); if ($enabled_entities[$this->dstEntityName] !== $this->dstEntityName && $this->dstEntityName !== 'all') { $choice = $this->io()->choice("Entity $this->dstEntityName is not enabled for import. Do you want to enable it?", ['Yes', 'No'], @@ -120,7 +126,7 @@ public function validateEntityForImport() { break; case 1: - throw new \Exception("Entity $this->dstEntityName is not enabled for import. Aborting..."); + throw new Exception("Entity $this->dstEntityName is not enabled for import. Aborting..."); } } } @@ -132,7 +138,7 @@ public function validateEntityForImport() { * Entity name to enable sync. */ public function enableEntitySync(string $entity_name) { - $dst_entity_generate_settings = \Drupal::configFactory()->getEditable('dst_entity_generate.settings'); + $dst_entity_generate_settings = Drupal::configFactory()->getEditable('dst_entity_generate.settings'); $sync_entities = $dst_entity_generate_settings->get('sync_entities'); $sync_entities[$entity_name] = $entity_name; $dst_entity_generate_settings->set('sync_entities', $sync_entities)->save(); @@ -143,14 +149,14 @@ public function enableEntitySync(string $entity_name) { * * @hook validate * - * @throws \Exception + * @throws Exception */ public function validateModulesStatus() { if (empty($this->dependentModules)) { return; } - $moduleHandler = \Drupal::moduleHandler(); + $moduleHandler = Drupal::moduleHandler(); $disabledModules = []; foreach ($this->dependentModules as $module) { if (!$moduleHandler->moduleExists($module)) { @@ -160,7 +166,7 @@ public function validateModulesStatus() { if (!empty($disabledModules)) { $disabledModules = \implode(',', $disabledModules); - throw new \Exception("Please enable $disabledModules to continue with this operation. Aborting..."); + throw new Exception("Please enable $disabledModules to continue with this operation. Aborting..."); } } @@ -177,13 +183,13 @@ public function validateModulesStatus() { */ protected function getDataFromSheet(string $sheet, $filter = TRUE) { $cache_key = 'dst_sheet_data.' . \strtolower($sheet); - $cache_api = \Drupal::cache(); + $cache_api = Drupal::cache(); if (!empty($cache_api->get($cache_key))) { $data = $cache_api->get($cache_key)->data; } else { - $google_sheet_api = \Drupal::service('dst_entity_generate.google_sheet_api'); + $google_sheet_api = Drupal::service('dst_entity_generate.google_sheet_api'); $data = $google_sheet_api->getData($sheet); // Store cached data for 6 hours. $cache_api->set($cache_key, $data, microtime(TRUE) + 21600); @@ -200,7 +206,7 @@ protected function getDataFromSheet(string $sheet, $filter = TRUE) { * @param string $key * Key of the DST sheet to filter the data. * - * @return array|null + * @return array * Filtered data or empty. */ protected function filterEntityTypeSpecificData(array $data, string $key = 'type') { @@ -231,15 +237,15 @@ protected function filterEntityTypeSpecificData(array $data, string $key = 'type * @param array $data * Data fetched from google sheet. * - * @return array|null + * @return array * Approved data. */ private function filterApprovedData(array $data) { if (empty($data)) { - return; + return []; } - $config = \Drupal::config('dst_entity_generate.settings'); + $config = Drupal::config('dst_entity_generate.settings'); $this->implementationFlagColumn = $config->get('column_name'); $column_value = $config->get('column_value'); $this->updateFlag = $config->get('update_flag'); @@ -280,43 +286,41 @@ private function converToMachineName($name) { * Helper function to generate pathauto pattern. */ public function generatePathautoPattern($bundle, $alias, $entity) { - $patternStatus = FALSE; - $moduleHandler = \Drupal::moduleHandler(); - if (!$moduleHandler->moduleExists('pathauto')) { - $this->io()->warning($this->t('Please install pathauto module.')); - return FALSE; - } - if (isset($alias)) { - $patternStatus = TRUE; + try { + $moduleHandler = Drupal::moduleHandler(); + if (!$moduleHandler->moduleExists('pathauto')) { + throw new BadMethodCallException('Pathauto module is not enabled.'); + } + + if (empty($alias) || $alias === self::SKIP_VALUE) { + $this->io()->warning($this->t('No alias set for @bundle, skipping.', ['@bundle' => $bundle])); + return; + } + $pattern_id = $bundle . '_pattern'; $pattern = $this->entityTypeManager->getStorage('pathauto_pattern')->load($pattern_id); - if ($pattern) { - $this->io()->warning($this->t('Alias for @bundle is already present, skipping.', ['@bundle' => $bundle])); - return FALSE; + + if (!$pattern) { + $this->createPathautoPattern($pattern_id, $bundle, $entity, $alias); + + return; } - if ($patternStatus) { - $pattern = $this->entityTypeManager->getStorage('pathauto_pattern')->create([ - 'id' => $pattern_id, - 'label' => $bundle . ' pattern', - 'type' => 'canonical_entities:' . $entity, - 'pattern' => $alias, - 'weight' => -5, - ]); - - // Add the bundle condition. - $pattern->addSelectionCondition([ - 'id' => 'entity_bundle:' . $entity, - 'bundles' => [$bundle => $bundle], - 'negate' => FALSE, - ]); - - $pattern->save(); - $this->io()->success($this->t('Alias for @bundle is created.', ['@bundle' => $bundle])); + if ($pattern->get('pattern') === $alias) { + $this->io()->warning($this->t('Alias for @bundle already set to @alias, skipping.', [ + '@bundle' => $bundle, + '@alias' => $alias, + ])); + return; } + + $this->updatePathautoPattern($pattern, $alias, $bundle); } - else { - $this->io()->warning($this->t('Alias for @bundle is not available, skipping.', ['@bundle' => $bundle])); + catch (\Throwable $e) { + $this->io()->error($this->t('Exception occurred while generating pathauto pattern for @bundle: @exception', [ + '@exception' => str_replace(['"', "'"], '', $e->getMessage()), + '@bundle' => $bundle, + ])); } } @@ -394,4 +398,75 @@ public function validateMachineName(string $machine_name, int $length = 32, stri return $result; } + /** + * Create new pathauto pattern. + * + * @param string $pattern_id + * The pattern id. + * @param string $bundle + * The bundle name. + * @param string $entity + * The entity type. + * @param string $alias + * The alias pattern. + * + * @return void + */ + private function createPathautoPattern( + string $pattern_id, + string $bundle, + syring $entity, + string $alias + ): void { + $pattern = $this->entityTypeManager->getStorage('pathauto_pattern')->create( + [ + 'id' => $pattern_id, + 'label' => $bundle.' pattern', + 'type' => 'canonical_entities:'.$entity, + 'pattern' => $alias, + 'weight' => -5, + ] + ); + + // Add the bundle condition. + $pattern->addSelectionCondition([ + 'id' => 'entity_bundle:'.$entity, + 'bundles' => [$bundle => $bundle], + 'negate' => FALSE, + ]); + + $pattern->save(); + $this->io()->success( + $this->t('Alias for @bundle is created.', ['@bundle' => $bundle]) + ); + } + + /** + * Update existing pathauto pattern. + * + * @param PathautoPatternInterface $pattern + * The pattern entity. + * @param string $alias + * The alias pattern. + * @param string $bundle + * The bundle name. + * + * @return void + */ + private function updatePathautoPattern( + PathautoPatternInterface $pattern, + string $alias, + string $bundle + ): void { + $pattern->set('pattern', $alias); + $pattern->save(); + $this->io()->warning( + $this->t('Alias for @bundle updated from @previous to @current.', [ + '@bundle' => $bundle, + '@previous' => $pattern->get('pattern'), + '@current' => $alias, + ]) + ); + } + } diff --git a/src/Commands/Vocabulary.php b/src/Commands/Vocabulary.php index f83eff3..81238b5 100644 --- a/src/Commands/Vocabulary.php +++ b/src/Commands/Vocabulary.php @@ -140,7 +140,7 @@ private function getVocabTypeData(array $data) { $vocabs['vid'] = $item['machine_name']; $vocabs['description'] = $description; $vocabs['name'] = $item['name']; - $vocabs['url_alias_pattern'] = $item['url_alias_pattern']; + $vocabs['url_alias_pattern'] = $item['url_alias_pattern'] ?? self::SKIP_VALUE; \array_push($vocab_types, $vocabs); } From d2686990980eded870d00b56aeb9e3568cd10d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julia=CC=81n=20Valero?= Date: Mon, 11 Mar 2024 10:45:04 +0100 Subject: [PATCH 4/4] Updated drush supported version in composer file --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d0c003e..46a1fb9 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ ], "require": { "cweagans/composer-patches": "^1.6", - "drush/drush": "^10.3 || ^11", + "drush/drush": "^10.3 || ^12", "google/apiclient": "^2.8" }, "require-dev": {