diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 3082892..308ab15 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -515,68 +515,60 @@ function image_field_config_delete(FieldConfigInterface $field) { /** * Implements hook_form_FORM_ID_alter(). * - * Alters the image dialog form for text editor, to allow the user to select an + * Alters the image dialog form for text editor to allow the user to select an * image style. * * @see \Drupal\editor\Form\EditorImageDialog::buildForm() */ -function image_form_editor_image_dialog_alter(&$form, FormStateInterface $form_state) { +function image_form_editor_image_dialog_alter(array &$form, FormStateInterface $form_state) { /** @var \Drupal\editor\EditorInterface $editor */ $editor = $form_state->getBuildInfo()['args'][0]; - // Alter the editor image dialog when image style functionality is available. /** @var \Drupal\image\Plugin\Filter\FilterImageStyle $filter */ $filter = $editor->getFilterFormat()->filters('filter_image_style'); - if ($filter->status) { - // Get the image () that is being edited on the client. - $image_element = $form_state->get('image_element'); - - // Get an array of image styles to present as options for selection. - $image_style_options = array_map(function (ImageStyleInterface $image_style) { - return $image_style->label(); - }, $filter->getAllowedImageStyles()); - - // If there is only a single image style the user doesn't have any choice. - // Just show a message in that case. - if (count($image_style_options) == 1) { - $label = reset($image_style_options); - $form['image_style']['selection'] = [ - '#type' => 'value', - '#value' => key($image_style_options), - '#parents' => ['attributes', 'data-image-style'], - ]; - $form['image_style']['help'] = [ - '#type' => 'html_tag', - '#tag' => 'p', - '#value' => t('The image will be displayed using the %image_style image style.', ['%image_style' => $label]), - ]; - } - else { - // Add a select element to choose an image style. - $form['image_style']['selection'] = [ - '#title' => t('Use image style'), - '#type' => 'select', - '#default_value' => isset($image_element['data-image-style']) ? $image_element['data-image-style'] : NULL, - '#options' => $image_style_options, - '#required' => TRUE, - '#parents' => ['attributes', 'data-image-style'], - ]; - } - // Add a link to the configuration of the image styles if the user has - // access to it. - $access_manager = \Drupal::service('access_manager'); - $route_parameters = ['filter_format' => $editor->getFilterFormat()->id()]; - if ($access_manager->checkNamedRoute('entity.filter_format.edit_form', $route_parameters, \Drupal::currentUser())) { - $url = Url::fromRoute('entity.filter_format.edit_form', $route_parameters); - $url->setOptions(['fragment' => 'edit-filters-filter-image-style-settings']); - $form['image_style']['link'] = [ - '#title' => t('Configure allowed image styles'), - '#type' => 'link', - '#url' => $url, - ]; - } + $access_filter_status = $filter->status; + + // Get the image () that is being edited on the client. + $image_element = $form_state->get('image_element'); + + // Get an array of image styles to present as options for selection. + $image_style_options = array_map(function (ImageStyleInterface $image_style) { + return $image_style->label(); + }, $filter->getAllowedImageStyles()); + + // Add a select element to choose an image style. + $form['image_style']['selection'] = [ + '#title' => t('Use image style'), + '#type' => 'select', + '#default_value' => isset($image_element['data-image-style']) ? $image_element['data-image-style'] : NULL, + '#options' => $image_style_options, + '#empty_value' => '', + '#parents' => ['attributes', 'data-image-style'], + '#access' => $access_filter_status, + ]; + + // Check access to configure allowed image styles for the configurtation + // link. + $route_parameters = ['filter_format' => $editor->getFilterFormat()->id()]; + $access_manager = \Drupal::service('access_manager'); + $access_administer_styles = \Drupal::currentUser()->hasPermission('administer image styles'); + $access_filter_form = $access_manager->checkNamedRoute('entity.filter_format.edit_form', $route_parameters, \Drupal::currentUser()); + + // Add a link to the configuration of the image styles. + $url = Url::fromRoute('entity.filter_format.edit_form', $route_parameters); + $url->setOptions(['fragment' => 'edit-filters-filter-image-style-settings']); + $form['image_style']['link'] = [ + '#title' => t('Configure allowed image styles'), + '#type' => 'link', + '#url' => $url, + '#access' => $access_filter_status && $access_administer_styles && $access_filter_form, + '#attributes' => [ + 'target' => '_blank', + ], + ]; + if ($access_filter_status) { $form['actions']['save_modal']['#validate'][] = 'image_form_editor_image_dialog_validate'; } } @@ -590,40 +582,41 @@ function image_form_editor_image_dialog_alter(&$form, FormStateInterface $form_s * @see \Drupal\editor\Form\EditorImageDialog::validateForm() * @see image_form_editor_image_dialog_alter() */ -function image_form_editor_image_dialog_validate(array &$form, FormStateInterface &$form_state) { +function image_form_editor_image_dialog_validate(array &$form, FormStateInterface $form_state) { if (!empty($form_state->getValue('fid')[0])) { - $attributes = &$form_state->getValue('attributes'); /** @var \Drupal\image\ImageStyleInterface $image_style */ $image_style = ImageStyle::load($attributes['data-image-style']); - /** @var \Drupal\file\FileInterface $file */ - $file = File::load($form_state->getValue('fid')[0]); + if (!empty($image_style)) { + /** @var \Drupal\file\FileInterface $file */ + $file = File::load($form_state->getValue('fid')[0]); - $uri = $file->getFileUri(); + $uri = $file->getFileUri(); - // Set the 'src' attribute to the image style URL. FilterImageStyle will - // look at the 'data-editor-file-uuid' attribute, not the 'src' attribute to - // render the appropriate output. - $image_url = $image_style->buildUrl($uri); - $attributes['src'] = file_url_transform_relative($image_url); + // Set the 'src' attribute to the image style URL. FilterImageStyle will + // look at the 'data-editor-file-uuid' attribute, not the 'src' attribute + // to render the appropriate output. + $image_url = $image_style->buildUrl($uri); + $attributes['src'] = file_url_transform_relative($image_url); - /** @var \Drupal\Core\Image\ImageInterface $image */ - $image = \Drupal::service('image.factory')->get($uri); + /** @var \Drupal\Core\Image\ImageInterface $image */ + $image = \Drupal::service('image.factory')->get($uri); - if ($image->isValid()) { - // Get the original width and height of the image. - $dimensions = [ - 'width' => $image->getWidth(), - 'height' => $image->getHeight(), - ]; - - // Transform the 'width' and 'height' dimensions of the image based on the - // image style. - $image_style->transformDimensions($dimensions, $attributes['src']); - $attributes['width'] = $dimensions['width']; - $attributes['height'] = $dimensions['height']; + if ($image->isValid()) { + // Get the original width and height of the image. + $dimensions = [ + 'width' => $image->getWidth(), + 'height' => $image->getHeight(), + ]; + + // Transform the 'width' and 'height' dimensions of the image based on + // the image style. + $image_style->transformDimensions($dimensions, $attributes['src']); + $attributes['width'] = $dimensions['width']; + $attributes['height'] = $dimensions['height']; + } } } } diff --git a/core/modules/image/js/plugins/drupalimagestyle/plugin.js b/core/modules/image/js/plugins/drupalimagestyle/plugin.js index ef8eae1..8d45a36 100644 --- a/core/modules/image/js/plugins/drupalimagestyle/plugin.js +++ b/core/modules/image/js/plugins/drupalimagestyle/plugin.js @@ -16,7 +16,7 @@ CKEDITOR.plugins.add('drupalimagestyle', { requires: 'drupalimage', - beforeInit: function (editor) { + beforeInit: function beforeInit(editor) { // Override the image2 widget definition to handle the additional // data-image-style attributes. editor.on('widgetDefinition', function (event) { @@ -44,7 +44,9 @@ if (!img) { img = findElementByName(element, 'img'); } - img.attributes['data-image-style'] = this.data['data-image-style']; + if (this.data.hasOwnProperty('data-image-style') && this.data['data-image-style'] !== '') { + img.attributes['data-image-style'] = this.data['data-image-style']; + } return img; }; diff --git a/core/modules/image/src/Plugin/CKEditorPlugin/DrupalImageStyle.php b/core/modules/image/src/Plugin/CKEditorPlugin/DrupalImageStyle.php index 0e6401b..ac92e8d 100644 --- a/core/modules/image/src/Plugin/CKEditorPlugin/DrupalImageStyle.php +++ b/core/modules/image/src/Plugin/CKEditorPlugin/DrupalImageStyle.php @@ -2,9 +2,8 @@ namespace Drupal\image\Plugin\CKEditorPlugin; -use Drupal\Component\Plugin\PluginBase; +use Drupal\ckeditor\CKEditorPluginBase; use Drupal\ckeditor\CKEditorPluginContextualInterface; -use Drupal\ckeditor\CKEditorPluginInterface; use Drupal\ckeditor\CKEditorPluginManager; use Drupal\editor\Entity\Editor; @@ -17,40 +16,27 @@ * module = "ckeditor" * ) */ -class DrupalImageStyle extends PluginBase implements CKEditorPluginInterface, CKEditorPluginContextualInterface { +class DrupalImageStyle extends CKEditorPluginBase implements CKEditorPluginContextualInterface { /** * {@inheritdoc} */ - public function isInternal() { - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function getDependencies(Editor $editor) { - return []; + public function getFile() { + return drupal_get_path('module', 'image') . '/js/plugins/drupalimagestyle/plugin.js'; } /** * {@inheritdoc} */ - public function getLibraries(Editor $editor) { + public function getConfig(Editor $editor) { return []; } /** * {@inheritdoc} */ - public function getFile() { - return drupal_get_path('module', 'image') . '/js/plugins/drupalimagestyle/plugin.js'; - } - - /** - * {@inheritdoc} - */ - public function getConfig(Editor $editor) { + public function getButtons() { + // Do not provide button. The drupalimage plugin provides the button for us. return []; } diff --git a/core/modules/image/src/Plugin/Filter/FilterImageStyle.php b/core/modules/image/src/Plugin/Filter/FilterImageStyle.php index e07798a..aeec29e 100644 --- a/core/modules/image/src/Plugin/Filter/FilterImageStyle.php +++ b/core/modules/image/src/Plugin/Filter/FilterImageStyle.php @@ -310,7 +310,8 @@ public function calculateDependencies() { public function tips($long = FALSE) { if ($long) { $image_styles = $this->getAllowedImageStyleIds(); - $list = new TranslatableMarkup('' . implode(', ', $image_styles) . ''); + $image_styles = implode(', ', $image_styles); + $list = new TranslatableMarkup("$image_styles"); return t('

You can display images using site-wide styles by adding a data-image-style attribute, whose values is one of the image style machine names: @image-style-machine-name-list.

', ['@image-style-machine-name-list' => $list]); } return t('You can display images using site-wide styles by adding a data-image-style attribute.'); diff --git a/core/modules/image/src/Tests/Update/ImageUpdateTextFormatsTest.php b/core/modules/image/src/Tests/Update/ImageUpdateTextFormatsTest.php deleted file mode 100644 index fd0441c..0000000 --- a/core/modules/image/src/Tests/Update/ImageUpdateTextFormatsTest.php +++ /dev/null @@ -1,47 +0,0 @@ -databaseDumpFiles = [ - __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', - ]; - } - - /** - * Tests image_post_update_enable_filter_image_style(). - * - * @see image_post_update_enable_filter_image_style() - */ - public function testPostUpdateFilterImageStyle() { - // Check that the 'basic_html' and 'full_html' formats do not have the image - // style filter before starting the update. - $config_factory = \Drupal::configFactory(); - $basic_html_data = $config_factory->get('filter.format.basic_html'); - $this->assertNull($basic_html_data->get('filters.filter_image_style')); - $full_html_data = $config_factory->get('filter.format.full_html'); - $this->assertNull($full_html_data->get('filters.filter_image_style')); - - // Run updates. - $this->runUpdates(); - - // Check that the filter_format entities have been updated. - $basic_html_data = $config_factory->get('filter.format.basic_html'); - $this->assertNotNull($basic_html_data->get('filters.filter_image_style')); - $full_html_data = $config_factory->get('filter.format.full_html'); - $this->assertNotNull($full_html_data->get('filters.filter_image_style')); - } - -} diff --git a/core/modules/image/tests/src/Functional/FilterImageStyleTest.php b/core/modules/image/tests/src/Functional/FilterImageStyleTest.php index 2c7aee6..40c99e1 100644 --- a/core/modules/image/tests/src/Functional/FilterImageStyleTest.php +++ b/core/modules/image/tests/src/Functional/FilterImageStyleTest.php @@ -11,6 +11,7 @@ * Tests FilterImageStyle conversion of inline images to utilize image styles. * * @coversDefaultClass \Drupal\image\Plugin\Filter\FilterImageStyle + * * @group image */ class FilterImageStyleTest extends BrowserTestBase { @@ -110,9 +111,9 @@ public function testImageStyle() { /** @var \Behat\Mink\Element\NodeElement $img_element */ $image_element = $this->getSession()->getPage()->find('css', 'img.image-style-medium'); - $this->assertFalse(empty($image_element)); + $this->assertNotEmpty($image_element); - $this->assertTrue(strpos($image_element->getAttribute('src'), 'medium')); + $this->assertContains('medium', $image_element->getAttribute('src')); $this->assertEquals('220', $image_element->getAttribute('width')); $this->assertEquals('164', $image_element->getAttribute('height')); } diff --git a/core/modules/image/tests/src/Functional/Update/ImageUpdateTest.php b/core/modules/image/tests/src/Functional/Update/ImageUpdateTest.php index c3a5ddf..865f898 100644 --- a/core/modules/image/tests/src/Functional/Update/ImageUpdateTest.php +++ b/core/modules/image/tests/src/Functional/Update/ImageUpdateTest.php @@ -32,11 +32,11 @@ public function testPostUpdateImageStylesDependencies() { // Check that view display 'node.article.default' doesn't depend on image // style 'image.style.large'. $dependencies = $this->config($view)->get('dependencies.config'); - $this->assertFalse(in_array('image.style.large', $dependencies)); + $this->assertNotContains('image.style.large', $dependencies); // Check that form display 'node.article.default' doesn't depend on image // style 'image.style.thumbnail'. $dependencies = $this->config($form)->get('dependencies.config'); - $this->assertFalse(in_array('image.style.thumbnail', $dependencies)); + $this->assertNotContains('image.style.thumbnail', $dependencies); // Run updates. $this->runUpdates(); @@ -44,11 +44,35 @@ public function testPostUpdateImageStylesDependencies() { // Check that view display 'node.article.default' depend on image style // 'image.style.large'. $dependencies = $this->config($view)->get('dependencies.config'); - $this->assertTrue(in_array('image.style.large', $dependencies)); + $this->assertContains('image.style.large', $dependencies); // Check that form display 'node.article.default' depend on image style // 'image.style.thumbnail'. $dependencies = $this->config($view)->get('dependencies.config'); - $this->assertTrue(in_array('image.style.large', $dependencies)); + $this->assertContains('image.style.large', $dependencies); + } + + /** + * Tests image_post_update_enable_filter_image_style(). + * + * @see image_post_update_enable_filter_image_style() + */ + public function testPostUpdateFilterImageStyle() { + // Check that the 'basic_html' and 'full_html' formats do not have the image + // style filter before starting the update. + $config_factory = \Drupal::configFactory(); + $basic_html_data = $config_factory->get('filter.format.basic_html'); + $this->assertNull($basic_html_data->get('filters.filter_image_style')); + $full_html_data = $config_factory->get('filter.format.full_html'); + $this->assertNull($full_html_data->get('filters.filter_image_style')); + + // Run updates. + $this->runUpdates(); + + // Check that the filter_format entities have been updated. + $basic_html_data = $config_factory->get('filter.format.basic_html'); + $this->assertNotNull($basic_html_data->get('filters.filter_image_style')); + $full_html_data = $config_factory->get('filter.format.full_html'); + $this->assertNotNull($full_html_data->get('filters.filter_image_style')); } } diff --git a/core/modules/image/tests/src/FunctionalJavascript/AddImageTest.php b/core/modules/image/tests/src/FunctionalJavascript/AddImageTest.php index f8562e5..4f65cf0 100644 --- a/core/modules/image/tests/src/FunctionalJavascript/AddImageTest.php +++ b/core/modules/image/tests/src/FunctionalJavascript/AddImageTest.php @@ -69,10 +69,8 @@ public function testDataImageStyleElement() { $image_button = $page->find('css', $image_button_selector); $this->assertNotEmpty($image_button); $image_button->click(); - // Wait for the modal form elements to appear (loading is done). - $this->assertJsCondition("jQuery('input[data-drupal-selector=\"edit-attributes-alt\"]').length > 0"); - $url_input = $page->findField('attributes[src]'); + $url_input = $this->assertSession()->waitForField('attributes[src]'); $this->assertNotEmpty($url_input); $url_input->setValue($image_url); @@ -87,8 +85,8 @@ public function testDataImageStyleElement() { // To prevent 403s on save, we re-set our request (cookie) state. $this->prepareRequest(); - // Using NodeElement::click() on the button or NodeElement::submit() on the - // form generated phantomjs-internal exceptions. This was the only recourse. + // @todo: Switch to using NodeElement::click() on the button or + // NodeElement::submit() on the form when #2831506 is fixed. // @see https://www.drupal.org/node/2831506 $script = "jQuery('input[id^=\"edit-actions-save-modal\"]').click()"; $this->getSession()->executeScript($script); @@ -97,7 +95,6 @@ public function testDataImageStyleElement() { $source_button = $page->find('css', 'a.cke_button__source'); $this->assertNotEmpty($source_button); $source_button->click(); - $this->assertSession()->assertWaitOnAjaxRequest(); $this->assertContains('data-image-style="thumbnail"', $page->find('css', 'textarea.cke_source')->getValue()); } diff --git a/core/modules/image/tests/src/Kernel/EditorImageStyleDialogTest.php b/core/modules/image/tests/src/Kernel/EditorImageStyleDialogTest.php index bdcad28..5c456af 100644 --- a/core/modules/image/tests/src/Kernel/EditorImageStyleDialogTest.php +++ b/core/modules/image/tests/src/Kernel/EditorImageStyleDialogTest.php @@ -27,7 +27,11 @@ class EditorImageStyleDialogTest extends EntityKernelTestBase { protected $editor; /** - * {@inheritdoc} + * Modules to enable. + * + * @var array + * + * @todo: Change to protected. https://www.drupal.org/node/2822382 */ public static $modules = [ 'ckeditor', @@ -151,7 +155,8 @@ protected function setUpForm($enable_image_filter) { public function testDialogNoStyles() { $form = $this->setUpForm(FALSE); - $this->assertArrayNotHasKey('image_style', $form); + $this->assertFalse($form['image_style']['selection']['#access']); + $this->assertFalse($form['image_style']['link']['#access']); } /** @@ -160,10 +165,9 @@ public function testDialogNoStyles() { public function testDialogStyles() { $form = $this->setUpForm(TRUE); - $this->assertEquals(['large', 'medium', 'thumbnail'], array_keys($form['image_style']['selection']['#options'])); + $this->assertEquals(['', 'large', 'medium', 'thumbnail'], array_keys($form['image_style']['selection']['#options'])); $this->assertEquals('medium', $form['image_style']['selection']['#default_value']); - $this->assertEquals(TRUE, $form['image_style']['selection']['#required']); } }