Skip to content

Commit

Permalink
8.1.23
Browse files Browse the repository at this point in the history
- Override the SQL id_map plugin for our migration lookup (#52)
- CSV convert to UTF-8 correctly
- Switch form field access to readonly field widget (#51)
  • Loading branch information
pookmish authored Mar 17, 2022
2 parents fca3ab9 + 8c0a30c commit bc39df8
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 29 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Stanford Migrate


8.x-1.23
--------------------------------------------------------------------------------
_Release Date: 2022-03-17_

- Override the SQL id_map plugin for our migration lookup (#52)
- CSV convert to UTF-8 correctly
- Switch form field access to readonly field widget (#51)


8.x-1.22
--------------------------------------------------------------------------------
_Release Date: 2022-02-02_
Expand Down
9 changes: 8 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
"require": {
"drupal/migrate_file": "^2.0",
"drupal/migrate_plus": "^5.0",
"drupal/migrate_source_csv": "^3.4",
"drupal/migrate_tools": "^5.0",
"drupal/readonly_field_widget": "^1.4",
"drupal/ultimate_cron": "^2.0@alpha",
"drupal/migrate_source_csv": "^3.4",
"joshfraser/php-name-parser": "dev-master"
},
"require-dev": {
"drupal/entity_reference_revisions": "^1.9"
},
"extra": {
"patches": {
"drupal/migrate_plus": {
Expand All @@ -29,6 +33,9 @@
}
}
},
"config": {
"sort-packages": true
},
"autoload": {
"psr-4": {
"Drupal\\stanford_migrate\\": "./src"
Expand Down
5 changes: 5 additions & 0 deletions css/stanford_migrate.readonly.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.messages.messages--readonly {
background-color: transparent;
border-color: #ccc;
color: inherit;
}
7 changes: 3 additions & 4 deletions src/Form/StanfordMigrateCsvImportForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ public function save(array $form, FormStateInterface $form_state) {
$state[] = $file_id;
$this->state->set("stanford_migrate.csv.$migration_id", $state);

$link = Link::createFromRoute($this->t('import page'), 'stanford_migrate.list')
->toString();

// Track the file usage on the migration.
$this->fileUsage->add($file, 'stanford_migrate', 'migration', $migration_id);
}
Expand All @@ -288,7 +285,9 @@ protected function fixLineBreaks($csv_path) {
foreach ($reader as $row) {
foreach ($row as &$column) {
$column = str_replace(["\r\n", "\n\r", "\n", "\r"], '<br />', $column);
$column = iconv("ISO-8859-1", "UTF-8", $column);
// Convert Microsoft characters and other obscure characters into
// UTF-8 Characters.
$column = iconv('UTF-8', 'ASCII//TRANSLIT', $column);
}
$data[] = $row;
}
Expand Down
31 changes: 31 additions & 0 deletions src/Plugin/migrate/id_map/StanfordSql.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Drupal\stanford_migrate\Plugin\migrate\id_map;

use Drupal\migrate\Plugin\migrate\id_map\Sql;

/**
* SQL Plugin override to modify the way the methods are used.
*/
class StanfordSql extends Sql {

/**
* {@inheritdoc}
*/
public function getRowByDestination(array $destination_id_values) {
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map');
foreach ($this->destinationIdFields() as $field_name => $destination_id) {
if (!isset($destination_id_values[$field_name])) {
// In the parent class, if the destination id values doesn't include
// every field, we get an empty data. We're overridding it to use
// whatever values & conditions we can.
continue;
}
$query->condition("map.$destination_id", $destination_id_values[$field_name], '=');
}
return count($query->conditions()) > 1 ?
$query->execute()->fetchAssoc() : [];
}

}
5 changes: 3 additions & 2 deletions stanford_migrate.info.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: 'Stanford Migrate'
description: 'Adds more functionality to migrate and migrate plus modules'
type: module
core_version_requirement: ^8.8 || ^9
core_version_requirement: ^8.8 || ^9 || ^10
package: 'Stanford'
version: 8.x-1.22
version: 8.x-1.23
dependencies:
- drupal:migrate
- migrate_plus:migrate_plus
- migrate_tools:migrate_tools
- readonly_field_widget:readonly_field_widget
- ultimate_cron:ultimate_cron
13 changes: 13 additions & 0 deletions stanford_migrate.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

/**
* @file
* stanford_migrate.install
*/

/**
* Install readonly_field_widget module.
*/
function stanford_migrate_update_8001() {
\Drupal::service('module_installer')->install(['readonly_field_widget']);
}
6 changes: 6 additions & 0 deletions stanford_migrate.libraries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
readonly:
css:
component:
css/stanford_migrate.readonly.css: {}
dependencies:
- seven/classy.messages
95 changes: 73 additions & 22 deletions stanford_migrate.module
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
* Contains stanford_migrate.module.
*/

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
Expand Down Expand Up @@ -61,16 +59,20 @@ function stanford_migrate_get_migration(NodeInterface $node) {

$plugin_manager = \Drupal::service('plugin.manager.migration');

// Load only migrations that are enabled.
$migrations = \Drupal::entityTypeManager()
->getStorage('migration')
->loadByProperties(['status' => 1]);

// Loop through the migration entities, build their migration plugins so that
// we can dig into their source mapping data.
/** @var \Drupal\migrate_plus\Entity\MigrationInterface $migration */
foreach (Migration::loadMultiple() as $migration) {
foreach ($migrations as $migration) {

// This migrate entity has methods that allow easy queries on the
// migrate_map tables.
/** @var \Drupal\migrate\Plugin\MigrationInterface $migrate */
$migrate = $plugin_manager->createInstance($migration->id());

// CSV Imported content can be ignored since it's normally a one time thing.
if (!$migrate || $migrate->getSourcePlugin()->getPluginId() == 'csv') {
continue;
Expand All @@ -84,7 +86,8 @@ function stanford_migrate_get_migration(NodeInterface $node) {
// If the migrate id map returns something, that means this node is tied
// to this migration. Set the static variable for later references and
// get out of here.
$row_data = $migrate->getIdMap()->getRowByDestination(['nid' => $node->id()]);
$row_data = $migrate->getIdMap()
->getRowByDestination(['nid' => $node->id()]);
if (!empty($row_data) && $row_data['source_row_status'] != MigrateIdMapInterface::STATUS_IGNORED) {
$node_migration = $migration;
return $migration;
Expand All @@ -95,18 +98,36 @@ function stanford_migrate_get_migration(NodeInterface $node) {
}

/**
* Implements hook_entity_field_access().
* Implements hook_entity_form_display_alter().
*/
function stanford_migrate_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
$route_match = \Drupal::routeMatch();
// When edit an existing node that was imported via migrate module, mark the
// fields that are mapped from migration as forbidden.
if (
$operation == 'edit' &&
$route_match->getRouteName() == 'entity.node.edit_form' &&
$migration = stanford_migrate_get_migration($route_match->getParameter('node'))
) {
$field_name = $field_definition->getName();
function stanford_migrate_entity_form_display_alter(EntityFormDisplayInterface $form_display, array $context) {
// We only care about nodes, but this could be expanded later if more entities
// are imported.
$node = \Drupal::routeMatch()->getParameter('node');
if ($context['entity_type'] != 'node' || !$node) {
return;
}

$migration = stanford_migrate_get_migration($node);
// Check if the current node was imported.
if (!$migration) {
return;
}

// Grab the default display settings for use later.
$default_display = EntityViewDisplay::load("node.{$node->bundle()}.default");

$field_definitions = $form_display->get('fieldDefinitions');
foreach ($form_display->getComponents() as $field_name => $component) {

// Make sure the field component is one of the field definitions.
if (empty($field_definitions[$field_name])) {
continue;
}

// When edit an existing node that was imported via migrate module, mark the
// fields that are mapped from migration as readonly.
$field_definition = $field_definitions[$field_name];
$columns = $field_definition->getFieldStorageDefinition()->getColumns();
$processing = !empty($migration->process[$field_name]);

Expand Down Expand Up @@ -137,13 +158,36 @@ function stanford_migrate_entity_field_access($operation, FieldDefinitionInterfa

if ($processing) {
\Drupal::messenger()
->addWarning(t('Some fields can not be edited since they contain imported & synced data. They are not visible here.'));

return AccessResult::forbidden((string) t('Field is mapped by the importer'));
->addWarning(t('Some fields can not be edited since they contain imported & synced data.'));

// If the default display is configured with some settings, let's use that
// for the best display on the entity form. If it's not configured, the
// readonly_field_widget module will use some default display settings.
if ($display_component = $default_display->getComponent($field_name)) {
$component['settings']['formatter_type'] = $display_component['type'];
$component['settings']['formatter_settings'] = $display_component['settings'];
}
$component['type'] = 'readonly_field_widget';
$form_display->setComponent($field_name, $component);
}
}
}

return AccessResult::neutral();
/**
* Implements hook_preprocess_HOOK().
*/
function stanford_migrate_preprocess_field(&$variables) {
if (
!empty($variables['element']['#parents']) &&
in_array('readonly_field', $variables['element']['#parents'])
) {
// Wrap the readonly form fields with classes so that they can be identified
// more easily to the user.
$variables['attributes']['class'][] = 'messages';
$variables['attributes']['class'][] = 'messages--warning';
$variables['attributes']['class'][] = 'messages--readonly';
$variables['#attached']['library'][] = 'stanford_migrate/readonly';
}
}

/**
Expand Down Expand Up @@ -209,6 +253,13 @@ function stanford_migrate_migration_delete(Migration $entity) {
\Drupal::state()->delete("stanford_migrate.csv.{$entity->id()}");
}

/**
* Implements hook_migrate_id_map_info_alter().
*/
function stanford_migrate_migrate_id_map_info_alter(&$definitions) {
$definitions['sql']['class'] = '\Drupal\stanford_migrate\Plugin\migrate\id_map\StanfordSql';
}

/**
* Implements hook_migrate_source_info_alter().
*/
Expand Down
47 changes: 47 additions & 0 deletions tests/src/Kernel/Plugin/migrate/id_map/StanfordSqlTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Drupal\Tests\stanford_migrate\Kernel\Plugin\migrate\id_map;

use Drupal\Core\Cache\Cache;
use Drupal\migrate\MigrateExecutable;
use Drupal\node\Entity\Node;
use Drupal\stanford_migrate\Plugin\migrate\id_map\StanfordSql;
use Drupal\Tests\stanford_migrate\Kernel\StanfordMigrateKernelTestBase;

/**
* Class StanfordSqlTest.
*
* @group stanford_migrate
* @coversDefaultClass \Drupal\stanford_migrate\Plugin\migrate\id_map\StanfordSql
*/
class StanfordSqlTest extends StanfordMigrateKernelTestBase {

/**
* Ensure the id map returns expected values.
*/
public function testOverride() {
\Drupal::configFactory()
->getEditable('migrate_plus.migration.stanford_migrate')
->set('destination.plugin', 'entity_reference_revisions:node')
->set('source.urls', [dirname(__FILE__, 4) . '/test.xml'])
->save();
Cache::invalidateTags(['migration_plugins']);

$manager = \Drupal::service('plugin.manager.migration');
/** @var \Drupal\migrate\Plugin\Migration $migration */
$migration = $manager->createInstance('stanford_migrate');
$migrate_executable = new MigrateExecutable($migration);
$migrate_executable->import();

$nodes = Node::loadMultiple();
$node = reset($nodes);

$this->assertInstanceOf(StanfordSql::class, $migration->getIdMap());
$this->assertNotEmpty($migration->getIdMap()
->getRowByDestination(['nid' => $node->id()]));
$this->assertNotEmpty($migration->getIdMap()
->getRowByDestination(['nid' => $node->id(), 'vid' => $node->getRevisionId()]));
$this->assertEmpty($migration->getIdMap()->getRowByDestination([]));
}

}
1 change: 1 addition & 0 deletions tests/src/Kernel/StanfordMigrateKernelTestBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ abstract class StanfordMigrateKernelTestBase extends KernelTestBase {
*/
protected static $modules = [
'test_stanford_migrate',
'entity_reference_revisions',
'stanford_migrate',
'migrate_plus',
'migrate',
Expand Down

0 comments on commit bc39df8

Please sign in to comment.