association-1.0.0-alpha2/association.install
association.install
<?php /** * @file * Drupal hooks for installation, updating and checking requirements. */ use Drupal\Core\Database\SchemaObjectExistsException; use Drupal\Core\Field\BaseFieldDefinition; /** * Implements hook_install(). */ function association_install() { // Association module hooks should run later than the base entity hooks. module_set_weight('association', 10); } /** * Implements hook_modules_preuninstall(). */ function association_modules_preuninstall($module) { if ($module == 'association') { // This handler doesn't need to run on the association module itself, as the // database tables will be cleared and removed as part of the uninstall. return; } // Ensure that all association linked content belonging to the uninstalled // module has been cleaned up before the entities are removed. $entityAdapterManager = \Drupal::service('plugin.manager.association.entity_adapter'); $staleTypes = []; foreach ($entityAdapterManager->getDefinitions() as $definition) { if (isset($definition['entity_type']) && $definition['provider'] == $module) { $stateTypes[] = $definition['entity_type']; } } if ($staleTypes) { $linkStorage = \Drupal::entityTypeManager() ->getStorage('association_link'); $links = $linkStorage->loadByProperties([ 'entity_type' => $staleTypes, ]); if ($links) { $linkStorage->delete($links); } } } /** * Add association_link table missing indexes. * * Association link table used to use * \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::processBaseTable() * to install table indexes, but this method was removed in Drupal 9.x. If the * module was installed for the first time with Drupal 9.x these indexes will * be missing. * * @see \Drupal\association\Entity\Storage\AssociationLinkStorageSchema::initializeBaseTable() */ function association_update_9101() { /** @var \Drupal\Core\Entity\EntityFieldManagerInterface */ $field_manager = \Drupal::service('entity_field.manager'); $entity_type_manager = \Drupal::entityTypeManager(); /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface */ $entity_storage = $entity_type_manager->getStorage('association_link'); $table_name = $entity_type_manager ->getDefinition('association_link') ->getBaseTable(); /** @var \Drupal\Core\Field\BaseFieldDefinition[] */ $base_fields = $field_manager->getBaseFieldDefinitions('association_link'); $base_fields = [ 'association' => $base_fields['association'], 'entity_type' => $base_fields['entity_type'], 'target' => $base_fields['target'], ]; // Create a partial table spec with the field property schemas of the // table columns to use for the additional indexes. $table_mapping = $entity_storage->getTableMapping($base_fields); $table_spec = []; foreach ($base_fields as $field_def) { $prop = $field_def->getMainPropertyName(); $col = $table_mapping->getFieldColumnName($field_def, $prop); $table_spec['fields'][$col] = $field_def->getSchema()['columns'][$prop]; $table_spec['fields'][$col]['not null'] = TRUE; } try { $db_schema = \Drupal::database()->schema(); $db_schema->addIndex($table_name, 'target_entity', [ 'entity_type', 'target', ], $table_spec); $db_schema->addUniqueKey($table_name, 'association_link_target', [ 'association', 'entity_type', 'target', ]); } catch (SchemaObjectExistsException $e) { // If the indexes already existed, this is okay. This might happen if // module was installed with Drupal 8 before // \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::processBaseTable() // was removed. } } /** * Add a revisionable status base field which is needed for workflows. */ function association_update_9103(&$sandbox = []) { /** @var \Drupal\association_page\Entity\Storage\AssociationPageStorage */ $page_storage = \Drupal::entityTypeManager()->getStorage('association_page'); $query = $page_storage->getQuery() ->accessCheck(FALSE); if (!isset($sandbox['progress'])) { $count_query = clone $query; $sandbox['progress'] = 0; $sandbox['current'] = 0; $sandbox['total'] = $count_query->count()->execute(); $status_def = [ 'type' => 'int', 'size' => 'tiny', 'default' => 1, 'not null' => TRUE, ]; // The EntityDefinitionUpdateManager::installFieldStorageDefinition() // does not properly apply the default value during install and errors for // this "boolean" data patch. $schema = \Drupal::database()->schema(); $schema->addField('association_page_field_data', 'status', $status_def); $schema->addField('association_page_field_revision', 'status', $status_def); } $ids = $query ->condition('id', $sandbox['current'], '>') ->sort('id', 'ASC') ->range(0, 50) ->execute(); if ($ids) { /** @var \Drupal\association_page\Entity\AssociationPage */ foreach ($page_storage->loadMultiple($ids) as $page) { $assoc_status = $page->getAssociation()->isActive(); $page ->set('status', [$assoc_status]) ->save(); $rids = $page_storage->revisionIds($page); /** @var \Drupal\association_page\Entity\AssociationPage */ foreach ($page_storage->loadMultipleRevisions($rids) as $revision) { $revision ->set('status', [$assoc_status]) ->save(); } $sandbox['current'] = $page->id(); ++$sandbox['progress']; } } if ($ids && $sandbox['total'] > 0 && $sandbox['progress'] < $sandbox['total']) { $sandbox['#finished'] = $sandbox['progress'] / $sandbox['total']; } else { $update_manager = \Drupal::entityDefinitionUpdateManager(); $entity_type = $update_manager->getEntityType('association_page'); $update_manager->updateEntityType($entity_type); } } /** * Convert entity manifest behavior configurations to multiple bundles per tag. * * In order to add more flexibility to entity manifest the configuration * structure was updated to allow multiple entity and bundles per tag * definition. Updates configuration to new format. */ function association_update_9104() { /** @var \Drupal\association\Entity\AssociationTypeInterface[] */ $assoc_types = \Drupal::entityTypeManager() ->getStorage('association_type') ->loadMultiple(); foreach ($assoc_types as $type) { $behavior = $type->getBehavior(); // Only update entity manifest behavior plugins. if (!$behavior || $behavior->getPluginId() !== 'entity_manifest') { continue; } $config = $behavior->getConfiguration(); foreach ($config['manifest'] as &$def) { [$entity_type, $bundle] = explode(':', $def['entity_bundle'], 2); $def['entity_types'][$entity_type][$bundle] = $bundle; unset($def['entity_bundle']); } // Update the config changes, and save the association type. $behavior->setConfiguration($config); $type->save(); } } /** * Add a target entity bundle to allow for multiple entity bundles per "tag". */ function association_update_9105(&$sandbox = []) { /** @var \Drupal\association\Entity\Storage\AssociationLinkStorage */ $link_storage = \Drupal::entityTypeManager()->getStorage('association_link'); $query = $link_storage->getQuery()->accessCheck(FALSE); $bundle_field = BaseFieldDefinition::create('string') ->setLabel(t('Target entity bundle')) ->setRequired(FALSE) ->setTranslatable(FALSE); if (!isset($sandbox['progress'])) { $count_query = clone $query; $sandbox['progress'] = 0; $sandbox['current'] = 0; $sandbox['total'] = $count_query->count()->execute(); \Drupal::entityDefinitionUpdateManager() ->installFieldStorageDefinition('bundle', 'association_link', 'association', $bundle_field); } $ids = $query ->condition('id', $sandbox['current'], '>') ->sort('id', 'ASC') ->range(0, 50) ->execute(); if ($ids) { /** @var \Drupal\association\Entity\AssociationLink */ foreach ($link_storage->loadMultiple($ids) as $link) { $assoc = $link->getAssociation(); $behavior = $assoc ? $assoc->getBehavior() : NULL; if ($behavior && $behavior->getPluginId() === 'entity_list') { $link->set('tag', 'entity'); } $link ->set('bundle', $link->target->entity->bundle()) ->save(); $sandbox['current'] = $link->id(); ++$sandbox['progress']; } } if ($ids && $sandbox['total'] > 0 && $sandbox['progress'] < $sandbox['total']) { $sandbox['#finished'] = $sandbox['progress'] / $sandbox['total']; } else { $update_manager = \Drupal::entityDefinitionUpdateManager(); // Now that this value has been populated (failed with "NULL" values), we // can change this db field to required (aka "not null"). $bundle_field->setRequired(TRUE); $update_manager->updateFieldStorageDefinition($bundle_field); $entity_type = $update_manager->getEntityType('association_link'); $update_manager->updateEntityType($entity_type); } } /** * Enable association_page module and update association types. * * Association landing page handling has been updated to be plugin based, and * the association_page entity has been moved to the association_page module. * * The update hook enabled the association_page module to ensure the page * entity is available for any association types that used it, and migrates the * landing page options to the comparable plugin configurations. */ function association_update_9106() { $config_factory = \Drupal::configFactory(); $entity_type_manager = \Drupal::entityTypeManager(); $updateManager = \Drupal::entityDefinitionUpdateManager(); // Install the page settings field. $page_field = BaseFieldDefinition::create('association_plugin_settings') ->setTargetEntityTypeId('association') ->setLabel(t('Landing page settings')) ->setRevisionable(FALSE) ->setTranslatable(FALSE) ->addConstraint('AssociationPluginFieldSettings') ->setDescription(t('Landing page handler settings for this association.')) ->setSettings([ 'type' => 'landing_page', 'label' => t('Landing page'), ]) ->setDisplayConfigurable('view', FALSE) ->setDisplayOptions('form', [ 'type' => 'association_plugin_settings_widget', 'weight' => -1, ]); $updateManager->installFieldStorageDefinition('page', 'association', 'association', $page_field); // Install the association_page module to provide the page entity definitions // that are already installed. Entity can be uninstalled later, but needs to // be here to avoid unexpected error when definitions are missing. \Drupal::service('module_installer')->install(['association_page']); /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $assoc_store */ $assoc_store = $entity_type_manager->getStorage('association'); $table_mapping = $assoc_store->getTableMapping(); $plugin_col = $table_mapping->getFieldColumnName($page_field, 'plugin'); $settings_col = $table_mapping->getFieldColumnName($page_field, 'settings'); /** @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $type_def */ $type_def = $entity_type_manager->getDefinition('association_type'); $storage = $entity_type_manager->getStorage('association_type'); $config_prefix = $type_def->getConfigPrefix(); /** @var \Drupal\association\Entity\AssociationTypeInterface $type */ foreach ($storage->loadMultiple() as $name => $type) { // Load the raw config data, to check for old values and missing config. $config = $config_factory->get($config_prefix . '.' . $name); $data = $config->getRawData(); // Only update data where the landing page plugin configurations are empty. if ($data && empty($data['landingPage'])) { if (!empty($data['hasPage'])) { $plugin_id = 'association_page'; $type->set('landingPage', [ 'id' => 'association_page', 'config' => [ 'new_revision' => (bool) $data['newRevision'] ?? FALSE, ], ]); } else { $plugin_id = 'none'; $type->set('landingPage', [ 'id' => 'none', 'config' => [], ]); } // Update and save the landing page plugin settings. $type->save(); // Update the plugin settings field values. \Drupal::database() ->update($table_mapping->getFieldTableName('page')) ->fields([ $plugin_col => $plugin_id, $settings_col => serialize([]), ]) ->condition('type', $name) ->isNull($settings_col) ->execute(); } } }