diff --git a/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml b/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml index 86e801e..10d1bda 100644 --- a/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml +++ b/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml @@ -50,6 +50,10 @@ migrate.source.variable_multirow: type: string label: 'Variable' +migrate.source.d6_imagecache_presets: + type: migrate_source_sql + label: 'Drupal 6 ImageCache Presets' + migrate_entity_constant: type: mapping mapping: diff --git a/core/modules/migrate_drupal/migration_templates/d6_imagecache_presets.yml b/core/modules/migrate_drupal/migration_templates/d6_imagecache_presets.yml new file mode 100644 index 0000000..91e1201 --- /dev/null +++ b/core/modules/migrate_drupal/migration_templates/d6_imagecache_presets.yml @@ -0,0 +1,24 @@ +id: d6_imagecache_presets +label: Drupal 6 ImageCache Presets +migration_tags: + - Drupal 6 +source: + plugin: d6_imagecache_presets +process: + name: + - + plugin: machine_name + source: presetname + - + plugin: dedupe_entity + entity_type: image_style + field: name + length: 32 + label: presetname + effects: + plugin: d6_imagecache_actions + source: + - @plugin + - data +destination: + plugin: entity:image_style diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/destination/EntityImageStyle.php b/core/modules/migrate_drupal/src/Plugin/migrate/destination/EntityImageStyle.php new file mode 100644 index 0000000..a4924a2 --- /dev/null +++ b/core/modules/migrate_drupal/src/Plugin/migrate/destination/EntityImageStyle.php @@ -0,0 +1,57 @@ +getDestinationProperty('effects')) { + $effects = $row->getDestinationProperty('effects'); + $row->setDestinationProperty('effects', array()); + } + + $style = $this->getEntity($row, $old_destination_id_values); + + // Iterate the effects array so each effect plugin can be initialized. + // Catch any missing plugin exceptions. + foreach ($effects as $effect) { + try { + $style->addImageEffect($effect); + } + catch (PluginNotFoundException $e) { + throw new MigrateException($e->getMessage()); + } + } + + $style->save(); + + return array($style->id()); + } +} diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/ImageCacheActions.php b/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/ImageCacheActions.php new file mode 100644 index 0000000..f651acb --- /dev/null +++ b/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/ImageCacheActions.php @@ -0,0 +1,53 @@ +getSourceProperty('actions') as $action) { + $id = preg_replace('/^imagecache/', 'image', $action['action']); + + if($id === 'image_crop') { + $action['data']['anchor'] = $action['data']['xoffset'] . '-' . $action['data']['yoffset']; + + if(!preg_match('/^[a-z]*\-[a-z]*/', $action['data']['anchor'])) { + throw new MigrateSkipRowException('The Drupal 8 image crop effect does not support numeric values for x and y offsets. Use keywords to set crop effect offsets instead.'); + } + + unset($action['data']['xoffset']); + unset($action['data']['yoffset']); + } + + $effects[] = array( + 'id' => $id, + 'weight' => $action['weight'], + 'data' => $action['data'], + ); + } + + return $effects; + } +} diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/ImageCachePreset.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/ImageCachePreset.php new file mode 100644 index 0000000..a405709 --- /dev/null +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/ImageCachePreset.php @@ -0,0 +1,74 @@ +select('imagecache_preset', 'icp') + ->fields('icp', array( + 'presetid', + 'presetname', + ) + ); + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = array( + 'presetid' => $this->t('Preset ID'), + 'presetname' => $this->t('Preset Name'), + ); + return $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['presetid']['type'] = 'integer'; + return $ids; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $actions = array(); + + $results = $this->select('imagecache_action', 'ica') + ->fields('ica') + ->condition('presetid', $row->getSourceProperty('presetid')) + ->execute(); + + foreach($results as $key => $result) { + $actions[$key] = $result; + $actions[$key]['data'] = unserialize($result['data']); + } + + $row->setSourceProperty('actions', $actions); + return parent::prepareRow($row); + } +} diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php new file mode 100644 index 0000000..194cc93 --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction.php @@ -0,0 +1,105 @@ +createTable("imagecache_action", array( + 'primary key' => array( + 'actionid', + ), + 'fields' => array( + 'actionid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'length' => '10', + 'unsigned' => TRUE, + ), + 'presetid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'length' => '10', + 'default' => '0', + 'unsigned' => TRUE, + ), + 'weight' => array( + 'type' => 'int', + 'not null' => TRUE, + 'length' => '11', + 'default' => '0', + ), + 'module' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + ), + 'action' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + ), + 'data' => array( + 'type' => 'text', + 'not null' => TRUE, + 'length' => 100, + ), + ), + 'mysql_character_set' => 'utf8', + )); + $this->database->insert("imagecache_action")->fields(array( + 'actionid', + 'presetid', + 'weight', + 'module', + 'action', + 'data', + )) + ->values(array( + 'actionid' => '3', + 'presetid' => '1', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_scale_and_crop', + 'data' => 'a:2:{s:5:"width";s:4:"100%";s:6:"height";s:4:"100%";}', + ))->values(array( + 'actionid' => '4', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_crop', + 'data' => 'a:4:{s:5:"width";s:3:"555";s:6:"height";s:4:"5555";s:7:"xoffset";s:6:"center";s:7:"yoffset";s:6:"center";}', + ))->values(array( + 'actionid' => '5', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_resize', + 'data' => 'a:2:{s:5:"width";s:3:"55%";s:6:"height";s:3:"55%";}', + ))->values(array( + 'actionid' => '6', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_rotate', + 'data' => 'a:3:{s:7:"degrees";s:2:"55";s:6:"random";i:0;s:7:"bgcolor";s:0:"";}', + ))->execute(); + } + +} +#90267fd3a92bd722208f016a23ab5f97 diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction_fail.php b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction_fail.php new file mode 100644 index 0000000..ea12418 --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecacheAction_fail.php @@ -0,0 +1,112 @@ +createTable("imagecache_action", array( + 'primary key' => array( + 'actionid', + ), + 'fields' => array( + 'actionid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'length' => '10', + 'unsigned' => TRUE, + ), + 'presetid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'length' => '10', + 'default' => '0', + 'unsigned' => TRUE, + ), + 'weight' => array( + 'type' => 'int', + 'not null' => TRUE, + 'length' => '11', + 'default' => '0', + ), + 'module' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + ), + 'action' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + ), + 'data' => array( + 'type' => 'text', + 'not null' => TRUE, + 'length' => 100, + ), + ), + 'mysql_character_set' => 'utf8', + )); + $this->database->insert("imagecache_action")->fields(array( + 'actionid', + 'presetid', + 'weight', + 'module', + 'action', + 'data', + )) + ->values(array( + 'actionid' => '2', + 'presetid' => '1', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_deprecated_scale', + 'data' => 'a:3:{s:3:"fit";s:7:"outside";s:5:"width";s:3:"200";s:6:"height";s:3:"200";}', + ))->values(array( + 'actionid' => '3', + 'presetid' => '1', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_scale_and_crop', + 'data' => 'a:2:{s:5:"width";s:4:"100%";s:6:"height";s:4:"100%";}', + ))->values(array( + 'actionid' => '4', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_crop', + 'data' => 'a:4:{s:5:"width";s:3:"555";s:6:"height";s:4:"5555";s:7:"xoffset";s:6:"center";s:7:"yoffset";s:6:"center";}', + ))->values(array( + 'actionid' => '5', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_resize', + 'data' => 'a:2:{s:5:"width";s:3:"55%";s:6:"height";s:3:"55%";}', + ))->values(array( + 'actionid' => '6', + 'presetid' => '2', + 'weight' => '0', + 'module' => 'imagecache', + 'action' => 'imagecache_rotate', + 'data' => 'a:3:{s:7:"degrees";s:2:"55";s:6:"random";i:0;s:7:"bgcolor";s:0:"";}', + ))->execute(); + } + +} +#2adcbd67f3f7113bca46e1804ab1d99a diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php new file mode 100644 index 0000000..154662c --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/Table/d6/ImagecachePreset.php @@ -0,0 +1,56 @@ +createTable("imagecache_preset", array( + 'primary key' => array( + 'presetid', + ), + 'fields' => array( + 'presetid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'length' => '10', + 'unsigned' => TRUE, + ), + 'presetname' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + ), + ), + 'mysql_character_set' => 'utf8', + )); + $this->database->insert("imagecache_preset")->fields(array( + 'presetid', + 'presetname', + )) + ->values(array( + 'presetid' => '1', + 'presetname' => 'slackjaw_boys', + ))->values(array( + 'presetid' => '2', + 'presetname' => 'big_blue_cheese', + ))->execute(); + } + +} +#b2102d82ad5b3d8be026fe23cea75674 diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php index a684403..d0d9d9b 100644 --- a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php +++ b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php @@ -848,6 +848,28 @@ public function load() { 'weight' => '0', 'info' => 'a:10:{s:4:"name";s:8:"Views UI";s:11:"description";s:93:"Administrative interface to views. Without this module, you cannot create or edit your views.";s:7:"package";s:5:"Views";s:4:"core";s:3:"6.x";s:12:"dependencies";a:1:{i:0;s:5:"views";}s:7:"version";s:7:"6.x-3.0";s:7:"project";s:5:"views";s:9:"datestamp";s:10:"1325638545";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}', ))->values(array( + 'filename' => 'sites/all/modules/imageapi/imageapi.module', + 'name' => 'imageapi', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '0', + 'weight' => '0', + 'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}', + ))->values(array( + 'filename' => 'sites/all/modules/imagecache/imagecache.module', + 'name' => 'imagecache', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '6001', + 'weight' => '0', + 'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}', + ))->values(array( 'filename' => 'themes/bluemarine/bluemarine.info', 'name' => 'bluemarine', 'type' => 'theme', @@ -917,4 +939,4 @@ public function load() { } } -#f48594e66407fef659b575523a75c6e6 +#f7d26efda87933cbe199c1f232d329b2 diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateImageCacheTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateImageCacheTest.php new file mode 100644 index 0000000..051172f --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateImageCacheTest.php @@ -0,0 +1,122 @@ +prepareMigrations(array( + 'd6_imagecache_presets' => [], + )); + $this->installConfig(array('image')); + } + + /** + * Override parent to setup migration prior to run. + */ + public function testSourcePlugin() { + $this->loadDumps(['ImagecachePreset.php', 'ImagecacheAction.php']); + $this->executeMigration('d6_imagecache_presets'); + parent::testSourcePlugin(); + } + + /** + * Test basic passing migrations. + */ + public function testPassingMigration() { + $this->loadDumps(['ImagecachePreset.php', 'ImagecacheAction.php']); + $this->executeMigration('d6_imagecache_presets'); + + /** @var \Drupal\image\Entity\ImageStyle $style */ + $style = ImageStyle::load('big_blue_cheese'); + + //check basic Style info + $this->assertIdentical('big_blue_cheese', $style->get('name'), 'ImageStyle name set correctly'); + $this->assertIdentical('big_blue_cheese', $style->get('label'), 'ImageStyle label set correctly'); + + //test effects + $effects = $style->getEffects(); + + //check crop effect + $this->assertImageEffect($effects, 'image_crop', [ + 'width' => 555, + 'height' => 5555, + 'anchor' => 'center-center', + ]); + + //check resize effect + $this->assertImageEffect($effects, 'image_resize', [ + 'width' => 55, + 'height' => 55, + ]); + + //check rotate effect + $this->assertImageEffect($effects, 'image_rotate', [ + 'degrees' => 55, + 'random' => FALSE, + 'bgcolor' => '', + ]); + } + + /** + * Test that missing action's causes failures. + */ + public function testMissingEffectPlugin() { + + $this->loadDumps(['ImagecacheAction_fail.php', 'ImagecachePreset.php']); + $this->startCollectingMessages(); + $this->executeMigration('d6_imagecache_presets'); + $this->assertEqual(['error' => [ + 'The "image_deprecated_scale" plugin does not exist.' + ]], $this->migrateMessages); + } + + /** + * Assert that a given image effect is migrated. + * + * @param array $collection + * Collection of effects + * @param $id + * Id that should exist in the collection. + * @param $config + * Expected configuration for the collection. + * + * @return bool + */ + protected function assertImageEffect($collection, $id, $config) { + /** @var \Drupal\image\ConfigurableImageEffectBase $effect */ + foreach ($collection as $key => $effect) { + $effect_config = $effect->getConfiguration(); + + if ($effect_config['id'] == $id && $effect_config['data'] == $config) { + return $this->pass('Effect ' . $id . ' imported correctly'); + } + } + return $this->fail('Effect ' . $id . ' did not import correctly'); + } +}