/** * Tests moving a randomly generated image. */ function testNormal() { // Pick a file for testing. $file = File::create((array) current($this->drupalGetTestFiles('image'))); // Create derivative image. $styles = ImageStyle::loadMultiple(); $style = reset($styles); $original_uri = $file->getFileUri(); $derivative_uri = $style->buildUri($original_uri); $style->createDerivative($original_uri, $derivative_uri); // Check if derivative image exists. $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.'); // Clone the object so we don't have to worry about the function changing // our reference copy. $desired_filepath = 'public://' . $this->randomMachineName(); $result = file_move(clone $file, $desired_filepath, FILE_EXISTS_ERROR); // Check if image has been moved. $this->assertTrue(file_exists($result->getFileUri()), 'Make sure image is moved successfully.'); // Check if derivative image has been flushed. $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.'); }
/** * {@inheritdoc} */ public function calculateDependencies() { parent::calculateDependencies(); $providers = \Drupal::service('breakpoint.manager')->getGroupProviders($this->breakpoint_group); foreach ($providers as $provider => $type) { $this->addDependency($type, $provider); } // Extract all the styles from the image style mappings. $styles = ImageStyle::loadMultiple($this->getImageStyleIds()); array_walk($styles, function ($style) { $this->addDependency('config', $style->getConfigDependencyName()); }); return $this; }
/** * General test to add a style, add/remove/edit effects to it, then delete it. */ function testStyle() { $admin_path = 'admin/config/media/image-styles'; // Setup a style to be created and effects to add to it. $style_name = strtolower($this->randomMachineName(10)); $style_label = $this->randomString(); $style_path = $admin_path . '/manage/' . $style_name; $effect_edits = array('image_resize' => array('width' => 100, 'height' => 101), 'image_scale' => array('width' => 110, 'height' => 111, 'upscale' => 1), 'image_scale_and_crop' => array('width' => 120, 'height' => 121), 'image_crop' => array('width' => 130, 'height' => 131, 'anchor' => 'left-top'), 'image_desaturate' => array(), 'image_rotate' => array('degrees' => 5, 'random' => 1, 'bgcolor' => '#FFFF00')); // Add style form. $edit = array('name' => $style_name, 'label' => $style_label); $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); $this->assertRaw(t('Style %name was created.', array('%name' => $style_label))); // Ensure that the expected entity operations are there. $this->drupalGet($admin_path); $this->assertLinkByHref($style_path); $this->assertLinkByHref($style_path . '/flush'); $this->assertLinkByHref($style_path . '/delete'); // Add effect form. // Add each sample effect to the style. foreach ($effect_edits as $effect => $edit) { $edit_data = array(); foreach ($edit as $field => $value) { $edit_data['data[' . $field . ']'] = $value; } // Add the effect. $this->drupalPostForm($style_path, array('new' => $effect), t('Add')); if (!empty($edit)) { $this->drupalPostForm(NULL, $edit_data, t('Add effect')); } } // Load the saved image style. $style = ImageStyle::load($style_name); // Ensure that third party settings were added to the config entity. // These are added by a hook_image_style_presave() implemented in // image_module_test module. $this->assertEqual('bar', $style->getThirdPartySetting('image_module_test', 'foo'), 'Third party settings were added to the image style.'); // Ensure that the image style URI matches our expected path. $style_uri_path = $style->url(); $this->assertTrue(strpos($style_uri_path, $style_path) !== FALSE, 'The image style URI is correct.'); // Confirm that all effects on the image style have settings that match // what was saved. $uuids = array(); foreach ($style->getEffects() as $uuid => $effect) { // Store the uuid for later use. $uuids[$effect->getPluginId()] = $uuid; $effect_configuration = $effect->getConfiguration(); foreach ($effect_edits[$effect->getPluginId()] as $field => $value) { $this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', array('%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value))); } } // Assert that every effect was saved. foreach (array_keys($effect_edits) as $effect_name) { $this->assertTrue(isset($uuids[$effect_name]), format_string('A %effect_name effect was saved with ID %uuid', array('%effect_name' => $effect_name, '%uuid' => $uuids[$effect_name]))); } // Image style overview form (ordering and renaming). // Confirm the order of effects is maintained according to the order we // added the fields. $effect_edits_order = array_keys($effect_edits); $order_correct = TRUE; $index = 0; foreach ($style->getEffects() as $effect) { if ($effect_edits_order[$index] != $effect->getPluginId()) { $order_correct = FALSE; } $index++; } $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); // Test the style overview form. // Change the name of the style and adjust the weights of effects. $style_name = strtolower($this->randomMachineName(10)); $style_label = $this->randomMachineName(); $weight = count($effect_edits); $edit = array('name' => $style_name, 'label' => $style_label); foreach ($style->getEffects() as $uuid => $effect) { $edit['effects[' . $uuid . '][weight]'] = $weight; $weight--; } // Create an image to make sure it gets flushed after saving. $image_path = $this->createSampleImage($style); $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', array('%style' => $style->label(), '%file' => $image_path))); $this->drupalPostForm($style_path, $edit, t('Update style')); // Note that after changing the style name, the style path is changed. $style_path = 'admin/config/media/image-styles/manage/' . $style_name; // Check that the URL was updated. $this->drupalGet($style_path); $this->assertTitle(t('Edit style @name | Drupal', array('@name' => $style_label))); $this->assertResponse(200, format_string('Image style %original renamed to %new', array('%original' => $style->id(), '%new' => $style_name))); // Check that the image was flushed after updating the style. // This is especially important when renaming the style. Make sure that // the old image directory has been deleted. $this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', array('%style' => $style->label()))); // Load the style by the new name with the new weights. $style = ImageStyle::load($style_name); // Confirm the new style order was saved. $effect_edits_order = array_reverse($effect_edits_order); $order_correct = TRUE; $index = 0; foreach ($style->getEffects() as $effect) { if ($effect_edits_order[$index] != $effect->getPluginId()) { $order_correct = FALSE; } $index++; } $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); // Image effect deletion form. // Create an image to make sure it gets flushed after deleting an effect. $image_path = $this->createSampleImage($style); $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', array('%style' => $style->label(), '%file' => $image_path))); // Delete the 'image_crop' effect from the style. $this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', array(), t('Delete')); // Confirm that the form submission was successful. $this->assertResponse(200); $image_crop_effect = $style->getEffect($uuids['image_crop']); $this->assertRaw(t('The image effect %name has been deleted.', array('%name' => $image_crop_effect->label()))); // Confirm that there is no longer a link to the effect. $this->assertNoLinkByHref($style_path . '/effects/' . $uuids['image_crop'] . '/delete'); // Refresh the image style information and verify that the effect was // actually deleted. $style = entity_load_unchanged('image_style', $style->id()); $this->assertFalse($style->getEffects()->has($uuids['image_crop']), format_string('Effect with ID %uuid no longer found on image style %style', array('%uuid' => $uuids['image_crop'], '%style' => $style->label()))); // Additional test on Rotate effect, for transparent background. $edit = array('data[degrees]' => 5, 'data[random]' => 0, 'data[bgcolor]' => ''); $this->drupalPostForm($style_path, array('new' => 'image_rotate'), t('Add')); $this->drupalPostForm(NULL, $edit, t('Add effect')); $style = entity_load_unchanged('image_style', $style_name); $this->assertEqual(count($style->getEffects()), 6, 'Rotate effect with transparent background was added.'); // Style deletion form. // Delete the style. $this->drupalPostForm($style_path . '/delete', array(), t('Delete')); // Confirm the style directory has been removed. $directory = file_default_scheme() . '://styles/' . $style_name; $this->assertFalse(is_dir($directory), format_string('Image style %style directory removed on style deletion.', array('%style' => $style->label()))); $this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', array('%style' => $style->label()))); // Test empty text when there are no image styles. // Delete all image styles. foreach (ImageStyle::loadMultiple() as $image_style) { $image_style->delete(); } // Confirm that the empty text is correct on the image styles page. $this->drupalGet($admin_path); $this->assertRaw(t('There are currently no styles. <a href=":url">Add a new one</a>.', [':url' => \Drupal::url('image.style_add')])); }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items) { $elements = array(); // Check if the formatter involves a link. $image_link_setting = $this->getSetting('image_link'); if ($image_link_setting == 'content') { $entity = $items->getEntity(); if (!$entity->isNew()) { // @todo Remove when theme_image_formatter() has support for route name. $uri['path'] = $entity->getSystemPath(); $uri['options'] = $entity->urlInfo()->getOptions(); } } elseif ($image_link_setting == 'file') { $link_file = TRUE; } $fallback_image_style = ''; // Check if the user defined a custom fallback image style. if ($this->getSetting('fallback_image_style')) { $fallback_image_style = $this->getSetting('fallback_image_style'); } // Collect cache tags to be added for each item in the field. $image_styles_to_load = array_filter($this->getSetting('image_styles')); if ($fallback_image_style) { $image_styles_to_load[] = $fallback_image_style; } $image_styles = ImageStyle::loadMultiple($image_styles_to_load); foreach ($image_styles as $image_style) { $all_cache_tags[] = $image_style->getCacheTag(); } $cache_tags = NestedArray::mergeDeepArray($all_cache_tags); foreach ($items as $delta => $item) { if ($item->entity) { if (isset($link_file)) { $image_uri = $item->entity->getFileUri(); $uri = array('path' => file_create_url($image_uri), 'options' => array()); } // Extract field item attributes for the theme function, and unset them // from the $item so that the field template does not re-render them. $item_attributes = $item->_attributes; unset($item->_attributes); $elements[$delta] = array('#theme' => 'image_sizes_formatter', '#attached' => array('library' => array('core/picturefill')), '#item' => $item, '#item_attributes' => $item_attributes, '#image_styles' => array_filter($this->getSetting('image_styles')), '#fallback_image_style' => $this->getSetting('fallback_image_style'), '#sizes' => $this->getSetting('sizes'), '#path' => isset($uri) ? $uri : '', '#cache' => array('tags' => $cache_tags)); } } return $elements; }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items) { $elements = array(); $files = $this->getEntitiesToView($items); // Early opt-out if the field is empty. if (empty($files)) { return $elements; } $url = NULL; // Check if the formatter involves a link. if ($this->getSetting('image_link') == 'content') { $entity = $items->getEntity(); if (!$entity->isNew()) { $url = $entity->urlInfo(); } } elseif ($this->getSetting('image_link') == 'file') { $link_file = TRUE; } $fallback_image_style = ''; // Check if the user defined a custom fallback image style. if ($this->getSetting('fallback_image_style')) { $fallback_image_style = $this->getSetting('fallback_image_style'); } // Collect cache tags to be added for each item in the field. $responsive_image_style = $this->responsiveImageStyleStorage->load($this->getSetting('responsive_image_style')); $image_styles_to_load = array(); $cache_tags = []; if ($responsive_image_style) { $cache_tags = Cache::mergeTags($cache_tags, $responsive_image_style->getCacheTags()); $image_styles_to_load = $responsive_image_style->getImageStyleIds(); } // If there is a fallback image style, add it to the image styles to load. if ($fallback_image_style) { $image_styles_to_load[] = $fallback_image_style; } else { // The <picture> element uses the first matching breakpoint (see // http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#update-the-source-set // points 2 and 3). Meaning the breakpoints are sorted from large to // small. With mobile-first in mind, the fallback image should be the one // selected for the smallest screen. $fallback_image_style = end($image_styles_to_load); } $image_styles = ImageStyle::loadMultiple($image_styles_to_load); foreach ($image_styles as $image_style) { $cache_tags = Cache::mergeTags($cache_tags, $image_style->getCacheTags()); } foreach ($files as $delta => $file) { // Link the <picture> element to the original file. if (isset($link_file)) { $url = Url::fromUri(file_create_url($file->getFileUri())); } $elements[$delta] = array('#theme' => 'responsive_image_formatter', '#attached' => array('library' => array('core/picturefill')), '#item' => $file->_referringItem, '#image_style' => $fallback_image_style, '#responsive_image_style_id' => $responsive_image_style ? $responsive_image_style->id() : '', '#url' => $url, '#cache' => array('tags' => $cache_tags)); } return $elements; }
/** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { $row = []; $row['name'] = [ 'data' => $this->getLabel($entity), 'class' => ['menu-label'], ]; $row['description'] = Xss::filterAdmin($entity->description); $row['aspect_ratio'] = $entity->getAspectRatio(); // Load all image styles used by the current crop type. $image_style_ids = $this->queryFactory->get('image_style') ->condition('effects.*.data.crop_type', $entity->id()) ->execute(); $image_styles = ImageStyle::loadMultiple($image_style_ids); /** @var \Drupal\image\Entity\ImageStyle $image_style */ $usage = []; foreach ($image_styles as $image_style) { if (count($usage) < 2) { $usage[] = $image_style->link(); } } $other_image_styles = array_splice($image_styles, 2); if ($other_image_styles) { $usage_message = t('@first, @second and @count more', ['@first' => $usage[0], '@second' => $usage[1], '@count' => count($other_image_styles)]); } else { $usage_message = implode(', ', $usage); } $row['usage']['data']['#markup'] = $usage_message; return $row + parent::buildRow($entity); }