diff --git a/core/modules/image/image.install b/core/modules/image/image.install index 75ffd2a..3b357fa 100644 --- a/core/modules/image/image.install +++ b/core/modules/image/image.install @@ -5,6 +5,8 @@ * Install, update and uninstall functions for the image module. */ +use Drupal\Component\Uuid\Uuid; + /** * Implements hook_install(). */ @@ -103,3 +105,68 @@ function image_requirements($phase) { return $requirements; } + +/** + * Loads all effects for an image style. + * + * @param array $style + * The image style (array) to retrieve effects for. + * + * @return array + * An array of effects keyed by UUIDs. + * + * @see image_update_8000() + */ +function _image_update_get_style_with_effects(array $style) { + // Retrieve image effects. + // @todo Module updates are not able to invoke module hooks and API functions; + // additional information previously supplied via hook_image_effect_info() + // is not and cannot be taken into account. + $effects = array(); + $result = db_select('image_effects', NULL, array('fetch' => PDO::FETCH_ASSOC)) + ->fields('image_effects') + ->condition('isid', $style['isid']) + ->execute(); + foreach ($result as $effect) { + unset($effect['isid']); + $effect['data'] = unserialize($effect['data']); + + // Generate a unique image effect ID for the effect. + $uuid = new Uuid(); + $effect['ieid'] = $uuid->generate(); + + $effects[$effect['ieid']] = $effect; + } + return $effects; +} + +/** + * Convert existing image styles to the new config system. + */ +function image_update_8000() { + $styles = array(); + $result = db_select('image_styles', NULL, array('fetch' => PDO::FETCH_ASSOC)) + ->fields('image_styles') + ->execute() + ->fetchAllAssoc('name', PDO::FETCH_ASSOC); + foreach ($result as $style_name => $style) { + $style['effects'] = _image_update_get_style_with_effects($style); + $styles[$style_name] = $style; + } + + // Convert each style into a configuration object. + foreach ($styles as $name => $style) { + $config = config('image.style.' . $name); + $config->set('name', $name); + $config->set('effects', $style['effects']); + $config->save(); + } +} + +/** + * Remove the {image_styles} and {image_effects} tables. + */ +function image_update_8001() { + db_drop_table('image_styles'); + db_drop_table('image_effects'); +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ImageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ImageUpgradePathTest.php new file mode 100644 index 0000000..d0e9951 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ImageUpgradePathTest.php @@ -0,0 +1,112 @@ + 'Image upgrade test', + 'description' => 'Upgrade tests for overridden and custom image styles.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + $this->databaseDumpFiles = array( + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz', + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.image.database.php', + ); + parent::setUp(); + } + + /** + * Tests that custom and overridden image styles have been upgraded. + */ + public function testImageStyleUpgrade() { + $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); + + // Verify that image styles were properly upgraded. + $expected_styles['test-custom'] = array( + 'name' => 'test-custom', + 'effects' => array( + 'uuid1' => array( + 'name' => 'image_rotate', + 'data' => array( + 'degrees' => '90', + 'bgcolor' => '#FFFFFF', + 'random' => '1', + ), + 'weight' => '1', + ), + 'uuid2' => array( + 'name' => 'image_desaturate', + 'data' => array(), + 'weight' => '2', + ), + ), + ); + $expected_styles['thumbnail'] = array( + 'name' => 'thumbnail', + 'effects' => array ( + 'uuid1' => array( + 'name' => 'image_scale', + 'data' => array ( + 'width' => '177', + 'height' => '177', + 'upscale' => '0', + ), + 'weight' => '0', + ), + ), + ); + foreach ($expected_styles as $name => $style) { + $config = config('image.style.' . $name); + // Replace placeholder uuid + number keys with UUID's generated during by + // the image style upgrade functions. + $count = 1; + foreach ($config->get('effects') as $uuid => $effect) { + // Copy placeholder data. + $style['effects'][$uuid] = $style['effects']['uuid' . $count]; + // Set the missing ieid key as this is unknown because it is a UUID. + $style['effects'][$uuid]['ieid'] = $uuid; + // Remove the placeholder data. + unset($style['effects']['uuid' . $count]); + $count++; + } + $this->assertEqual($this->sortByKey($style), $config->get(), format_string('@first is equal to @second.', array( + '@first' => var_export($this->sortByKey($style), TRUE), + '@second' => var_export($config->get(), TRUE), + ))); + } + } + /** + * Sorts all keys in configuration data. + * + * Since we can not be sure of the order of the UUID's generated by + * _image_update_get_style_with_effects() we need to sort the data in order + * to compare it with data saved in the config system. + * + * @param array $data + * An associative array to sort recursively by key name. + * + * @return array + * A sorted array. + */ + public function sortByKey(array $data) { + ksort($data); + foreach ($data as &$value) { + if (is_array($value)) { + $this->sortByKey($value); + } + } + return $data; + } +} \ No newline at end of file diff --git a/core/modules/system/tests/upgrade/drupal-7.image.database.php b/core/modules/system/tests/upgrade/drupal-7.image.database.php new file mode 100644 index 0000000..6d7f456 --- /dev/null +++ b/core/modules/system/tests/upgrade/drupal-7.image.database.php @@ -0,0 +1,59 @@ +fields(array( + 'isid', + 'name', +)) +// Override thumbnail style. +->values(array( + 'isid' => '1', + 'name' => 'thumbnail', +)) +// Custom style. +->values(array( + 'isid' => '2', + 'name' => 'test-custom', +)) +->execute(); + +// Add image effects. +db_insert('image_effects')->fields(array( + 'ieid', + 'isid', + 'weight', + 'name', + 'data', +)) +->values(array( + 'ieid' => '1', + 'isid' => '1', + 'weight' => '0', + 'name' => 'image_scale', + 'data' => 'a:3:{s:5:"width";s:3:"177";s:6:"height";s:3:"177";s:7:"upscale";i:0;}', +)) +->values(array( + 'ieid' => '3', + 'isid' => '2', + 'weight' => '1', + 'name' => 'image_rotate', + 'data' => 'a:3:{s:7:"degrees";s:2:"90";s:7:"bgcolor";s:7:"#FFFFFF";s:6:"random";i:1;}', +)) +->values(array( + 'ieid' => '4', + 'isid' => '2', + 'weight' => '2', + 'name' => 'image_desaturate', + 'data' => 'a:0:{}', +)) +->execute();