diff --git a/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_node_doc_d7.yml b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_node_doc_d7.yml new file mode 100644 index 000000000..9ec642cae --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_node_doc_d7.yml @@ -0,0 +1,55 @@ +id: drupalfr_node_doc_d7 +label: 'Nodes Documents (doc type in D7)' +audit: true +migration_group: drupalfr_d7 +migration_tags: + - Drupal 7 + - Content +deriver: Drupal\node\Plugin\migrate\D7NodeDeriver +source: + plugin: d7_node + node_type: doc +process: + # If you are using this file to build a custom migration consider removing + # the nid and vid fields to allow incremental migrations. + # In D7, nodes always have a tnid, but it's zero for untranslated nodes. + # We normalize it to equal the nid in that case. + # @see \Drupal\node\Plugin\migrate\source\d7\Node::prepareRow(). + nid: vid + langcode: + plugin: default_value + source: language + default_value: "und" + title: title + uid: node_uid + status: status + created: created + changed: changed + promote: promote + sticky: sticky + revision_uid: revision_uid + revision_log: log + revision_timestamp: timestamp + type: + plugin: default_value + default_value: doc + body: + plugin: sub_process + source: body + process: + value: value + format: + - + plugin: default_value + default_value: basic_html +destination: + plugin: entity:node + default_bundle: doc +migration_dependencies: + required: + - d7_user + - d7_node_type + - drupalfr_nodetypes_d7 + optional: + - d7_field_instance + - d7_comment_field_instance diff --git a/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_nodetypes_d7.yml b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_nodetypes_d7.yml new file mode 100644 index 000000000..9e03d14a0 --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration.drupalfr_nodetypes_d7.yml @@ -0,0 +1,27 @@ +id: drupalfr_nodetypes_d7 +label: Node type configuration +migration_group: drupalfr_d7 +migration_tags: + - Drupal 7 + - Configuration +source: + plugin: drupalfr_nodetypes_d7 + types: + - doc + constants: + preview: 1 # DRUPAL_OPTIONAL +process: + type: type + name: name + description: description + help: help + title_label: title_label + preview_mode: 'constants/preview' + display_submitted: display_submitted + new_revision: 'options/revision' + create_body: create_body + create_body_label: body_label + 'third_party_settings/menu_ui/available_menus': available_menus + 'third_party_settings/menu_ui/parent': parent +destination: + plugin: entity:node_type diff --git a/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration_group.drupalfr_d7.yml b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration_group.drupalfr_d7.yml new file mode 100644 index 000000000..9b551ca2f --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/config/install/migrate_plus.migration_group.drupalfr_d7.yml @@ -0,0 +1,9 @@ +langcode: fr +status: true +dependencies: { } +id: drupalfr_d7 +label: Migrate content +description: 'A container for any migrations not explicitly assigned to a group.' +source_type: 'Drupal 7' +module: null +shared_configuration: null diff --git a/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.install b/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.install index 24e4f253a..b215f5eeb 100644 --- a/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.install +++ b/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.install @@ -11,8 +11,22 @@ function drupalfr_migrate_d7_uninstall() { /** @var \Drupal\Core\File\FileSystemInterface $file_system */ $file_system = \Drupal::service('file_system'); - $files = $file_system->scanDirectory(drupal_get_path('module', 'drupalfr_migrate_d7') . "/config/install", "/.*\.yml/"); + $files = $file_system->scanDirectory(drupal_get_path('module', 'drupalfr_migrate_d7') . '/config/install', "/.*\.yml/"); foreach ($files as $file) { \Drupal::configFactory()->getEditable($file->name)->delete(); } + + // Uninstall Migration Entities. + $group = \Drupal::entityTypeManager()->getStorage('migration_group')->load('drupalfr_d7'); + if ($group) { + $group->delete(); + } + $entity = \Drupal::entityTypeManager()->getStorage('migration')->load('drupalfr_nodetypes_d7'); + if ($entity) { + $entity->delete(); + } + $entity = \Drupal::entityTypeManager()->getStorage('migration')->load('drupalfr_node_doc_d7'); + if ($entity) { + $entity->delete(); + } } diff --git a/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.routing.yml b/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.routing.yml new file mode 100644 index 000000000..d2c2d5b72 --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/drupalfr_migrate_d7.routing.yml @@ -0,0 +1,7 @@ +drupalfr_migrate_d7.entities_form: + path: '/drupalfr_migrate_d7/form/entities' + defaults: + _form: '\Drupal\drupalfr_migrate_d7\Form\DeleteEntitiesForm' + _title: 'EntitiesForm' + requirements: + _access: 'TRUE' diff --git a/www/modules/custom/drupalfr_migrate_d7/includes/nodes.batch.inc b/www/modules/custom/drupalfr_migrate_d7/includes/nodes.batch.inc new file mode 100644 index 000000000..d3dda2a45 --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/includes/nodes.batch.inc @@ -0,0 +1,32 @@ +getStorage('node'); + + $nodes = $storage_controller->loadMultiple($nids); + $storage_controller->delete($nodes); +} + +/** + * Message at end of batch. + */ +function deleteNodeFromNid($nid) { + $storage_controller = \Drupal::service('entity_type.manager')->getStorage('node'); + $node = $storage_controller->load($nid); + $storage_controller->delete([$node]); +} + +/** + * Message at end of batch. + */ +function finishBatch($nids): void { + \Drupal::service('messenger')->addMessage(sprintf('%s nodes deleted.', count($nids))); +} diff --git a/www/modules/custom/drupalfr_migrate_d7/src/Form/DeleteEntitiesForm.php b/www/modules/custom/drupalfr_migrate_d7/src/Form/DeleteEntitiesForm.php new file mode 100644 index 000000000..0f36382fa --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/src/Form/DeleteEntitiesForm.php @@ -0,0 +1,151 @@ +entityTypeManager = $container->get('entity_type.manager'); + $instance->messenger = $container->get('messenger'); + $instance->database = $container->get('database'); + + return $instance; + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'entities_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $options = $this->getNodesTypes(); + if (empty($options)) { + return [ + '#type' => 'markup', + '#markup' => $this->t('No entities existing.'), + ]; + } + + $form['deletable_nodes'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Nodes types to delete'), + '#description' => $this->t('Choose nodes types and contents to delete'), + '#options' => $options, + '#required' => TRUE, + '#weight' => '0', + ]; + + $form['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Submit'), + ]; + $this->getNodesTypes(); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + // Display result. + $selection = $form_state->getValue('deletable_nodes'); + $selections = []; + foreach ($selection as $sel) { + if (0 !== $sel) { + $selections[] = $sel; + } + } + $this->deleteNodesByTypes($selections); + } + + /** + * Get Nodes Types. + */ + private function getNodesTypes() { + $query = $this->entityTypeManager->getStorage('node')->getAggregateQuery() + ->groupBy('type'); + $result = $query->execute(); + $types = []; + foreach ($result as $res) { + $types[$res['type']] = $res['type']; + } + foreach ($types as $key => $type) { + $res = $this->database->select('node', 'n') + ->fields('n', ['nid']) + ->condition('type', $key) + ->execute() + ->fetchAll(); + $types[$key] = sprintf('%s (%s nodes)', $key, count($res)); + } + return $types; + } + + /** + * Delete Nodes by types. + */ + private function deleteNodesByTypes($types) { + $res = $this->database->select('node', 'n') + ->fields('n', ['nid']) + ->condition('type', $types, 'in') + ->execute() + ->fetchAllKeyed(); + $nids = array_keys($res); + + $batch = [ + 'title' => $this->t('Deleting nodes'), + 'init_message' => $this->t('Get nodes to delete.'), + 'progress_message' => $this->t('Completed step @current of @total.'), + 'file' => drupal_get_path('module', 'drupalfr_migrate_d7') . '/includes/nodes.batch.inc', + 'finished' => ['finishBatch', $nids], + ]; + while (count($nids) > 0) { + $numberToExtract = count($nids) >= self::DELETE_NUMBER_MAX ? self::DELETE_NUMBER_MAX : count($nids); + $extract = array_slice($nids, 0, $numberToExtract); + array_splice($nids, 0, $numberToExtract); + $batch['operations'][] = ['delete_nodes_multiple', [$extract]]; + $batch['error_message'] = $this->t('Error deleting nodes.'); + } + batch_set($batch); + } + +} diff --git a/www/modules/custom/drupalfr_migrate_d7/src/Plugin/migrate/source/d7/NodeType.php b/www/modules/custom/drupalfr_migrate_d7/src/Plugin/migrate/source/d7/NodeType.php new file mode 100644 index 000000000..d58b6542c --- /dev/null +++ b/www/modules/custom/drupalfr_migrate_d7/src/Plugin/migrate/source/d7/NodeType.php @@ -0,0 +1,163 @@ +select('node_type', 't')->fields('t'); + if (!empty($this->configuration[self::CONF_TYPE_NAME])) { + $query->condition('t.type', $this->configuration[self::CONF_TYPE_NAME], 'in'); + } + + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'type' => $this->t('Machine name of the node type.'), + 'name' => $this->t('Human name of the node type.'), + 'description' => $this->t('Description of the node type.'), + 'help' => $this->t('Help text for the node type.'), + 'title_label' => $this->t('Title label.'), + 'disabled' => $this->t('Flag indicating the node type is enable'), + 'base' => $this->t('base node.'), + 'custom' => $this->t('Flag.'), + 'modified' => $this->t('Flag.'), + 'locked' => $this->t('Flag.'), + 'orig_type' => $this->t('The original type.'), + 'teaser_length' => $this->t('Teaser length'), + ]; + if ($this->moduleExists('comment')) { + $fields += $this->getCommentFields(); + } + + return $fields; + } + + /** + * Returns the fields containing comment settings for each node type. + * + * @return string[] + * An associative array of field descriptions, keyed by field + */ + protected function getCommentFields() { + return [ + 'comment' => $this->t('Default comment setting'), + 'comment_default_mode' => $this->t('Default display mode'), + 'comment_default_per_page' => $this->t('Default comments per page'), + 'comment_anonymous' => $this->t('Anonymous commenting'), + 'comment_subject_field' => $this->t('Comment subject field'), + 'comment_preview' => $this->t('Preview comment'), + 'comment_form_location' => $this->t('Location of comment submission form'), + ]; + } + + /** + * {@inheritdoc} + */ + protected function initializeIterator() { + $this->teaserLength = $this->variableGet('teaser_length', 600); + $this->nodePreview = $this->variableGet('node_preview', 0); + + return parent::initializeIterator(); + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $row->setSourceProperty('teaser_length', $this->teaserLength); + $row->setSourceProperty('node_preview', $this->nodePreview); + + $type = $row->getSourceProperty('type'); + $source_options = $this->variableGet('node_options_' . $type, [ + 'promote', + 'sticky', + ]); + $options = []; + foreach (['promote', 'sticky', 'status', 'revision'] as $item) { + $options[$item] = in_array($item, $source_options); + } + $row->setSourceProperty('options', $options); + + // Don't create a body field until we prove that this node type has one. + $row->setSourceProperty('create_body', FALSE); + + if ($this->moduleExists('field')) { + // Find body field for this node type. + $body = $this->select('field_config_instance', 'fci') + ->fields('fci', ['data']) + ->condition('entity_type', 'node') + ->condition('bundle', $row->getSourceProperty('type')) + ->condition('field_name', 'body') + ->execute() + ->fetchAssoc(); + if ($body) { + $row->setSourceProperty('create_body', TRUE); + $body['data'] = unserialize($body['data']); + $row->setSourceProperty('body_label', $body['data']['label']); + } + } + + $row->setSourceProperty('display_submitted', $this->variableGet('node_submitted_' . $type, TRUE)); + + if ($menu_options = $this->variableGet('menu_options_' . $type, NULL)) { + $row->setSourceProperty('available_menus', $menu_options); + } + if ($parent = $this->variableGet('menu_parent_' . $type, NULL)) { + $row->setSourceProperty('parent', $parent . ':'); + } + + if ($this->moduleExists('comment')) { + foreach (array_keys($this->getCommentFields()) as $field) { + $row->setSourceProperty($field, $this->variableGet($field . '_' . $type, NULL)); + } + } + + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['type']['type'] = 'string'; + + return $ids; + } + +}