', $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/tests/src/Functional/FilterImageStyleTest.php b/core/modules/image/tests/src/Functional/FilterImageStyleTest.php
new file mode 100644
index 0000000..40c99e1
--- /dev/null
+++ b/core/modules/image/tests/src/Functional/FilterImageStyleTest.php
@@ -0,0 +1,121 @@
+format = FilterFormat::create([
+ 'format' => $this->randomMachineName(),
+ 'name' => $this->randomString(),
+ 'filters' => [
+ 'filter_html' => [
+ 'status' => TRUE,
+ 'settings' => [
+ 'allowed_html' => '',
+ ],
+ ],
+ 'filter_image_style' => ['status' => TRUE],
+ 'editor_file_reference' => ['status' => TRUE],
+ ],
+ ]);
+ $this->format->save();
+
+ $user = $this->drupalCreateUser(['access content', 'administer nodes']);
+ $this->drupalLogin($user);
+
+ $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
+ }
+
+ /**
+ * Helper function to create a test node with configurable image html.
+ */
+ protected function nodeHelper($image_html) {
+ $node = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'title' => $this->randomString(),
+ 'body' => [
+ [
+ 'format' => $this->format->id(),
+ 'value' => $image_html,
+ ],
+ ],
+ ]);
+ $node->save();
+
+ $this->drupalGet($node->toUrl());
+ $this->assertSession()->statusCodeEquals(200);
+ }
+
+ /**
+ * Tests that images not uploaded through media module are unmolested.
+ */
+ public function testImageNoStyle() {
+ $file_url = Url::fromUri('base:core/themes/bartik/screenshot.png')->toString();
+
+ $image_html = '';
+ $this->nodeHelper($image_html);
+
+ /** @var \Behat\Mink\Element\NodeElement $img_element */
+ $image_element = $this->getSession()->getPage()->find('css', "img");
+ $this->assertNotEmpty($image_element);
+
+ $this->assertFalse($image_element->hasAttribute('class'));
+ $this->assertEquals($file_url, $image_element->getAttribute('src'));
+ $this->assertEquals('220', $image_element->getAttribute('width'));
+ $this->assertFalse($image_element->hasAttribute('height'));
+ }
+
+ /**
+ * Tests image style modification of images.
+ */
+ public function testImageStyle() {
+ $this->assertArrayHasKey('medium', $this->container->get('entity_type.manager')->getStorage('image_style')->loadMultiple());
+
+ $file = File::create(['uri' => 'core/themes/bartik/screenshot.png']);
+ $file->save();
+
+ $image_html = '';
+ $this->nodeHelper($image_html);
+
+ /** @var \Behat\Mink\Element\NodeElement $img_element */
+ $image_element = $this->getSession()->getPage()->find('css', 'img.image-style-medium');
+ $this->assertNotEmpty($image_element);
+
+ $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
new file mode 100644
index 0000000..4f65cf0
--- /dev/null
+++ b/core/modules/image/tests/src/FunctionalJavascript/AddImageTest.php
@@ -0,0 +1,102 @@
+ 'filtered_html',
+ 'name' => $this->randomString(),
+ 'filters' => [
+ 'filter_image_style' => ['status' => TRUE],
+ ],
+ ])->save();
+
+ $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
+
+ Editor::create([
+ 'format' => 'filtered_html',
+ 'editor' => 'ckeditor',
+ ])->save();
+
+ $user = $this->drupalCreateUser([
+ 'access content',
+ 'administer nodes',
+ 'create page content',
+ 'use text format filtered_html',
+ ]);
+ $this->drupalLogin($user);
+ }
+
+ /**
+ * Tests if an image can be placed inline with the data-image-style attribute.
+ */
+ public function testDataImageStyleElement() {
+ $image_url = Url::fromUri('base:core/themes/bartik/screenshot.png')->toString();
+
+ $this->drupalGet('node/add/page');
+ $this->assertSession()->statusCodeEquals(200);
+
+ $page = $this->getSession()->getPage();
+ // Wait for the ckeditor toolbar elements to appear (loading is done).
+ $image_button_selector = 'a.cke_button__drupalimage';
+ $this->assertJsCondition("jQuery('$image_button_selector').length > 0");
+
+ $image_button = $page->find('css', $image_button_selector);
+ $this->assertNotEmpty($image_button);
+ $image_button->click();
+
+ $url_input = $this->assertSession()->waitForField('attributes[src]');
+ $this->assertNotEmpty($url_input);
+ $url_input->setValue($image_url);
+
+ $alt_input = $page->findField('attributes[alt]');
+ $this->assertNotEmpty($alt_input);
+ $alt_input->setValue('asd');
+
+ $image_style_input_name = 'attributes[data-image-style]';
+ $this->assertNotEmpty($page->findField($image_style_input_name));
+ $page->selectFieldOption($image_style_input_name, 'thumbnail');
+
+ // To prevent 403s on save, we re-set our request (cookie) state.
+ $this->prepareRequest();
+
+ // @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);
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ $source_button = $page->find('css', 'a.cke_button__source');
+ $this->assertNotEmpty($source_button);
+ $source_button->click();
+
+ $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
new file mode 100644
index 0000000..5c456af
--- /dev/null
+++ b/core/modules/image/tests/src/Kernel/EditorImageStyleDialogTest.php
@@ -0,0 +1,173 @@
+installEntitySchema('file');
+ $this->installSchema('system', ['key_value_expire']);
+ $this->installSchema('node', ['node_access']);
+ $this->installSchema('file', ['file_usage']);
+ $this->installConfig(['node']);
+
+ // Install the image module config so we have the medium image style.
+ $this->installConfig('image');
+
+ // Create a node type for testing.
+ $type = NodeType::create(['type' => 'page', 'name' => 'page']);
+ $type->save();
+ node_add_body_field($type);
+ $this->installEntitySchema('user');
+ $this->container->get('router.builder')->rebuild();
+ }
+
+ /**
+ * Fixture to consolidate tasks while making filter status configurable.
+ *
+ * @param bool $enable_image_filter
+ * Whether to activate filter_image_style in the text format.
+ *
+ * @return array|\Symfony\Component\HttpFoundation\Response
+ * The submitted form.
+ */
+ protected function setUpForm($enable_image_filter) {
+ $format = FilterFormat::create([
+ 'format' => $this->randomMachineName(),
+ 'name' => $this->randomString(),
+ 'weight' => 0,
+ 'filters' => [
+ 'filter_image_style' => ['status' => $enable_image_filter],
+ ],
+ ]);
+ $format->save();
+
+ // Set up text editor.
+ /** @var \Drupal\editor\EditorInterface $editor */
+ $editor = Editor::create([
+ 'format' => $format->id(),
+ 'editor' => 'ckeditor',
+ 'image_upload' => [
+ 'max_size' => 100,
+ 'scheme' => 'public',
+ 'directory' => '',
+ 'status' => TRUE,
+ ],
+ ]);
+ $editor->save();
+
+ /** @var \Drupal\file\FileInterface $file */
+ $file = file_save_data(file_get_contents($this->root . '/core/modules/image/sample.png'), 'public://');
+
+ $input = [
+ 'editor_object' => [
+ 'src' => file_url_transform_relative($file->getFileUri()),
+ 'alt' => 'Balloons floating above a field.',
+ 'data-entity-type' => 'file',
+ 'data-entity-uuid' => $file->uuid(),
+ ],
+ 'dialogOptions' => [
+ 'title' => 'Edit Image',
+ 'dialogClass' => 'editor-image-dialog',
+ 'autoResize' => 'true',
+ ],
+ '_drupal_ajax' => '1',
+ 'ajax_page_state' => [
+ 'theme' => 'bartik',
+ 'theme_token' => 'some-token',
+ 'libraries' => '',
+ ],
+ ];
+ if ($enable_image_filter) {
+ $input['editor_object']['data-image-style'] = 'medium';
+ }
+
+ $form_state = (new FormState())
+ ->setRequestMethod('POST')
+ ->setUserInput($input)
+ ->addBuildInfo('args', [$editor]);
+
+ /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
+ $form_builder = $this->container->get('form_builder');
+ $form_object = new EditorImageDialog(\Drupal::entityTypeManager()->getStorage('file'));
+ $form_id = $form_builder->getFormId($form_object, $form_state);
+ $form = [];
+
+ /** @var \Drupal\Core\Render\RendererInterface $renderer */
+ $renderer = \Drupal::service('renderer');
+ $renderer->executeInRenderContext(new RenderContext(), function () use (&$form, $form_builder, $form_id, $form_state) {
+ $form = $form_builder->retrieveForm($form_id, $form_state);
+ $form_builder->prepareForm($form_id, $form, $form_state);
+ $form_builder->processForm($form_id, $form, $form_state);
+ });
+
+ return $form;
+ }
+
+ /**
+ * Tests that style selection is hidden when filter_image_style is disabled.
+ */
+ public function testDialogNoStyles() {
+ $form = $this->setUpForm(FALSE);
+
+ $this->assertFalse($form['image_style']['selection']['#access']);
+ $this->assertFalse($form['image_style']['link']['#access']);
+ }
+
+ /**
+ * Tests EditorImageDialog when filter_image_style is enabled.
+ */
+ public function testDialogStyles() {
+ $form = $this->setUpForm(TRUE);
+
+ $this->assertEquals(['', 'large', 'medium', 'thumbnail'], array_keys($form['image_style']['selection']['#options']));
+
+ $this->assertEquals('medium', $form['image_style']['selection']['#default_value']);
+ }
+
+}
diff --git a/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php b/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php
index 09e40aa..00b72db 100644
--- a/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php
+++ b/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php
@@ -39,7 +39,7 @@ public function testAllowedHtmlUpdate() {
// Make sure we have the expected values after the update.
$filters_after = [
- 'basic_html' => ' -
-
-
',
+ 'basic_html' => ' -
-
-
',
'restricted_html' => ' -
-
-
',
];
foreach ($filters_after as $name => $after) {
diff --git a/core/profiles/standard/config/install/filter.format.basic_html.yml b/core/profiles/standard/config/install/filter.format.basic_html.yml
index 92224c2..9f03910 100644
--- a/core/profiles/standard/config/install/filter.format.basic_html.yml
+++ b/core/profiles/standard/config/install/filter.format.basic_html.yml
@@ -1,8 +1,13 @@
langcode: en
status: true
dependencies:
+ config:
+ - image.style.large
+ - image.style.medium
+ - image.style.thumbnail
module:
- editor
+ - image
name: 'Basic HTML'
format: basic_html
weight: 0
@@ -15,7 +20,7 @@ filters:
status: true
weight: -10
settings:
- allowed_html: '