Update core 8.3.0

This commit is contained in:
Rob Davies 2017-04-13 15:53:35 +01:00
parent da7a7918f8
commit cd7a898e66
6144 changed files with 132297 additions and 87747 deletions

View file

@ -139,6 +139,14 @@ field.formatter.settings.image:
type: string
label: 'Image style'
field.formatter.settings.image_url:
type: mapping
label: 'Image URL formatter settings'
mapping:
image_style:
type: string
label: 'Image style'
field.widget.settings.image_image:
type: mapping
label: 'Image field display format settings'

View file

@ -0,0 +1,52 @@
/**
* @file
* Functional styles for the Image module's in-place editor.
*/
/**
* A minimum width/height is required so that users can drag and drop files
* onto small images.
*/
.quickedit-image-element {
min-width: 200px;
min-height: 200px;
}
.quickedit-image-dropzone {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.quickedit-image-icon {
display: block;
width: 50px;
height: 50px;
background-repeat: no-repeat;
background-size: cover;
}
.quickedit-image-field-info {
display: flex;
align-items: center;
justify-content: flex-end;
}
.quickedit-image-text {
display: block;
}
/**
* If we do not prevent pointer-events for child elements, our drag+drop events
* will not fire properly. This can lead to unintentional redirects if a file
* is dropped on a child element when a user intended to upload it.
*/
.quickedit-image-dropzone * {
pointer-events: none;
}

View file

@ -0,0 +1,100 @@
/**
* @file
* Theme styles for the Image module's in-place editor.
*/
.quickedit-image-dropzone {
background: rgba(116, 183, 255, 0.8);
transition: background .2s;
}
.quickedit-image-icon {
margin: 0 0 10px 0;
transition: margin .5s;
}
.quickedit-image-dropzone.hover {
background: rgba(116, 183, 255, 0.9);
}
.quickedit-image-dropzone.error {
background: rgba(255, 52, 27, 0.81);
}
.quickedit-image-dropzone.upload .quickedit-image-icon {
background-image: url('../../images/upload.svg');
}
.quickedit-image-dropzone.error .quickedit-image-icon {
background-image: url('../../images/error.svg');
}
.quickedit-image-dropzone.loading .quickedit-image-icon {
margin: -10px 0 20px 0;
}
.quickedit-image-dropzone.loading .quickedit-image-icon::after {
display: block;
content: "";
margin-left: -10px;
margin-top: -5px;
animation-duration: 2s;
animation-name: quickedit-image-spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 60px;
height: 60px;
border-style: solid;
border-radius: 35px;
border-width: 5px;
border-color: white transparent transparent transparent;
}
@keyframes quickedit-image-spin {
0% {transform: rotate(0deg);}
50% {transform: rotate(180deg);}
100% {transform: rotate(360deg);}
}
.quickedit-image-text {
text-align: center;
color: white;
font-family: "Droid sans", "Lucida Grande", sans-serif;
font-size: 16px;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.quickedit-image-field-info {
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid #c5c5c5;
padding: 5px;
}
.quickedit-image-field-info div {
margin-right: 10px; /* LTR */
}
.quickedit-image-field-info div:last-child {
margin-right: 0; /* LTR */
}
[dir="rtl"] .quickedit-image-field-info div {
margin-left: 10px;
margin-right: 0;
}
[dir="rtl"] .quickedit-image-field-info div:last-child {
margin-left: 0;
}
.quickedit-image-errors .messages__wrapper {
margin: 0;
padding: 0;
}
.quickedit-image-errors .messages--error {
box-shadow: none;
}

View file

@ -33,11 +33,11 @@ function template_preprocess_image_style_preview(&$variables) {
// Set up original file information.
$original_path = \Drupal::config('image.settings')->get('preview_image');
$original_image = $image_factory->get($original_path);
$variables['original'] = array(
$variables['original'] = [
'url' => file_url_transform_relative(file_create_url($original_path)),
'width' => $original_image->getWidth(),
'height' => $original_image->getHeight(),
);
];
if ($variables['original']['width'] > $variables['original']['height']) {
$variables['preview']['original']['width'] = min($variables['original']['width'], $sample_width);
$variables['preview']['original']['height'] = round($variables['preview']['original']['width'] / $variables['original']['width'] * $variables['original']['height']);
@ -54,11 +54,11 @@ function template_preprocess_image_style_preview(&$variables) {
$style->createDerivative($original_path, $preview_file);
}
$preview_image = $image_factory->get($preview_file);
$variables['derivative'] = array(
$variables['derivative'] = [
'url' => file_url_transform_relative(file_create_url($preview_file)),
'width' => $preview_image->getWidth(),
'height' => $preview_image->getHeight(),
);
];
if ($variables['derivative']['width'] > $variables['derivative']['height']) {
$variables['preview']['derivative']['width'] = min($variables['derivative']['width'], $sample_width);
$variables['preview']['derivative']['height'] = round($variables['preview']['derivative']['width'] / $variables['derivative']['width'] * $variables['derivative']['height']);
@ -69,31 +69,31 @@ function template_preprocess_image_style_preview(&$variables) {
}
// Build the preview of the original image.
$variables['original']['rendered'] = array(
$variables['original']['rendered'] = [
'#theme' => 'image',
'#uri' => $original_path,
'#alt' => t('Sample original image'),
'#title' => '',
'#attributes' => array(
'#attributes' => [
'width' => $variables['original']['width'],
'height' => $variables['original']['height'],
'style' => 'width: ' . $variables['preview']['original']['width'] . 'px; height: ' . $variables['preview']['original']['height'] . 'px;',
),
);
],
];
// Build the preview of the image style derivative. Timestamps are added
// to prevent caching of images on the client side.
$variables['derivative']['rendered'] = array(
$variables['derivative']['rendered'] = [
'#theme' => 'image',
'#uri' => $variables['derivative']['url'] . '?cache_bypass=' . $variables['cache_bypass'],
'#alt' => t('Sample modified image'),
'#title' => '',
'#attributes' => array(
'#attributes' => [
'width' => $variables['derivative']['width'],
'height' => $variables['derivative']['height'],
'style' => 'width: ' . $variables['preview']['derivative']['width'] . 'px; height: ' . $variables['preview']['derivative']['height'] . 'px;',
),
);
],
];
}
@ -109,26 +109,26 @@ function template_preprocess_image_style_preview(&$variables) {
function template_preprocess_image_anchor(&$variables) {
$element = $variables['element'];
$rows = array();
$row = array();
$rows = [];
$row = [];
foreach (Element::children($element) as $n => $key) {
$element[$key]['#attributes']['title'] = $element[$key]['#title'];
unset($element[$key]['#title']);
$row[] = array(
$row[] = [
'data' => $element[$key],
);
];
if ($n % 3 == 3 - 1) {
$rows[] = $row;
$row = array();
$row = [];
}
}
$variables['table'] = array(
$variables['table'] = [
'#type' => 'table',
'#header' => array(),
'#header' => [],
'#rows' => $rows,
'#attributes' => array(
'class' => array('image-anchor'),
),
);
'#attributes' => [
'class' => ['image-anchor'],
],
];
}

View file

@ -20,14 +20,14 @@ use Drupal\Core\Render\Element;
function template_preprocess_image_widget(&$variables) {
$element = $variables['element'];
$variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
$variables['attributes'] = ['class' => ['image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix']];
if (!empty($element['fids']['#value'])) {
$file = reset($element['#files']);
$element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
}
$variables['data'] = array();
$variables['data'] = [];
foreach (Element::children($element) as $child) {
$variables['data'][$child] = $element[$child];
}
@ -49,15 +49,15 @@ function template_preprocess_image_widget(&$variables) {
*/
function template_preprocess_image_formatter(&$variables) {
if ($variables['image_style']) {
$variables['image'] = array(
$variables['image'] = [
'#theme' => 'image_style',
'#style_name' => $variables['image_style'],
);
];
}
else {
$variables['image'] = array(
$variables['image'] = [
'#theme' => 'image',
);
];
}
$variables['image']['#attributes'] = $variables['item_attributes'];
@ -75,7 +75,7 @@ function template_preprocess_image_formatter(&$variables) {
$variables['image']['#uri'] = $item->uri;
}
foreach (array('width', 'height', 'alt') as $key) {
foreach (['width', 'height', 'alt'] as $key) {
$variables['image']["#$key"] = $item->$key;
}
}

View file

@ -29,19 +29,19 @@ function image_uninstall() {
*/
function image_requirements($phase) {
if ($phase != 'runtime') {
return array();
return [];
}
$toolkit = \Drupal::service('image.toolkit.manager')->getDefaultToolkit();
if ($toolkit) {
$plugin_definition = $toolkit->getPluginDefinition();
$requirements = array(
'image.toolkit' => array(
$requirements = [
'image.toolkit' => [
'title' => t('Image toolkit'),
'value' => $toolkit->getPluginId(),
'description' => $plugin_definition['title'],
),
);
],
];
foreach ($toolkit->getRequirements() as $key => $requirement) {
$namespaced_key = 'image.toolkit.' . $toolkit->getPluginId() . '.' . $key;
@ -49,15 +49,22 @@ function image_requirements($phase) {
}
}
else {
$requirements = array(
'image.toolkit' => array(
$requirements = [
'image.toolkit' => [
'title' => t('Image toolkit'),
'value' => t('None'),
'description' => t("No image toolkit is configured on the site. Check PHP installed extensions or add a contributed toolkit that doesn't require a PHP extension. Make sure that at least one valid image toolkit is enabled."),
'severity' => REQUIREMENT_ERROR,
),
);
],
];
}
return $requirements;
}
/**
* Flush caches as we changed field formatter metadata.
*/
function image_update_8201() {
// Empty update to trigger a cache flush.
}

View file

@ -3,3 +3,19 @@ admin:
css:
theme:
css/image.admin.css: {}
quickedit.inPlaceEditor.image:
version: VERSION
js:
js/editors/image.js: {}
js/theme.js: {}
css:
component:
css/editors/image.css: {}
theme:
css/editors/image.theme.css: {}
dependencies:
- core/jquery
- core/drupal
- core/underscore
- quickedit/quickedit

View file

@ -52,29 +52,26 @@ define('IMAGE_STORAGE_MODULE', IMAGE_STORAGE_OVERRIDE | IMAGE_STORAGE_DEFAULT);
*/
define('IMAGE_DERIVATIVE_TOKEN', 'itok');
// Load all Field module hooks for Image.
require_once __DIR__ . '/image.field.inc';
/**
* Implements hook_help().
*/
function image_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.image':
$field_ui_url = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', array('name' => 'field_ui')) : '#';
$field_ui_url = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#';
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Image module allows you to create fields that contain image files and to configure <a href=":image_styles">Image styles</a> that can be used to manipulate the display of images. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for terminology and general information on entities, fields, and how to create and manage fields. For more information, see the <a href=":image_documentation">online documentation for the Image module</a>.', array(':image_styles' => \Drupal::url('entity.image_style.collection'), ':field' => \Drupal::url('help.page', array('name' => 'field')), ':field_ui' => $field_ui_url, ':image_documentation' => 'https://www.drupal.org/documentation/modules/image')) . '</p>';
$output .= '<p>' . t('The Image module allows you to create fields that contain image files and to configure <a href=":image_styles">Image styles</a> that can be used to manipulate the display of images. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for terminology and general information on entities, fields, and how to create and manage fields. For more information, see the <a href=":image_documentation">online documentation for the Image module</a>.', [':image_styles' => \Drupal::url('entity.image_style.collection'), ':field' => \Drupal::url('help.page', ['name' => 'field']), ':field_ui' => $field_ui_url, ':image_documentation' => 'https://www.drupal.org/documentation/modules/image']) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dt>' . t('Defining image styles') . '</dt>';
$output .= '<dd>' . t('The concept of image styles is that you can upload a single image but display it in several ways; each display variation, or <em>image style</em>, is the result of applying one or more <em>effects</em> to the original image. As an example, you might upload a high-resolution image with a 4:3 aspect ratio, and display it scaled down, square cropped, or black-and-white (or any combination of these effects). The Image module provides a way to do this efficiently: you configure an image style with the desired effects on the <a href=":image">Image styles page</a>, and the first time a particular image is requested in that style, the effects are applied. The resulting image is saved, and the next time that same style is requested, the saved image is retrieved without the need to recalculate the effects. Drupal core provides several effects that you can use to define styles; others may be provided by contributed modules.', array(':image' => \Drupal::url('entity.image_style.collection')));
$output .= '<dd>' . t('The concept of image styles is that you can upload a single image but display it in several ways; each display variation, or <em>image style</em>, is the result of applying one or more <em>effects</em> to the original image. As an example, you might upload a high-resolution image with a 4:3 aspect ratio, and display it scaled down, square cropped, or black-and-white (or any combination of these effects). The Image module provides a way to do this efficiently: you configure an image style with the desired effects on the <a href=":image">Image styles page</a>, and the first time a particular image is requested in that style, the effects are applied. The resulting image is saved, and the next time that same style is requested, the saved image is retrieved without the need to recalculate the effects. Drupal core provides several effects that you can use to define styles; others may be provided by contributed modules.', [':image' => \Drupal::url('entity.image_style.collection')]);
$output .= '<dt>' . t('Naming image styles') . '</dt>';
$output .= '<dd>' . t('When you define an image style, you will need to choose a displayed name and a machine name. The displayed name is shown in administrative pages, and the machine name is used to generate the URL for accessing an image processed in that style. There are two common approaches to naming image styles: either based on the effects being applied (for example, <em>Square 85x85</em>), or based on where you plan to use it (for example, <em>Profile picture</em>).') . '</dd>';
$output .= '<dt>' . t('Configuring image fields') . '</dt>';
$output .= '<dd>' . t('A few of the settings for image fields are defined once when you create the field and cannot be changed later; these include the choice of public or private file storage and the number of images that can be stored in the field. The rest of the settings can be edited later; these settings include the field label, help text, allowed file extensions, image resolution restrictions, and the subdirectory in the public or private file storage where the images will be stored. The editable settings can also have different values for different entity sub-types; for instance, if your image field is used on both Page and Article content types, you can store the files in a different subdirectory for the two content types.') . '</dd>';
$output .= '<dd>' . t('For accessibility and search engine optimization, all images that convey meaning on web sites should have alternate text. Drupal also allows entry of title text for images, but it can lead to confusion for screen reader users and its use is not recommended. Image fields can be configured so that alternate and title text fields are enabled or disabled; if enabled, the fields can be set to be required. The recommended setting is to enable and require alternate text and disable title text.') . '</dd>';
$output .= '<dd>' . t('When you create an image field, you will need to choose whether the uploaded images will be stored in the public or private file directory defined in your settings.php file and shown on the <a href=":file-system">File system page</a>. This choice cannot be changed later. You can also configure your field to store files in a subdirectory of the public or private directory; this setting can be changed later and can be different for each entity sub-type using the field. For more information on file storage, see the <a href=":system-help">System module help page</a>.', array(':file-system' => \Drupal::url('system.file_system_settings'), ':system-help' => \Drupal::url('help.page', array('name' => 'system')))) . '</dd>';
$output .= '<dd>' . t('When you create an image field, you will need to choose whether the uploaded images will be stored in the public or private file directory defined in your settings.php file and shown on the <a href=":file-system">File system page</a>. This choice cannot be changed later. You can also configure your field to store files in a subdirectory of the public or private directory; this setting can be changed later and can be different for each entity sub-type using the field. For more information on file storage, see the <a href=":system-help">System module help page</a>.', [':file-system' => \Drupal::url('system.file_system_settings'), ':system-help' => \Drupal::url('help.page', ['name' => 'system'])]) . '</dd>';
$output .= '<dd>' . t('The maximum file size that can be uploaded is limited by PHP settings of the server, but you can restrict it further by configuring a <em>Maximum upload size</em> in the field settings (this setting can be changed later). The maximum file size, either from PHP server settings or field configuration, is automatically displayed to users in the help text of the image field.') . '</dd>';
$output .= '<dd>' . t('You can also configure a minimum and/or maximum resolution for uploaded images. Images that are too small will be rejected. Images that are to large will be resized. During the resizing the <a href="http://wikipedia.org/wiki/Exchangeable_image_file_format">EXIF data</a> in the image will be lost.') . '</dd>';
$output .= '<dd>' . t('You can also configure a default image that will be used if no image is uploaded in an image field. This default can be defined for all instances of the field in the field storage settings when you create a field, and the setting can be overridden for each entity sub-type that uses the field.') . '</dd>';
@ -101,9 +98,9 @@ function image_help($route_name, RouteMatchInterface $route_match) {
* Implements hook_theme().
*/
function image_theme() {
return array(
return [
// Theme functions in image.module.
'image_style' => array(
'image_style' => [
// HTML 4 and XHTML 1.0 always require an alt attribute. The HTML 5 draft
// allows the alt attribute to be omitted in some cases. Therefore,
// default the alt attribute to an empty string, but allow code using
@ -116,49 +113,49 @@ function image_theme() {
// - http://dev.w3.org/html5/spec/Overview.html#alt
// The title attribute is optional in all cases, so it is omitted by
// default.
'variables' => array(
'variables' => [
'style_name' => NULL,
'uri' => NULL,
'width' => NULL,
'height' => NULL,
'alt' => '',
'title' => NULL,
'attributes' => array(),
),
),
'attributes' => [],
],
],
// Theme functions in image.admin.inc.
'image_style_preview' => array(
'variables' => array('style' => NULL),
'image_style_preview' => [
'variables' => ['style' => NULL],
'file' => 'image.admin.inc',
),
'image_anchor' => array(
],
'image_anchor' => [
'render element' => 'element',
'file' => 'image.admin.inc',
),
'image_resize_summary' => array(
'variables' => array('data' => NULL, 'effect' => array()),
),
'image_scale_summary' => array(
'variables' => array('data' => NULL, 'effect' => array()),
),
'image_crop_summary' => array(
'variables' => array('data' => NULL, 'effect' => array()),
),
'image_rotate_summary' => array(
'variables' => array('data' => NULL, 'effect' => array()),
),
],
'image_resize_summary' => [
'variables' => ['data' => NULL, 'effect' => []],
],
'image_scale_summary' => [
'variables' => ['data' => NULL, 'effect' => []],
],
'image_crop_summary' => [
'variables' => ['data' => NULL, 'effect' => []],
],
'image_rotate_summary' => [
'variables' => ['data' => NULL, 'effect' => []],
],
// Theme functions in image.field.inc.
'image_widget' => array(
'image_widget' => [
'render element' => 'element',
'file' => 'image.field.inc',
),
'image_formatter' => array(
'variables' => array('item' => NULL, 'item_attributes' => NULL, 'url' => NULL, 'image_style' => NULL),
],
'image_formatter' => [
'variables' => ['item' => NULL, 'item_attributes' => NULL, 'url' => NULL, 'image_style' => NULL],
'file' => 'image.field.inc',
),
);
],
];
}
/**
@ -183,17 +180,17 @@ function image_file_download($uri) {
$image = \Drupal::service('image.factory')->get($uri);
if ($image->isValid()) {
// Check the permissions of the original to grant access to this image.
$headers = \Drupal::moduleHandler()->invokeAll('file_download', array($original_uri));
$headers = \Drupal::moduleHandler()->invokeAll('file_download', [$original_uri]);
// Confirm there's at least one module granting access and none denying access.
if (!empty($headers) && !in_array(-1, $headers)) {
return array(
return [
// Send headers describing the image's size, and MIME-type.
'Content-Type' => $image->getMimeType(),
'Content-Length' => $image->getFileSize(),
// By not explicitly setting them here, this uses normal Drupal
// Expires, Cache-Control and ETag headers to prevent proxy or
// browser caching of private images.
);
];
}
}
return -1;
@ -239,7 +236,7 @@ function image_path_flush($path) {
*/
function image_style_options($include_empty = TRUE) {
$styles = ImageStyle::loadMultiple();
$options = array();
$options = [];
if ($include_empty && !empty($styles)) {
$options[''] = t('- None -');
}
@ -283,21 +280,21 @@ function template_preprocess_image_style(&$variables) {
$style = ImageStyle::load($variables['style_name']);
// Determine the dimensions of the styled image.
$dimensions = array(
$dimensions = [
'width' => $variables['width'],
'height' => $variables['height'],
);
];
$style->transformDimensions($dimensions, $variables['uri']);
$variables['image'] = array(
$variables['image'] = [
'#theme' => 'image',
'#width' => $dimensions['width'],
'#height' => $dimensions['height'],
'#attributes' => $variables['attributes'],
'#uri' => $style->buildUrl($variables['uri']),
'#style_name' => $variables['style_name'],
);
];
if (isset($variables['alt']) || array_key_exists('alt', $variables)) {
$variables['image']['#alt'] = $variables['alt'];

View file

@ -71,3 +71,29 @@ image.effect_edit_form:
route_callbacks:
- '\Drupal\image\Routing\ImageStyleRoutes::routes'
image.upload:
path: '/quickedit/image/upload/{entity_type}/{entity}/{field_name}/{langcode}/{view_mode_id}'
defaults:
_controller: '\Drupal\image\Controller\QuickEditImageController::upload'
options:
parameters:
entity:
type: entity:{entity_type}
requirements:
_permission: 'access in-place editing'
_access_quickedit_entity_field: 'TRUE'
_method: 'POST'
image.info:
path: '/quickedit/image/info/{entity_type}/{entity}/{field_name}/{langcode}/{view_mode_id}'
defaults:
_controller: '\Drupal\image\Controller\QuickEditImageController::getInfo'
options:
parameters:
entity:
type: entity:{entity_type}
requirements:
_permission: 'access in-place editing'
_access_quickedit_entity_field: 'TRUE'
_method: 'GET'

View file

@ -19,13 +19,13 @@ function image_field_views_data(FieldStorageConfigInterface $field_storage) {
$data = views_field_default_views_data($field_storage);
foreach ($data as $table_name => $table_data) {
// Add the relationship only on the target_id field.
$data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = array(
$data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = [
'id' => 'standard',
'base' => 'file_managed',
'entity type' => 'file',
'base field' => 'fid',
'label' => t('image from @field_name', array('@field_name' => $field_storage->getName())),
);
'label' => t('image from @field_name', ['@field_name' => $field_storage->getName()]),
];
}
return $data;
@ -47,10 +47,10 @@ function image_field_views_data_views_data_alter(array &$data, FieldStorageConfi
list($label) = views_entity_field_label($entity_type_id, $field_name);
$data['file_managed'][$pseudo_field_name]['relationship'] = array(
'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
'label' => t('@field_name', array('@field_name' => $field_name)),
'help' => t('Relate each @entity with a @field set to the image.', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
$data['file_managed'][$pseudo_field_name]['relationship'] = [
'title' => t('@entity using @field', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
'label' => t('@field_name', ['@field_name' => $field_name]),
'help' => t('Relate each @entity with a @field set to the image.', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
'group' => $entity_type->getLabel(),
'id' => 'entity_reverse',
'base' => $entity_type->getDataTable() ?: $entity_type->getBaseTable(),
@ -59,12 +59,12 @@ function image_field_views_data_views_data_alter(array &$data, FieldStorageConfi
'field_name' => $field_name,
'field table' => $table_mapping->getDedicatedDataTableName($field_storage),
'field field' => $field_name . '_target_id',
'join_extra' => array(
0 => array(
'join_extra' => [
0 => [
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
),
),
);
],
],
];
}

View file

@ -0,0 +1,4 @@
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View file

@ -0,0 +1,4 @@
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
</svg>

After

Width:  |  Height:  |  Size: 202 B

View file

@ -0,0 +1,342 @@
/**
* @file
* Drag+drop based in-place editor for images.
*/
(function ($, _, Drupal) {
'use strict';
Drupal.quickedit.editors.image = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.image# */{
/**
* @constructs
*
* @augments Drupal.quickedit.EditorView
*
* @param {object} options
* Options for the image editor.
*/
initialize: function (options) {
Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
// Set our original value to our current HTML (for reverting).
this.model.set('originalValue', this.$el.html().trim());
// $.val() callback function for copying input from our custom form to
// the Quick Edit Field Form.
this.model.set('currentValue', function (index, value) {
var matches = $(this).attr('name').match(/(alt|title)]$/);
if (matches) {
var name = matches[1];
var $toolgroup = $('#' + options.fieldModel.toolbarView.getMainWysiwygToolgroupId());
var $input = $toolgroup.find('.quickedit-image-field-info input[name="' + name + '"]');
if ($input.length) {
return $input.val();
}
}
});
},
/**
* @inheritdoc
*
* @param {Drupal.quickedit.FieldModel} fieldModel
* The field model that holds the state.
* @param {string} state
* The state to change to.
* @param {object} options
* State options, if needed by the state change.
*/
stateChange: function (fieldModel, state, options) {
var from = fieldModel.previous('state');
switch (state) {
case 'inactive':
break;
case 'candidate':
if (from !== 'inactive') {
this.$el.find('.quickedit-image-dropzone').remove();
this.$el.removeClass('quickedit-image-element');
}
if (from === 'invalid') {
this.removeValidationErrors();
}
break;
case 'highlighted':
break;
case 'activating':
// Defer updating the field model until the current state change has
// propagated, to not trigger a nested state change event.
_.defer(function () {
fieldModel.set('state', 'active');
});
break;
case 'active':
var self = this;
// Indicate that this element is being edited by Quick Edit Image.
this.$el.addClass('quickedit-image-element');
// Render our initial dropzone element. Once the user reverts changes
// or saves a new image, this element is removed.
var $dropzone = this.renderDropzone('upload', Drupal.t('Drop file here or click to upload'));
$dropzone.on('dragenter', function (e) {
$(this).addClass('hover');
});
$dropzone.on('dragleave', function (e) {
$(this).removeClass('hover');
});
$dropzone.on('drop', function (e) {
// Only respond when a file is dropped (could be another element).
if (e.originalEvent.dataTransfer && e.originalEvent.dataTransfer.files.length) {
$(this).removeClass('hover');
self.uploadImage(e.originalEvent.dataTransfer.files[0]);
}
});
$dropzone.on('click', function (e) {
// Create an <input> element without appending it to the DOM, and
// trigger a click event. This is the easiest way to arbitrarily
// open the browser's upload dialog.
$('<input type="file">')
.trigger('click')
.on('change', function () {
if (this.files.length) {
self.uploadImage(this.files[0]);
}
});
});
// Prevent the browser's default behavior when dragging files onto
// the document (usually opens them in the same tab).
$dropzone.on('dragover dragenter dragleave drop click', function (e) {
e.preventDefault();
e.stopPropagation();
});
this.renderToolbar(fieldModel);
break;
case 'changed':
break;
case 'saving':
if (from === 'invalid') {
this.removeValidationErrors();
}
this.save(options);
break;
case 'saved':
break;
case 'invalid':
this.showValidationErrors();
break;
}
},
/**
* Validates/uploads a given file.
*
* @param {File} file
* The file to upload.
*/
uploadImage: function (file) {
// Indicate loading by adding a special class to our icon.
this.renderDropzone('upload loading', Drupal.t('Uploading <i>@file</i>…', {'@file': file.name}));
// Build a valid URL for our endpoint.
var fieldID = this.fieldModel.get('fieldID');
var url = Drupal.quickedit.util.buildUrl(fieldID, Drupal.url('quickedit/image/upload/!entity_type/!id/!field_name/!langcode/!view_mode'));
// Construct form data that our endpoint can consume.
var data = new FormData();
data.append('files[image]', file);
// Construct a POST request to our endpoint.
var self = this;
this.ajax({
type: 'POST',
url: url,
data: data,
success: function (response) {
var $el = $(self.fieldModel.get('el'));
// Indicate that the field has changed - this enables the
// "Save" button.
self.fieldModel.set('state', 'changed');
self.fieldModel.get('entity').set('inTempStore', true);
self.removeValidationErrors();
// Replace our html with the new image. If we replaced our entire
// element with data.html, we would have to implement complicated logic
// like what's in Drupal.quickedit.AppView.renderUpdatedField.
var $content = $(response.html).closest('[data-quickedit-field-id]').children();
$el.empty().append($content);
}
});
},
/**
* Utility function to make an AJAX request to the server.
*
* In addition to formatting the correct request, this also handles error
* codes and messages by displaying them visually inline with the image.
*
* Drupal.ajax is not called here as the Form API is unused by this
* in-place editor, and our JSON requests/responses try to be
* editor-agnostic. Ideally similar logic and routes could be used by
* modules like CKEditor for drag+drop file uploads as well.
*
* @param {object} options
* Ajax options.
* @param {string} options.type
* The type of request (i.e. GET, POST, PUT, DELETE, etc.)
* @param {string} options.url
* The URL for the request.
* @param {*} options.data
* The data to send to the server.
* @param {function} options.success
* A callback function used when a request is successful, without errors.
*/
ajax: function (options) {
var defaultOptions = {
context: this,
dataType: 'json',
cache: false,
contentType: false,
processData: false,
error: function () {
this.renderDropzone('error', Drupal.t('A server error has occurred.'));
}
};
var ajaxOptions = $.extend(defaultOptions, options);
var successCallback = ajaxOptions.success;
// Handle the success callback.
ajaxOptions.success = function (response) {
if (response.main_error) {
this.renderDropzone('error', response.main_error);
if (response.errors.length) {
this.model.set('validationErrors', response.errors);
}
this.showValidationErrors();
}
else {
successCallback(response);
}
};
$.ajax(ajaxOptions);
},
/**
* Renders our toolbar form for editing metadata.
*
* @param {Drupal.quickedit.FieldModel} fieldModel
* The current Field Model.
*/
renderToolbar: function (fieldModel) {
var $toolgroup = $('#' + fieldModel.toolbarView.getMainWysiwygToolgroupId());
var $toolbar = $toolgroup.find('.quickedit-image-field-info');
if ($toolbar.length === 0) {
// Perform an AJAX request for extra image info (alt/title).
var fieldID = fieldModel.get('fieldID');
var url = Drupal.quickedit.util.buildUrl(fieldID, Drupal.url('quickedit/image/info/!entity_type/!id/!field_name/!langcode/!view_mode'));
var self = this;
self.ajax({
type: 'GET',
url: url,
success: function (response) {
$toolbar = $(Drupal.theme.quickeditImageToolbar(response));
$toolgroup.append($toolbar);
$toolbar.on('keyup paste', function () {
fieldModel.set('state', 'changed');
});
// Re-position the toolbar, which could have changed size.
fieldModel.get('entity').toolbarView.position();
}
});
}
},
/**
* Renders our dropzone element.
*
* @param {string} state
* The current state of our editor. Only used for visual styling.
* @param {string} text
* The text to display in the dropzone area.
*
* @return {jQuery}
* The rendered dropzone.
*/
renderDropzone: function (state, text) {
var $dropzone = this.$el.find('.quickedit-image-dropzone');
// If the element already exists, modify its contents.
if ($dropzone.length) {
$dropzone
.removeClass('upload error hover loading')
.addClass('.quickedit-image-dropzone ' + state)
.children('.quickedit-image-text')
.html(text);
}
else {
$dropzone = $(Drupal.theme('quickeditImageDropzone', {
state: state,
text: text
}));
this.$el.append($dropzone);
}
return $dropzone;
},
/**
* @inheritdoc
*/
revert: function () {
this.$el.html(this.model.get('originalValue'));
},
/**
* @inheritdoc
*/
getQuickEditUISettings: function () {
return {padding: false, unifiedToolbar: true, fullWidthToolbar: true, popup: false};
},
/**
* @inheritdoc
*/
showValidationErrors: function () {
var errors = Drupal.theme('quickeditImageErrors', {
errors: this.model.get('validationErrors')
});
$('#' + this.fieldModel.toolbarView.getMainWysiwygToolgroupId())
.append(errors);
this.getEditedElement()
.addClass('quickedit-validation-error');
// Re-position the toolbar, which could have changed size.
this.fieldModel.get('entity').toolbarView.position();
},
/**
* @inheritdoc
*/
removeValidationErrors: function () {
$('#' + this.fieldModel.toolbarView.getMainWysiwygToolgroupId())
.find('.quickedit-image-errors').remove();
this.getEditedElement()
.removeClass('quickedit-validation-error');
}
});
})(jQuery, _, Drupal);

View file

@ -0,0 +1,86 @@
/**
* @file
* Provides theme functions for image Quick Edit's client-side HTML.
*/
(function (Drupal) {
'use strict';
/**
* Theme function for validation errors of the Image in-place editor.
*
* @param {object} settings
* Settings object used to construct the markup.
* @param {string} settings.errors
* Already escaped HTML representing error messages.
*
* @return {string}
* The corresponding HTML.
*/
Drupal.theme.quickeditImageErrors = function (settings) {
return '<div class="quickedit-image-errors">' + settings.errors + '</div>';
};
/**
* Theme function for the dropzone element of the Image module's in-place
* editor.
*
* @param {object} settings
* Settings object used to construct the markup.
* @param {string} settings.state
* State of the upload.
* @param {string} settings.text
* Text to display inline with the dropzone element.
*
* @return {string}
* The corresponding HTML.
*/
Drupal.theme.quickeditImageDropzone = function (settings) {
return '<div class="quickedit-image-dropzone ' + settings.state + '">' +
' <i class="quickedit-image-icon"></i>' +
' <span class="quickedit-image-text">' + settings.text + '</span>' +
'</div>';
};
/**
* Theme function for the toolbar of the Image module's in-place editor.
*
* @param {object} settings
* Settings object used to construct the markup.
* @param {bool} settings.alt_field
* Whether or not the "Alt" field is enabled for this field.
* @param {bool} settings.alt_field_required
* Whether or not the "Alt" field is required for this field.
* @param {string} settings.alt
* The current value for the "Alt" field.
* @param {bool} settings.title_field
* Whether or not the "Title" field is enabled for this field.
* @param {bool} settings.title_field_required
* Whether or not the "Title" field is required for this field.
* @param {string} settings.title
* The current value for the "Title" field.
*
* @return {string}
* The corresponding HTML.
*/
Drupal.theme.quickeditImageToolbar = function (settings) {
var html = '<form class="quickedit-image-field-info">';
if (settings.alt_field) {
html += ' <div>' +
' <label for="alt" class="' + (settings.alt_field_required ? 'required' : '') + '">' + Drupal.t('Alternative text') + '</label>' +
' <input type="text" placeholder="' + settings.alt + '" value="' + settings.alt + '" name="alt" ' + (settings.alt_field_required ? 'required' : '') + '/>' +
' </div>';
}
if (settings.title_field) {
html += ' <div>' +
' <label for="title" class="' + (settings.title_field_required ? 'form-required' : '') + '">' + Drupal.t('Title') + '</label>' +
' <input type="text" placeholder="' + settings.title + '" value="' + settings.title + '" name="title" ' + (settings.title_field_required ? 'required' : '') + '/>' +
' </div>';
}
html += '</form>';
return html;
};
})(Drupal);

View file

@ -108,12 +108,12 @@ class ImageStyleDownloadController extends FileDownloadController {
}
$derivative_uri = $image_style->buildUri($image_uri);
$headers = array();
$headers = [];
// If using the private scheme, let other modules provide headers and
// control access to the file.
if ($scheme == 'private') {
$headers = $this->moduleHandler()->invokeAll('file_download', array($image_uri));
$headers = $this->moduleHandler()->invokeAll('file_download', [$image_uri]);
if (in_array(-1, $headers) || empty($headers)) {
throw new AccessDeniedHttpException();
}
@ -128,7 +128,7 @@ class ImageStyleDownloadController extends FileDownloadController {
$path_info = pathinfo($image_uri);
$converted_image_uri = $path_info['dirname'] . DIRECTORY_SEPARATOR . $path_info['filename'];
if (!file_exists($converted_image_uri)) {
$this->logger->notice('Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri));
$this->logger->notice('Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', ['%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri]);
return new Response($this->t('Error generating image, missing source file.'), 404);
}
else {
@ -160,10 +160,10 @@ class ImageStyleDownloadController extends FileDownloadController {
if ($success) {
$image = $this->imageFactory->get($derivative_uri);
$uri = $image->getSource();
$headers += array(
$headers += [
'Content-Type' => $image->getMimeType(),
'Content-Length' => $image->getFileSize(),
);
];
// \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
// sets response as not cacheable if the Cache-Control header is not
// already modified. We pass in FALSE for non-private schemes for the
@ -171,7 +171,7 @@ class ImageStyleDownloadController extends FileDownloadController {
return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
}
else {
$this->logger->notice('Unable to generate the derived image located at %path.', array('%path' => $derivative_uri));
$this->logger->notice('Unable to generate the derived image located at %path.', ['%path' => $derivative_uri]);
return new Response($this->t('Error generating image.'), 500);
}
}

View file

@ -0,0 +1,225 @@
<?php
namespace Drupal\image\Controller;
use Drupal\Core\Cache\CacheableJsonResponse;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Render\Element\StatusMessages;
use Drupal\Core\Render\RendererInterface;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\user\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* Returns responses for our image routes.
*/
class QuickEditImageController extends ControllerBase {
/**
* Stores The Quick Edit tempstore.
*
* @var \Drupal\user\PrivateTempStore
*/
protected $tempStore;
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The image factory.
*
* @var \Drupal\Core\Image\ImageFactory
*/
protected $imageFactory;
/**
* Constructs a new QuickEditImageController.
*
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Image\ImageFactory $image_factory
* The image factory.
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
*/
public function __construct(RendererInterface $renderer, ImageFactory $image_factory, PrivateTempStoreFactory $temp_store_factory) {
$this->renderer = $renderer;
$this->imageFactory = $image_factory;
$this->tempStore = $temp_store_factory->get('quickedit');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('renderer'),
$container->get('image.factory'),
$container->get('user.private_tempstore')
);
}
/**
* Returns JSON representing the new file upload, or validation errors.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity of which an image field is being rendered.
* @param string $field_name
* The name of the (image) field that is being rendered
* @param string $langcode
* The language code of the field that is being rendered.
* @param string $view_mode_id
* The view mode of the field that is being rendered.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* The JSON response.
*/
public function upload(EntityInterface $entity, $field_name, $langcode, $view_mode_id) {
$field = $this->getField($entity, $field_name, $langcode);
$field_validators = $field->getUploadValidators();
$field_settings = $field->getFieldDefinition()->getSettings();
$destination = $field->getUploadLocation();
// Add upload resolution validation.
if ($field_settings['max_resolution'] || $field_settings['min_resolution']) {
$field_validators['file_validate_image_resolution'] = [$field_settings['max_resolution'], $field_settings['min_resolution']];
}
// Create the destination directory if it does not already exist.
if (isset($destination) && !file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
return new JsonResponse(['main_error' => $this->t('The destination directory could not be created.'), 'errors' => '']);
}
// Attempt to save the image given the field's constraints.
$result = file_save_upload('image', $field_validators, $destination);
if (is_array($result) && $result[0]) {
/** @var \Drupal\file\Entity\File $file */
$file = $result[0];
$image = $this->imageFactory->get($file->getFileUri());
// Set the value in the Entity to the new file.
/** @var \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $field_list */
$value = $entity->$field_name->getValue();
$value[0]['target_id'] = $file->id();
$value[0]['width'] = $image->getWidth();
$value[0]['height'] = $image->getHeight();
$entity->$field_name->setValue($value);
// Render the new image using the correct formatter settings.
$entity_view_mode_ids = array_keys($this->entityManager()->getViewModes($entity->getEntityTypeId()));
if (in_array($view_mode_id, $entity_view_mode_ids, TRUE)) {
$output = $entity->$field_name->view($view_mode_id);
}
else {
// Each part of a custom (non-Entity Display) view mode ID is separated
// by a dash; the first part must be the module name.
$mode_id_parts = explode('-', $view_mode_id, 2);
$module = reset($mode_id_parts);
$args = [$entity, $field_name, $view_mode_id, $langcode];
$output = $this->moduleHandler()->invoke($module, 'quickedit_render_field', $args);
}
// Save the Entity to tempstore.
$this->tempStore->set($entity->uuid(), $entity);
$data = [
'fid' => $file->id(),
'html' => $this->renderer->renderRoot($output),
];
return new JsonResponse($data);
}
else {
// Return a JSON object containing the errors from Drupal and our
// "main_error", which is displayed inside the dropzone area.
$messages = StatusMessages::renderMessages('error');
return new JsonResponse(['errors' => $this->renderer->render($messages), 'main_error' => $this->t('The image failed validation.')]);
}
}
/**
* Returns JSON representing an image field's metadata.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity of which an image field is being rendered.
* @param string $field_name
* The name of the (image) field that is being rendered
* @param string $langcode
* The language code of the field that is being rendered.
* @param string $view_mode_id
* The view mode of the field that is being rendered.
*
* @return \Drupal\Core\Cache\CacheableJsonResponse
* The JSON response.
*/
public function getInfo(EntityInterface $entity, $field_name, $langcode, $view_mode_id) {
$field = $this->getField($entity, $field_name, $langcode);
$settings = $field->getFieldDefinition()->getSettings();
$info = [
'alt' => $field->alt,
'title' => $field->title,
'alt_field' => $settings['alt_field'],
'title_field' => $settings['title_field'],
'alt_field_required' => $settings['alt_field_required'],
'title_field_required' => $settings['title_field_required'],
];
$response = new CacheableJsonResponse($info);
$response->addCacheableDependency($entity);
return $response;
}
/**
* Returns JSON representing the current state of the field.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity of which an image field is being rendered.
* @param string $field_name
* The name of the (image) field that is being rendered
* @param string $langcode
* The language code of the field that is being rendered.
*
* @return \Drupal\image\Plugin\Field\FieldType\ImageItem
* The field for this request.
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
* Throws an exception if the request is invalid.
*/
protected function getField(EntityInterface $entity, $field_name, $langcode) {
// Ensure that this is a valid Entity.
if (!($entity instanceof ContentEntityInterface)) {
throw new BadRequestHttpException('Requested Entity is not a Content Entity.');
}
// Check that this field exists.
/** @var \Drupal\Core\Field\FieldItemListInterface $field_list */
$field_list = $entity->getTranslation($langcode)->get($field_name);
if (!$field_list) {
throw new BadRequestHttpException('Requested Field does not exist.');
}
// If the list is empty, append an empty item to use.
if ($field_list->isEmpty()) {
$field = $field_list->appendItem();
}
// Otherwise, use the first item.
else {
$field = $entity->getTranslation($langcode)->get($field_name)->first();
}
// Ensure that the field is the type we expect.
if (!($field instanceof ImageItem)) {
throw new BadRequestHttpException('Requested Field is not of type "image".');
}
return $field;
}
}

View file

@ -73,7 +73,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
*
* @var array
*/
protected $effects = array();
protected $effects = [];
/**
* Holds the collection of image effects that are used by this image style.
@ -200,11 +200,11 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
// that (if both are set, the security token will neither be emitted in the
// image derivative URL nor checked for in
// \Drupal\image\ImageStyleInterface::deliver()).
$token_query = array();
$token_query = [];
if (!\Drupal::config('image.settings')->get('suppress_itok_output')) {
// The passed $path variable can be either a relative path or a full URI.
$original_uri = file_uri_scheme($path) ? file_stream_wrapper_uri_normalize($path) : file_build_uri($path);
$token_query = array(IMAGE_DERIVATIVE_TOKEN => $this->getPathToken($original_uri));
$token_query = [IMAGE_DERIVATIVE_TOKEN => $this->getPathToken($original_uri)];
}
if ($clean_urls === NULL) {
@ -225,7 +225,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
// built.
if ($clean_urls === FALSE && file_uri_scheme($uri) == 'public' && !file_exists($uri)) {
$directory_path = $this->getStreamWrapperManager()->getViaUri($uri)->getDirectoryPath();
return Url::fromUri('base:' . $directory_path . '/' . file_uri_target($uri), array('absolute' => TRUE, 'query' => $token_query))->toString();
return Url::fromUri('base:' . $directory_path . '/' . file_uri_target($uri), ['absolute' => TRUE, 'query' => $token_query])->toString();
}
$file_url = file_create_url($uri);
@ -260,7 +260,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
// Let other modules update as necessary on flush.
$module_handler = \Drupal::moduleHandler();
$module_handler->invokeAll('image_style_flush', array($this));
$module_handler->invokeAll('image_style_flush', [$this]);
// Clear caches so that formatters may be added for this style.
drupal_theme_rebuild();
@ -286,7 +286,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
// Build the destination folder tree if it doesn't already exist.
if (!file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
\Drupal::logger('image')->error('Failed to create style directory: %directory', array('%directory' => $directory));
\Drupal::logger('image')->error('Failed to create style directory: %directory', ['%directory' => $directory]);
return FALSE;
}
@ -296,7 +296,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
if (!$image->save($derivative_uri)) {
if (file_exists($derivative_uri)) {
\Drupal::logger('image')->error('Cached image file %destination already exists. There may be an issue with your rewrite configuration.', array('%destination' => $derivative_uri));
\Drupal::logger('image')->error('Cached image file %destination already exists. There may be an issue with your rewrite configuration.', ['%destination' => $derivative_uri]);
}
return FALSE;
}
@ -362,7 +362,7 @@ class ImageStyle extends ConfigEntityBase implements ImageStyleInterface, Entity
* {@inheritdoc}
*/
public function getPluginCollections() {
return array('effects' => $this->getEffects());
return ['effects' => $this->getEffects()];
}
/**

View file

@ -44,7 +44,7 @@ class ImageEffectAddForm extends ImageEffectFormBase {
public function buildForm(array $form, FormStateInterface $form_state, ImageStyleInterface $image_style = NULL, $image_effect = NULL) {
$form = parent::buildForm($form, $form_state, $image_style, $image_effect);
$form['#title'] = $this->t('Add %label effect', array('%label' => $this->imageEffect->label()));
$form['#title'] = $this->t('Add %label effect', ['%label' => $this->imageEffect->label()]);
$form['actions']['submit']['#value'] = $this->t('Add effect');
return $form;

View file

@ -29,7 +29,7 @@ class ImageEffectDeleteForm extends ConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to delete the @effect effect from the %style style?', array('%style' => $this->imageStyle->label(), '@effect' => $this->imageEffect->label()));
return $this->t('Are you sure you want to delete the @effect effect from the %style style?', ['%style' => $this->imageStyle->label(), '@effect' => $this->imageEffect->label()]);
}
/**
@ -68,7 +68,7 @@ class ImageEffectDeleteForm extends ConfirmFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->imageStyle->deleteImageEffect($this->imageEffect);
drupal_set_message($this->t('The image effect %name has been deleted.', array('%name' => $this->imageEffect->label())));
drupal_set_message($this->t('The image effect %name has been deleted.', ['%name' => $this->imageEffect->label()]));
$form_state->setRedirectUrl($this->imageStyle->urlInfo('edit-form'));
}

View file

@ -16,7 +16,7 @@ class ImageEffectEditForm extends ImageEffectFormBase {
public function buildForm(array $form, FormStateInterface $form_state, ImageStyleInterface $image_style = NULL, $image_effect = NULL) {
$form = parent::buildForm($form, $form_state, $image_style, $image_effect);
$form['#title'] = $this->t('Edit %label effect', array('%label' => $this->imageEffect->label()));
$form['#title'] = $this->t('Edit %label effect', ['%label' => $this->imageEffect->label()]);
$form['actions']['submit']['#value'] = $this->t('Update effect');
return $form;

View file

@ -64,14 +64,14 @@ abstract class ImageEffectFormBase extends FormBase {
}
$form['#attached']['library'][] = 'image/admin';
$form['uuid'] = array(
$form['uuid'] = [
'#type' => 'value',
'#value' => $this->imageEffect->getUuid(),
);
$form['id'] = array(
];
$form['id'] = [
'#type' => 'value',
'#value' => $this->imageEffect->getPluginId(),
);
];
$form['data'] = [];
$subform_state = SubformState::createForSubform($form['data'], $form, $form_state);
@ -79,22 +79,22 @@ abstract class ImageEffectFormBase extends FormBase {
$form['data']['#tree'] = TRUE;
// Check the URL for a weight, then the image effect, otherwise use default.
$form['weight'] = array(
$form['weight'] = [
'#type' => 'hidden',
'#value' => $request->query->has('weight') ? (int) $request->query->get('weight') : $this->imageEffect->getWeight(),
);
];
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
$form['actions'] = ['#type' => 'actions'];
$form['actions']['submit'] = [
'#type' => 'submit',
'#button_type' => 'primary',
);
$form['actions']['cancel'] = array(
];
$form['actions']['cancel'] = [
'#type' => 'link',
'#title' => $this->t('Cancel'),
'#url' => $this->imageStyle->urlInfo('edit-form'),
'#attributes' => ['class' => ['button']],
);
];
return $form;
}

View file

@ -14,7 +14,7 @@ class ImageStyleAddForm extends ImageStyleFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
drupal_set_message($this->t('Style %name was created.', array('%name' => $this->entity->label())));
drupal_set_message($this->t('Style %name was created.', ['%name' => $this->entity->label()]));
}
/**

View file

@ -21,7 +21,7 @@ class ImageStyleDeleteForm extends EntityDeleteForm {
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Optionally select a style before deleting %style', array('%style' => $this->entity->label()));
return $this->t('Optionally select a style before deleting %style', ['%style' => $this->entity->label()]);
}
/**
* {@inheritdoc}

View file

@ -49,54 +49,54 @@ class ImageStyleEditForm extends ImageStyleFormBase {
*/
public function form(array $form, FormStateInterface $form_state) {
$user_input = $form_state->getUserInput();
$form['#title'] = $this->t('Edit style %name', array('%name' => $this->entity->label()));
$form['#title'] = $this->t('Edit style %name', ['%name' => $this->entity->label()]);
$form['#tree'] = TRUE;
$form['#attached']['library'][] = 'image/admin';
// Show the thumbnail preview.
$preview_arguments = array('#theme' => 'image_style_preview', '#style' => $this->entity);
$form['preview'] = array(
$preview_arguments = ['#theme' => 'image_style_preview', '#style' => $this->entity];
$form['preview'] = [
'#type' => 'item',
'#title' => $this->t('Preview'),
'#markup' => drupal_render($preview_arguments),
// Render preview above parent elements.
'#weight' => -5,
);
];
// Build the list of existing image effects for this image style.
$form['effects'] = array(
$form['effects'] = [
'#type' => 'table',
'#header' => array(
'#header' => [
$this->t('Effect'),
$this->t('Weight'),
$this->t('Operations'),
),
'#tabledrag' => array(
array(
],
'#tabledrag' => [
[
'action' => 'order',
'relationship' => 'sibling',
'group' => 'image-effect-order-weight',
),
),
'#attributes' => array(
],
],
'#attributes' => [
'id' => 'image-style-effects',
),
],
'#empty' => t('There are currently no effects in this style. Add one by selecting an option below.'),
// Render effects below parent elements.
'#weight' => 5,
);
];
foreach ($this->entity->getEffects() as $effect) {
$key = $effect->getUuid();
$form['effects'][$key]['#attributes']['class'][] = 'draggable';
$form['effects'][$key]['#weight'] = isset($user_input['effects']) ? $user_input['effects'][$key]['weight'] : NULL;
$form['effects'][$key]['effect'] = array(
$form['effects'][$key]['effect'] = [
'#tree' => FALSE,
'data' => array(
'label' => array(
'data' => [
'label' => [
'#plain_text' => $effect->label(),
),
),
);
],
],
];
$summary = $effect->getSummary();
@ -105,42 +105,42 @@ class ImageStyleEditForm extends ImageStyleFormBase {
$form['effects'][$key]['effect']['data']['summary'] = $summary;
}
$form['effects'][$key]['weight'] = array(
$form['effects'][$key]['weight'] = [
'#type' => 'weight',
'#title' => $this->t('Weight for @title', array('@title' => $effect->label())),
'#title' => $this->t('Weight for @title', ['@title' => $effect->label()]),
'#title_display' => 'invisible',
'#default_value' => $effect->getWeight(),
'#attributes' => array(
'class' => array('image-effect-order-weight'),
),
);
'#attributes' => [
'class' => ['image-effect-order-weight'],
],
];
$links = array();
$links = [];
$is_configurable = $effect instanceof ConfigurableImageEffectInterface;
if ($is_configurable) {
$links['edit'] = array(
$links['edit'] = [
'title' => $this->t('Edit'),
'url' => Url::fromRoute('image.effect_edit_form', [
'image_style' => $this->entity->id(),
'image_effect' => $key,
]),
);
];
}
$links['delete'] = array(
$links['delete'] = [
'title' => $this->t('Delete'),
'url' => Url::fromRoute('image.effect_delete', [
'image_style' => $this->entity->id(),
'image_effect' => $key,
]),
);
$form['effects'][$key]['operations'] = array(
];
$form['effects'][$key]['operations'] = [
'#type' => 'operations',
'#links' => $links,
);
];
}
// Build the new image effect addition form and add it to the effect list.
$new_effect_options = array();
$new_effect_options = [];
$effects = $this->imageEffectManager->getDefinitions();
uasort($effects, function ($a, $b) {
return strcasecmp($a['id'], $b['id']);
@ -148,43 +148,43 @@ class ImageStyleEditForm extends ImageStyleFormBase {
foreach ($effects as $effect => $definition) {
$new_effect_options[$effect] = $definition['label'];
}
$form['effects']['new'] = array(
$form['effects']['new'] = [
'#tree' => FALSE,
'#weight' => isset($user_input['weight']) ? $user_input['weight'] : NULL,
'#attributes' => array('class' => array('draggable')),
);
$form['effects']['new']['effect'] = array(
'data' => array(
'new' => array(
'#attributes' => ['class' => ['draggable']],
];
$form['effects']['new']['effect'] = [
'data' => [
'new' => [
'#type' => 'select',
'#title' => $this->t('Effect'),
'#title_display' => 'invisible',
'#options' => $new_effect_options,
'#empty_option' => $this->t('Select a new effect'),
),
array(
'add' => array(
],
[
'add' => [
'#type' => 'submit',
'#value' => $this->t('Add'),
'#validate' => array('::effectValidate'),
'#submit' => array('::submitForm', '::effectSave'),
),
),
),
'#validate' => ['::effectValidate'],
'#submit' => ['::submitForm', '::effectSave'],
],
],
],
'#prefix' => '<div class="image-style-new">',
'#suffix' => '</div>',
);
];
$form['effects']['new']['weight'] = array(
$form['effects']['new']['weight'] = [
'#type' => 'weight',
'#title' => $this->t('Weight for new effect'),
'#title_display' => 'invisible',
'#default_value' => count($this->entity->getEffects()) + 1,
'#attributes' => array('class' => array('image-effect-order-weight')),
);
$form['effects']['new']['operations'] = array(
'data' => array(),
);
'#attributes' => ['class' => ['image-effect-order-weight']],
];
$form['effects']['new']['operations'] = [
'data' => [],
];
return parent::form($form, $form_state);
}
@ -211,20 +211,20 @@ class ImageStyleEditForm extends ImageStyleFormBase {
if (is_subclass_of($effect['class'], '\Drupal\image\ConfigurableImageEffectInterface')) {
$form_state->setRedirect(
'image.effect_add_form',
array(
[
'image_style' => $this->entity->id(),
'image_effect' => $form_state->getValue('new'),
),
array('query' => array('weight' => $form_state->getValue('weight')))
],
['query' => ['weight' => $form_state->getValue('weight')]]
);
}
// If there's no form, immediately add the image effect.
else {
$effect = array(
$effect = [
'id' => $effect['id'],
'data' => array(),
'data' => [],
'weight' => $form_state->getValue('weight'),
);
];
$effect_id = $this->entity->addImageEffect($effect);
$this->entity->save();
if (!empty($effect_id)) {

View file

@ -14,7 +14,7 @@ class ImageStyleFlushForm extends EntityConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to apply the updated %name image effect to all images?', array('%name' => $this->entity->label()));
return $this->t('Are you sure you want to apply the updated %name image effect to all images?', ['%name' => $this->entity->label()]);
}
/**
@ -43,7 +43,7 @@ class ImageStyleFlushForm extends EntityConfirmFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->flush();
drupal_set_message($this->t('The image style %name has been flushed.', array('%name' => $this->entity->label())));
drupal_set_message($this->t('The image style %name has been flushed.', ['%name' => $this->entity->label()]));
$form_state->setRedirectUrl($this->getCancelUrl());
}

View file

@ -50,20 +50,20 @@ abstract class ImageStyleFormBase extends EntityForm {
*/
public function form(array $form, FormStateInterface $form_state) {
$form['label'] = array(
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Image style name'),
'#default_value' => $this->entity->label(),
'#required' => TRUE,
);
$form['name'] = array(
];
$form['name'] = [
'#type' => 'machine_name',
'#machine_name' => array(
'exists' => array($this->imageStyleStorage, 'load'),
),
'#machine_name' => [
'exists' => [$this->imageStyleStorage, 'load'],
],
'#default_value' => $this->entity->id(),
'#required' => TRUE,
);
];
return parent::form($form, $form_state);
}

View file

@ -85,14 +85,14 @@ abstract class ImageEffectBase extends PluginBase implements ImageEffectInterfac
* {@inheritdoc}
*/
public function getSummary() {
return array(
return [
'#markup' => '',
'#effect' => array(
'#effect' => [
'id' => $this->pluginDefinition['id'],
'label' => $this->label(),
'description' => $this->pluginDefinition['description'],
),
);
],
];
}
/**
@ -128,23 +128,23 @@ abstract class ImageEffectBase extends PluginBase implements ImageEffectInterfac
* {@inheritdoc}
*/
public function getConfiguration() {
return array(
return [
'uuid' => $this->getUuid(),
'id' => $this->getPluginId(),
'weight' => $this->getWeight(),
'data' => $this->configuration,
);
];
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$configuration += array(
'data' => array(),
$configuration += [
'data' => [],
'uuid' => '',
'weight' => '',
);
];
$this->configuration = $configuration['data'] + $this->defaultConfiguration();
$this->uuid = $configuration['uuid'];
$this->weight = $configuration['weight'];
@ -155,14 +155,14 @@ abstract class ImageEffectBase extends PluginBase implements ImageEffectInterfac
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array();
return [];
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return array();
return [];
}
}

View file

@ -33,15 +33,15 @@ class ImageStyleListBuilder extends ConfigEntityListBuilder {
* {@inheritdoc}
*/
public function getDefaultOperations(EntityInterface $entity) {
$flush = array(
$flush = [
'title' => t('Flush'),
'weight' => 200,
'url' => $entity->urlInfo('flush-form'),
);
];
return parent::getDefaultOperations($entity) + array(
return parent::getDefaultOperations($entity) + [
'flush' => $flush,
);
];
}
/**

View file

@ -22,6 +22,9 @@ use Drupal\Core\Cache\Cache;
* label = @Translation("Image"),
* field_types = {
* "image"
* },
* quickedit = {
* "editor" = "image"
* }
* )
*/
@ -60,6 +63,8 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
* Any third party settings settings.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Entity\EntityStorageInterface $image_style_storage
* The image style storage.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, EntityStorageInterface $image_style_storage) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
@ -88,10 +93,10 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
* {@inheritdoc}
*/
public static function defaultSettings() {
return array(
return [
'image_style' => '',
'image_link' => '',
) + parent::defaultSettings();
] + parent::defaultSettings();
}
/**
@ -113,17 +118,17 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
'#access' => $this->currentUser->hasPermission('administer image styles')
],
];
$link_types = array(
$link_types = [
'content' => t('Content'),
'file' => t('File'),
);
$element['image_link'] = array(
];
$element['image_link'] = [
'#title' => t('Link image to'),
'#type' => 'select',
'#default_value' => $this->getSetting('image_link'),
'#empty_option' => t('Nothing'),
'#options' => $link_types,
);
];
return $element;
}
@ -132,7 +137,7 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = array();
$summary = [];
$image_styles = image_style_options(FALSE);
// Unset possible 'No defined styles' option.
@ -141,16 +146,16 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
// their styles in code.
$image_style_setting = $this->getSetting('image_style');
if (isset($image_styles[$image_style_setting])) {
$summary[] = t('Image style: @style', array('@style' => $image_styles[$image_style_setting]));
$summary[] = t('Image style: @style', ['@style' => $image_styles[$image_style_setting]]);
}
else {
$summary[] = t('Original image');
}
$link_types = array(
$link_types = [
'content' => t('Linked to content'),
'file' => t('Linked to file'),
);
];
// Display this setting only if image is linked.
$image_link_setting = $this->getSetting('image_link');
if (isset($link_types[$image_link_setting])) {
@ -164,7 +169,7 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
$elements = [];
$files = $this->getEntitiesToView($items, $langcode);
// Early opt-out if the field is empty.
@ -214,17 +219,17 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
$item_attributes = $item->_attributes;
unset($item->_attributes);
$elements[$delta] = array(
$elements[$delta] = [
'#theme' => 'image_formatter',
'#item' => $item,
'#item_attributes' => $item_attributes,
'#image_style' => $image_style_setting,
'#url' => $url,
'#cache' => array(
'#cache' => [
'tags' => $cache_tags,
'contexts' => $cache_contexts,
),
);
],
];
}
return $elements;

View file

@ -28,7 +28,7 @@ abstract class ImageFormatterBase extends FileFormatterBase {
// so that the fallback image can be rendered without affecting the
// field values in the entity being rendered.
$items = clone $items;
$items->setValue(array(
$items->setValue([
'target_id' => $file->id(),
'alt' => $default_image['alt'],
'title' => $default_image['title'],
@ -37,7 +37,7 @@ abstract class ImageFormatterBase extends FileFormatterBase {
'entity' => $file,
'_loaded' => TRUE,
'_is_default' => TRUE,
));
]);
$file->_referringItem = $items[0];
}
}

View file

@ -0,0 +1,82 @@
<?php
namespace Drupal\image\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'image_url' formatter.
*
* @FieldFormatter(
* id = "image_url",
* label = @Translation("URL to image"),
* field_types = {
* "image"
* }
* )
*/
class ImageUrlFormatter extends ImageFormatter {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'image_style' => '',
];
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$element = parent::settingsForm($form, $form_state);
unset($element['image_link']);;
return $element;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
return [$summary[0]];
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
/** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items */
if (empty($images = $this->getEntitiesToView($items, $langcode))) {
// Early opt-out if the field is empty.
return $elements;
}
/** @var \Drupal\image\ImageStyleInterface $image_style */
$image_style = $this->imageStyleStorage->load($this->getSetting('image_style'));
/** @var \Drupal\file\FileInterface[] $images */
foreach ($images as $delta => $image) {
$image_uri = $image->getFileUri();
$url = $image_style ? $image_style->buildUrl($image_uri) : file_create_url($image_uri);
$url = file_url_transform_relative($url);
// Add cacheability metadata from the image and image style.
$cacheability = CacheableMetadata::createFromObject($image);
if ($image_style) {
$cacheability->addCacheableDependency(CacheableMetadata::createFromObject($image_style));
}
$elements[$delta] = ['#markup' => $url];
$cacheability->applyTo($elements[$delta]);
}
return $elements;
}
}

View file

@ -55,22 +55,22 @@ class ImageItem extends FileItem {
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return array(
'default_image' => array(
return [
'default_image' => [
'uuid' => NULL,
'alt' => '',
'title' => '',
'width' => NULL,
'height' => NULL,
),
) + parent::defaultStorageSettings();
],
] + parent::defaultStorageSettings();
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
$settings = array(
$settings = [
'file_extensions' => 'png gif jpg jpeg',
'alt_field' => 1,
'alt_field_required' => 1,
@ -78,14 +78,14 @@ class ImageItem extends FileItem {
'title_field_required' => 0,
'max_resolution' => '',
'min_resolution' => '',
'default_image' => array(
'default_image' => [
'uuid' => NULL,
'alt' => '',
'title' => '',
'width' => NULL,
'height' => NULL,
),
) + parent::defaultFieldSettings();
],
] + parent::defaultFieldSettings();
unset($settings['description_field']);
return $settings;
@ -95,44 +95,44 @@ class ImageItem extends FileItem {
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return array(
'columns' => array(
'target_id' => array(
return [
'columns' => [
'target_id' => [
'description' => 'The ID of the file entity.',
'type' => 'int',
'unsigned' => TRUE,
),
'alt' => array(
],
'alt' => [
'description' => "Alternative image text, for the image's 'alt' attribute.",
'type' => 'varchar',
'length' => 512,
),
'title' => array(
],
'title' => [
'description' => "Image title text, for the image's 'title' attribute.",
'type' => 'varchar',
'length' => 1024,
),
'width' => array(
],
'width' => [
'description' => 'The width of the image in pixels.',
'type' => 'int',
'unsigned' => TRUE,
),
'height' => array(
],
'height' => [
'description' => 'The height of the image in pixels.',
'type' => 'int',
'unsigned' => TRUE,
),
),
'indexes' => array(
'target_id' => array('target_id'),
),
'foreign keys' => array(
'target_id' => array(
],
],
'indexes' => [
'target_id' => ['target_id'],
],
'foreign keys' => [
'target_id' => [
'table' => 'file_managed',
'columns' => array('target_id' => 'fid'),
),
),
);
'columns' => ['target_id' => 'fid'],
],
],
];
}
/**
@ -167,7 +167,7 @@ class ImageItem extends FileItem {
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element = array();
$element = [];
// We need the field-level 'default_image' setting, and $this->getSettings()
// will only provide the instance-level one, so we need to explicitly fetch
@ -175,13 +175,13 @@ class ImageItem extends FileItem {
$settings = $this->getFieldDefinition()->getFieldStorageDefinition()->getSettings();
$scheme_options = \Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::WRITE_VISIBLE);
$element['uri_scheme'] = array(
$element['uri_scheme'] = [
'#type' => 'radios',
'#title' => t('Upload destination'),
'#options' => $scheme_options,
'#default_value' => $settings['uri_scheme'],
'#description' => t('Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.'),
);
];
// Add default_image element.
static::defaultImageForm($element, $settings);
@ -200,101 +200,101 @@ class ImageItem extends FileItem {
$settings = $this->getSettings();
// Add maximum and minimum resolution settings.
$max_resolution = explode('x', $settings['max_resolution']) + array('', '');
$element['max_resolution'] = array(
$max_resolution = explode('x', $settings['max_resolution']) + ['', ''];
$element['max_resolution'] = [
'#type' => 'item',
'#title' => t('Maximum image resolution'),
'#element_validate' => array(array(get_class($this), 'validateResolution')),
'#element_validate' => [[get_class($this), 'validateResolution']],
'#weight' => 4.1,
'#field_prefix' => '<div class="container-inline">',
'#field_suffix' => '</div>',
'#description' => t('The maximum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of <a href="http://wikipedia.org/wiki/Exchangeable_image_file_format">EXIF data</a> in the image.'),
);
$element['max_resolution']['x'] = array(
];
$element['max_resolution']['x'] = [
'#type' => 'number',
'#title' => t('Maximum width'),
'#title_display' => 'invisible',
'#default_value' => $max_resolution[0],
'#min' => 1,
'#field_suffix' => ' × ',
);
$element['max_resolution']['y'] = array(
];
$element['max_resolution']['y'] = [
'#type' => 'number',
'#title' => t('Maximum height'),
'#title_display' => 'invisible',
'#default_value' => $max_resolution[1],
'#min' => 1,
'#field_suffix' => ' ' . t('pixels'),
);
];
$min_resolution = explode('x', $settings['min_resolution']) + array('', '');
$element['min_resolution'] = array(
$min_resolution = explode('x', $settings['min_resolution']) + ['', ''];
$element['min_resolution'] = [
'#type' => 'item',
'#title' => t('Minimum image resolution'),
'#element_validate' => array(array(get_class($this), 'validateResolution')),
'#element_validate' => [[get_class($this), 'validateResolution']],
'#weight' => 4.2,
'#field_prefix' => '<div class="container-inline">',
'#field_suffix' => '</div>',
'#description' => t('The minimum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'),
);
$element['min_resolution']['x'] = array(
];
$element['min_resolution']['x'] = [
'#type' => 'number',
'#title' => t('Minimum width'),
'#title_display' => 'invisible',
'#default_value' => $min_resolution[0],
'#min' => 1,
'#field_suffix' => ' × ',
);
$element['min_resolution']['y'] = array(
];
$element['min_resolution']['y'] = [
'#type' => 'number',
'#title' => t('Minimum height'),
'#title_display' => 'invisible',
'#default_value' => $min_resolution[1],
'#min' => 1,
'#field_suffix' => ' ' . t('pixels'),
);
];
// Remove the description option.
unset($element['description_field']);
// Add title and alt configuration options.
$element['alt_field'] = array(
$element['alt_field'] = [
'#type' => 'checkbox',
'#title' => t('Enable <em>Alt</em> field'),
'#default_value' => $settings['alt_field'],
'#description' => t('The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded. Enabling this field is recommended.'),
'#weight' => 9,
);
$element['alt_field_required'] = array(
];
$element['alt_field_required'] = [
'#type' => 'checkbox',
'#title' => t('<em>Alt</em> field required'),
'#default_value' => $settings['alt_field_required'],
'#description' => t('Making this field required is recommended.'),
'#weight' => 10,
'#states' => array(
'visible' => array(
':input[name="settings[alt_field]"]' => array('checked' => TRUE),
),
),
);
$element['title_field'] = array(
'#states' => [
'visible' => [
':input[name="settings[alt_field]"]' => ['checked' => TRUE],
],
],
];
$element['title_field'] = [
'#type' => 'checkbox',
'#title' => t('Enable <em>Title</em> field'),
'#default_value' => $settings['title_field'],
'#description' => t('The title attribute is used as a tooltip when the mouse hovers over the image. Enabling this field is not recommended as it can cause problems with screen readers.'),
'#weight' => 11,
);
$element['title_field_required'] = array(
];
$element['title_field_required'] = [
'#type' => 'checkbox',
'#title' => t('<em>Title</em> field required'),
'#default_value' => $settings['title_field_required'],
'#weight' => 12,
'#states' => array(
'visible' => array(
':input[name="settings[title_field]"]' => array('checked' => TRUE),
),
),
);
'#states' => [
'visible' => [
':input[name="settings[title_field]"]' => ['checked' => TRUE],
],
],
];
// Add default_image element.
static::defaultImageForm($element, $settings);
@ -328,11 +328,11 @@ class ImageItem extends FileItem {
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
$random = new Random();
$settings = $field_definition->getSettings();
static $images = array();
static $images = [];
$min_resolution = empty($settings['min_resolution']) ? '100x100' : $settings['min_resolution'];
$max_resolution = empty($settings['max_resolution']) ? '600x600' : $settings['max_resolution'];
$extensions = array_intersect(explode(' ', $settings['file_extensions']), array('png', 'gif', 'jpg', 'jpeg'));
$extensions = array_intersect(explode(' ', $settings['file_extensions']), ['png', 'gif', 'jpg', 'jpeg']);
$extension = array_rand(array_combine($extensions, $extensions));
// Generate a max of 5 different images.
if (!isset($images[$extension][$min_resolution][$max_resolution]) || count($images[$extension][$min_resolution][$max_resolution]) <= 5) {
@ -352,7 +352,7 @@ class ImageItem extends FileItem {
$images[$extension][$min_resolution][$max_resolution][$file->id()] = $file;
}
else {
return array();
return [];
}
}
else {
@ -362,13 +362,13 @@ class ImageItem extends FileItem {
}
list($width, $height) = getimagesize($file->getFileUri());
$values = array(
$values = [
'target_id' => $file->id(),
'alt' => $random->sentences(4),
'title' => $random->sentences(4),
'width' => $width,
'height' => $height,
);
];
return $values;
}
@ -377,11 +377,11 @@ class ImageItem extends FileItem {
*/
public static function validateResolution($element, FormStateInterface $form_state) {
if (!empty($element['x']['#value']) || !empty($element['y']['#value'])) {
foreach (array('x', 'y') as $dimension) {
foreach (['x', 'y'] as $dimension) {
if (!$element[$dimension]['#value']) {
// We expect the field name placeholder value to be wrapped in t()
// here, so it won't be escaped again as it's already marked safe.
$form_state->setError($element[$dimension], t('Both a height and width value must be specified in the @name field.', array('@name' => $element['#title'])));
$form_state->setError($element[$dimension], t('Both a height and width value must be specified in the @name field.', ['@name' => $element['#title']]));
return;
}
}
@ -401,51 +401,51 @@ class ImageItem extends FileItem {
* The field settings array.
*/
protected function defaultImageForm(array &$element, array $settings) {
$element['default_image'] = array(
$element['default_image'] = [
'#type' => 'details',
'#title' => t('Default image'),
'#open' => TRUE,
);
];
// Convert the stored UUID to a FID.
$fids = [];
$uuid = $settings['default_image']['uuid'];
if ($uuid && ($file = $this->getEntityManager()->loadEntityByUuid('file', $uuid))) {
$fids[0] = $file->id();
}
$element['default_image']['uuid'] = array(
$element['default_image']['uuid'] = [
'#type' => 'managed_file',
'#title' => t('Image'),
'#description' => t('Image to be shown if no image is uploaded.'),
'#default_value' => $fids,
'#upload_location' => $settings['uri_scheme'] . '://default_images/',
'#element_validate' => array(
'#element_validate' => [
'\Drupal\file\Element\ManagedFile::validateManagedFile',
array(get_class($this), 'validateDefaultImageForm'),
),
[get_class($this), 'validateDefaultImageForm'],
],
'#upload_validators' => $this->getUploadValidators(),
);
$element['default_image']['alt'] = array(
];
$element['default_image']['alt'] = [
'#type' => 'textfield',
'#title' => t('Alternative text'),
'#description' => t('This text will be used by screen readers, search engines, and when the image cannot be loaded.'),
'#default_value' => $settings['default_image']['alt'],
'#maxlength' => 512,
);
$element['default_image']['title'] = array(
];
$element['default_image']['title'] = [
'#type' => 'textfield',
'#title' => t('Title'),
'#description' => t('The title attribute is used as a tooltip when the mouse hovers over the image.'),
'#default_value' => $settings['default_image']['title'],
'#maxlength' => 1024,
);
$element['default_image']['width'] = array(
];
$element['default_image']['width'] = [
'#type' => 'value',
'#value' => $settings['default_image']['width'],
);
$element['default_image']['height'] = array(
];
$element['default_image']['height'] = [
'#type' => 'value',
'#value' => $settings['default_image']['height'],
);
];
}
/**
@ -487,7 +487,7 @@ class ImageItem extends FileItem {
/**
* Gets the entity manager.
*
* @return \Drupal\Core\Entity\EntityManagerInterface.
* @return \Drupal\Core\Entity\EntityManagerInterface
*/
protected function getEntityManager() {
if (!isset($this->entityManager)) {

View file

@ -26,10 +26,10 @@ class ImageWidget extends FileWidget {
* {@inheritdoc}
*/
public static function defaultSettings() {
return array(
return [
'progress_indicator' => 'throbber',
'preview_image_style' => 'thumbnail',
) + parent::defaultSettings();
] + parent::defaultSettings();
}
/**
@ -38,7 +38,7 @@ class ImageWidget extends FileWidget {
public function settingsForm(array $form, FormStateInterface $form_state) {
$element = parent::settingsForm($form, $form_state);
$element['preview_image_style'] = array(
$element['preview_image_style'] = [
'#title' => t('Preview image style'),
'#type' => 'select',
'#options' => image_style_options(FALSE),
@ -46,7 +46,7 @@ class ImageWidget extends FileWidget {
'#default_value' => $this->getSetting('preview_image_style'),
'#description' => t('The preview image will be shown while editing the content.'),
'#weight' => 15,
);
];
return $element;
}
@ -64,7 +64,7 @@ class ImageWidget extends FileWidget {
// their styles in code.
$image_style_setting = $this->getSetting('preview_image_style');
if (isset($image_styles[$image_style_setting])) {
$preview_image_style = t('Preview image style: @style', array('@style' => $image_styles[$image_style_setting]));
$preview_image_style = t('Preview image style: @style', ['@style' => $image_styles[$image_style_setting]]);
}
else {
$preview_image_style = t('No preview');
@ -84,12 +84,12 @@ class ImageWidget extends FileWidget {
$elements = parent::formMultipleElements($items, $form, $form_state);
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
$file_upload_help = array(
$file_upload_help = [
'#theme' => 'file_upload_help',
'#description' => '',
'#upload_validators' => $elements[0]['#upload_validators'],
'#cardinality' => $cardinality,
);
];
if ($cardinality == 1) {
// If there's only one field, return it as delta 0.
if (empty($elements[0]['#default_value']['fids'])) {
@ -114,15 +114,18 @@ class ImageWidget extends FileWidget {
// Add upload resolution validation.
if ($field_settings['max_resolution'] || $field_settings['min_resolution']) {
$element['#upload_validators']['file_validate_image_resolution'] = array($field_settings['max_resolution'], $field_settings['min_resolution']);
$element['#upload_validators']['file_validate_image_resolution'] = [$field_settings['max_resolution'], $field_settings['min_resolution']];
}
// If not using custom extension validation, ensure this is an image.
$supported_extensions = array('png', 'gif', 'jpg', 'jpeg');
$supported_extensions = ['png', 'gif', 'jpg', 'jpeg'];
$extensions = isset($element['#upload_validators']['file_validate_extensions'][0]) ? $element['#upload_validators']['file_validate_extensions'][0] : implode(' ', $supported_extensions);
$extensions = array_intersect(explode(' ', $extensions), $supported_extensions);
$element['#upload_validators']['file_validate_extensions'][0] = implode(' ', $extensions);
// Add mobile device image capture acceptance.
$element['#accept'] = 'image/*';
// Add properties needed by process() method.
$element['#preview_image_style'] = $this->getSetting('preview_image_style');
$element['#title_field'] = $field_settings['title_field'];
@ -139,7 +142,7 @@ class ImageWidget extends FileWidget {
if (!empty($default_image['uuid']) && $entity = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid'])) {
$default_image['fid'] = $entity->id();
}
$element['#default_image'] = !empty($default_image['fid']) ? $default_image : array();
$element['#default_image'] = !empty($default_image['fid']) ? $default_image : [];
return $element;
}
@ -160,10 +163,10 @@ class ImageWidget extends FileWidget {
// Add the image preview.
if (!empty($element['#files']) && $element['#preview_image_style']) {
$file = reset($element['#files']);
$variables = array(
$variables = [
'style_name' => $element['#preview_image_style'],
'uri' => $file->getFileUri(),
);
];
// Determine image dimensions.
if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
@ -181,43 +184,43 @@ class ImageWidget extends FileWidget {
}
}
$element['preview'] = array(
$element['preview'] = [
'#weight' => -10,
'#theme' => 'image_style',
'#width' => $variables['width'],
'#height' => $variables['height'],
'#style_name' => $variables['style_name'],
'#uri' => $variables['uri'],
);
];
// Store the dimensions in the form so the file doesn't have to be
// accessed again. This is important for remote files.
$element['width'] = array(
$element['width'] = [
'#type' => 'hidden',
'#value' => $variables['width'],
);
$element['height'] = array(
];
$element['height'] = [
'#type' => 'hidden',
'#value' => $variables['height'],
);
];
}
elseif (!empty($element['#default_image'])) {
$default_image = $element['#default_image'];
$file = File::load($default_image['fid']);
if (!empty($file)) {
$element['preview'] = array(
$element['preview'] = [
'#weight' => -10,
'#theme' => 'image_style',
'#width' => $default_image['width'],
'#height' => $default_image['height'],
'#style_name' => $element['#preview_image_style'],
'#uri' => $file->getFileUri(),
);
];
}
}
// Add the additional alt and title fields.
$element['alt'] = array(
$element['alt'] = [
'#title' => t('Alternative text'),
'#type' => 'textfield',
'#default_value' => isset($item['alt']) ? $item['alt'] : '',
@ -227,9 +230,9 @@ class ImageWidget extends FileWidget {
'#weight' => -12,
'#access' => (bool) $item['fids'] && $element['#alt_field'],
'#required' => $element['#alt_field_required'],
'#element_validate' => $element['#alt_field_required'] == 1 ? array(array(get_called_class(), 'validateRequiredFields')) : array(),
);
$element['title'] = array(
'#element_validate' => $element['#alt_field_required'] == 1 ? [[get_called_class(), 'validateRequiredFields']] : [],
];
$element['title'] = [
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => isset($item['title']) ? $item['title'] : '',
@ -238,8 +241,8 @@ class ImageWidget extends FileWidget {
'#weight' => -11,
'#access' => (bool) $item['fids'] && $element['#title_field'],
'#required' => $element['#title_field_required'],
'#element_validate' => $element['#title_field_required'] == 1 ? array(array(get_called_class(), 'validateRequiredFields')) : array(),
);
'#element_validate' => $element['#title_field_required'] == 1 ? [[get_called_class(), 'validateRequiredFields']] : [],
];
return parent::process($element, $form_state, $form);
}

View file

@ -23,7 +23,7 @@ class ConvertImageEffect extends ConfigurableImageEffectBase {
*/
public function applyEffect(ImageInterface $image) {
if (!$image->convert($this->configuration['extension'])) {
$this->logger->error('Image convert failed using the %toolkit toolkit on %path (%mimetype)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType()));
$this->logger->error('Image convert failed using the %toolkit toolkit on %path (%mimetype)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType()]);
return FALSE;
}
return TRUE;
@ -40,9 +40,9 @@ class ConvertImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function getSummary() {
$summary = array(
$summary = [
'#markup' => Unicode::strtoupper($this->configuration['extension']),
);
];
$summary += parent::getSummary();
return $summary;
@ -52,9 +52,9 @@ class ConvertImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
return [
'extension' => NULL,
);
];
}
/**
@ -64,15 +64,15 @@ class ConvertImageEffect extends ConfigurableImageEffectBase {
$extensions = \Drupal::service('image.toolkit.manager')->getDefaultToolkit()->getSupportedExtensions();
$options = array_combine(
$extensions,
array_map(array('\Drupal\Component\Utility\Unicode', 'strtoupper'), $extensions)
array_map(['\Drupal\Component\Utility\Unicode', 'strtoupper'], $extensions)
);
$form['extension'] = array(
$form['extension'] = [
'#type' => 'select',
'#title' => t('Extension'),
'#default_value' => $this->configuration['extension'],
'#required' => TRUE,
'#options' => $options,
);
];
return $form;
}

View file

@ -24,7 +24,7 @@ class CropImageEffect extends ResizeImageEffect {
$x = image_filter_keyword($x, $image->getWidth(), $this->configuration['width']);
$y = image_filter_keyword($y, $image->getHeight(), $this->configuration['height']);
if (!$image->crop($x, $y, $this->configuration['width'], $this->configuration['height'])) {
$this->logger->error('Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;
@ -34,10 +34,10 @@ class CropImageEffect extends ResizeImageEffect {
* {@inheritdoc}
*/
public function getSummary() {
$summary = array(
$summary = [
'#theme' => 'image_crop_summary',
'#data' => $this->configuration,
);
];
$summary += parent::getSummary();
return $summary;
@ -47,9 +47,9 @@ class CropImageEffect extends ResizeImageEffect {
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + array(
return parent::defaultConfiguration() + [
'anchor' => 'center-center',
);
];
}
/**
@ -57,10 +57,10 @@ class CropImageEffect extends ResizeImageEffect {
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['anchor'] = array(
$form['anchor'] = [
'#type' => 'radios',
'#title' => t('Anchor'),
'#options' => array(
'#options' => [
'left-top' => t('Top left'),
'center-top' => t('Top center'),
'right-top' => t('Top right'),
@ -70,11 +70,11 @@ class CropImageEffect extends ResizeImageEffect {
'left-bottom' => t('Bottom left'),
'center-bottom' => t('Bottom center'),
'right-bottom' => t('Bottom right'),
),
],
'#theme' => 'image_anchor',
'#default_value' => $this->configuration['anchor'],
'#description' => t('The part of the image that will be retained during the crop.'),
);
];
return $form;
}

View file

@ -21,7 +21,7 @@ class DesaturateImageEffect extends ImageEffectBase {
*/
public function applyEffect(ImageInterface $image) {
if (!$image->desaturate()) {
$this->logger->error('Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;

View file

@ -22,7 +22,7 @@ class ResizeImageEffect extends ConfigurableImageEffectBase {
*/
public function applyEffect(ImageInterface $image) {
if (!$image->resize($this->configuration['width'], $this->configuration['height'])) {
$this->logger->error('Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;
@ -41,10 +41,10 @@ class ResizeImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function getSummary() {
$summary = array(
$summary = [
'#theme' => 'image_resize_summary',
'#data' => $this->configuration,
);
];
$summary += parent::getSummary();
return $summary;
@ -54,32 +54,32 @@ class ResizeImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
return [
'width' => NULL,
'height' => NULL,
);
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['width'] = array(
$form['width'] = [
'#type' => 'number',
'#title' => t('Width'),
'#default_value' => $this->configuration['width'],
'#field_suffix' => ' ' . t('pixels'),
'#required' => TRUE,
'#min' => 1,
);
$form['height'] = array(
];
$form['height'] = [
'#type' => 'number',
'#title' => t('Height'),
'#default_value' => $this->configuration['height'],
'#field_suffix' => ' ' . t('pixels'),
'#required' => TRUE,
'#min' => 1,
);
];
return $form;
}

View file

@ -29,7 +29,7 @@ class RotateImageEffect extends ConfigurableImageEffectBase {
}
if (!$image->rotate($this->configuration['degrees'], $this->configuration['bgcolor'])) {
$this->logger->error('Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;
@ -56,10 +56,10 @@ class RotateImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function getSummary() {
$summary = array(
$summary = [
'#theme' => 'image_rotate_summary',
'#data' => $this->configuration,
);
];
$summary += parent::getSummary();
return $summary;
@ -69,39 +69,39 @@ class RotateImageEffect extends ConfigurableImageEffectBase {
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
return [
'degrees' => 0,
'bgcolor' => NULL,
'random' => FALSE,
);
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['degrees'] = array(
$form['degrees'] = [
'#type' => 'number',
'#default_value' => $this->configuration['degrees'],
'#title' => t('Rotation angle'),
'#description' => t('The number of degrees the image should be rotated. Positive numbers are clockwise, negative are counter-clockwise.'),
'#field_suffix' => '°',
'#required' => TRUE,
);
$form['bgcolor'] = array(
];
$form['bgcolor'] = [
'#type' => 'textfield',
'#default_value' => $this->configuration['bgcolor'],
'#title' => t('Background color'),
'#description' => t('The background color to use for exposed areas of the image. Use web-style hex colors (#FFFFFF for white, #000000 for black). Leave blank for transparency on image types that support it.'),
'#size' => 7,
'#maxlength' => 7,
);
$form['random'] = array(
];
$form['random'] = [
'#type' => 'checkbox',
'#default_value' => $this->configuration['random'],
'#title' => t('Randomize'),
'#description' => t('Randomize the rotation angle for each image. The angle specified above is used as a maximum.'),
);
];
return $form;
}

View file

@ -20,7 +20,7 @@ class ScaleAndCropImageEffect extends ResizeImageEffect {
*/
public function applyEffect(ImageInterface $image) {
if (!$image->scaleAndCrop($this->configuration['width'], $this->configuration['height'])) {
$this->logger->error('Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;

View file

@ -22,7 +22,7 @@ class ScaleImageEffect extends ResizeImageEffect {
*/
public function applyEffect(ImageInterface $image) {
if (!$image->scale($this->configuration['width'], $this->configuration['height'], $this->configuration['upscale'])) {
$this->logger->error('Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()));
$this->logger->error('Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', ['%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()]);
return FALSE;
}
return TRUE;
@ -41,10 +41,10 @@ class ScaleImageEffect extends ResizeImageEffect {
* {@inheritdoc}
*/
public function getSummary() {
$summary = array(
$summary = [
'#theme' => 'image_scale_summary',
'#data' => $this->configuration,
);
];
$summary += parent::getSummary();
return $summary;
@ -54,9 +54,9 @@ class ScaleImageEffect extends ResizeImageEffect {
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + array(
return parent::defaultConfiguration() + [
'upscale' => FALSE,
);
];
}
/**
@ -66,12 +66,12 @@ class ScaleImageEffect extends ResizeImageEffect {
$form = parent::buildConfigurationForm($form, $form_state);
$form['width']['#required'] = FALSE;
$form['height']['#required'] = FALSE;
$form['upscale'] = array(
$form['upscale'] = [
'#type' => 'checkbox',
'#default_value' => $this->configuration['upscale'],
'#title' => t('Allow Upscaling'),
'#description' => t('Let scale make images larger than their original size.'),
);
];
return $form;
}

View file

@ -0,0 +1,39 @@
<?php
namespace Drupal\image\Plugin\InPlaceEditor;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\quickedit\Plugin\InPlaceEditorBase;
/**
* Defines the image text in-place editor.
*
* @InPlaceEditor(
* id = "image"
* )
*/
class Image extends InPlaceEditorBase {
/**
* {@inheritdoc}
*/
public function isCompatible(FieldItemListInterface $items) {
$field_definition = $items->getFieldDefinition();
// This editor is only compatible with single-value image fields.
return $field_definition->getFieldStorageDefinition()->getCardinality() === 1
&& $field_definition->getType() === 'image';
}
/**
* {@inheritdoc}
*/
public function getAttachments() {
return [
'library' => [
'image/quickedit.inPlaceEditor.image',
],
];
}
}

View file

@ -46,7 +46,7 @@ class EntityImageStyle extends EntityConfigBase {
$style->save();
return array($style->id());
return [$style->id()];
}
}

View file

@ -47,7 +47,7 @@ class ImageCachePreset extends DrupalSqlBase {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$actions = array();
$actions = [];
$results = $this->select('imagecache_action', 'ica')
->fields('ica')

View file

@ -47,7 +47,7 @@ class ImageStyles extends DrupalSqlBase {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$effects = array();
$effects = [];
$results = $this->select('image_effects', 'ie')
->fields('ie')

View file

@ -45,7 +45,7 @@ class ImageStyleRoutes implements ContainerInjectionInterface {
* An array of route objects.
*/
public function routes() {
$routes = array();
$routes = [];
// Generate image derivatives of publicly available files. If clean URLs are
// disabled image derivatives will always be served through the menu system.
// If clean URLs are enabled and the image derivative already exists, PHP
@ -54,12 +54,12 @@ class ImageStyleRoutes implements ContainerInjectionInterface {
$routes['image.style_public'] = new Route(
'/' . $directory_path . '/styles/{image_style}/{scheme}',
array(
[
'_controller' => 'Drupal\image\Controller\ImageStyleDownloadController::deliver',
),
array(
],
[
'_access' => 'TRUE',
)
]
);
return $routes;
}

View file

@ -18,12 +18,12 @@ class FileMoveTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('image');
public static $modules = ['image'];
/**
* Tests moving a randomly generated image.
*/
function testNormal() {
public function testNormal() {
// Pick a file for testing.
$file = File::create((array) current($this->drupalGetTestFiles('image')));

View file

@ -19,7 +19,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
/**
* Given an image style, generate an image.
*/
function createSampleImage(ImageStyleInterface $style) {
public function createSampleImage(ImageStyleInterface $style) {
static $file_path;
// First, we need to make sure we have an image in our testing
@ -36,7 +36,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
/**
* Count the number of images currently create for a style.
*/
function getImageCount(ImageStyleInterface $style) {
public function getImageCount(ImageStyleInterface $style) {
return count(file_scan_directory('public://styles/' . $style->id(), '/.*/'));
}
@ -44,66 +44,66 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
* Test creating an image style with a numeric name and ensuring it can be
* applied to an image.
*/
function testNumericStyleName() {
public function testNumericStyleName() {
$style_name = rand();
$style_label = $this->randomString();
$edit = array(
$edit = [
'name' => $style_name,
'label' => $style_label,
);
];
$this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style'));
$this->assertRaw(t('Style %name was created.', array('%name' => $style_label)));
$this->assertRaw(t('Style %name was created.', ['%name' => $style_label]));
$options = image_style_options();
$this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', array('%key' => $style_name)));
$this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', ['%key' => $style_name]));
}
/**
* General test to add a style, add/remove/edit effects to it, then delete it.
*/
function testStyle() {
public 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(
$effect_edits = [
'image_resize' => [
'width' => 100,
'height' => 101,
),
'image_scale' => array(
],
'image_scale' => [
'width' => 110,
'height' => 111,
'upscale' => 1,
),
'image_scale_and_crop' => array(
],
'image_scale_and_crop' => [
'width' => 120,
'height' => 121,
),
'image_crop' => array(
],
'image_crop' => [
'width' => 130,
'height' => 131,
'anchor' => 'left-top',
),
'image_desaturate' => array(
],
'image_desaturate' => [
// No options for desaturate.
),
'image_rotate' => array(
],
'image_rotate' => [
'degrees' => 5,
'random' => 1,
'bgcolor' => '#FFFF00',
),
);
],
];
// Add style form.
$edit = array(
$edit = [
'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)));
$this->assertRaw(t('Style %name was created.', ['%name' => $style_label]));
// Ensure that the expected entity operations are there.
$this->drupalGet($admin_path);
@ -115,12 +115,12 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Add each sample effect to the style.
foreach ($effect_edits as $effect => $edit) {
$edit_data = array();
$edit_data = [];
foreach ($edit as $field => $value) {
$edit_data['data[' . $field . ']'] = $value;
}
// Add the effect.
$this->drupalPostForm($style_path, array('new' => $effect), t('Add'));
$this->drupalPostForm($style_path, ['new' => $effect], t('Add'));
if (!empty($edit)) {
$this->drupalPostForm(NULL, $edit_data, t('Add effect'));
}
@ -140,13 +140,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Confirm that all effects on the image style have settings that match
// what was saved.
$uuids = array();
$uuids = [];
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)));
$this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', ['%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value]));
}
}
@ -154,10 +154,10 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
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).
@ -180,10 +180,10 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
$style_name = strtolower($this->randomMachineName(10));
$style_label = $this->randomMachineName();
$weight = count($effect_edits);
$edit = array(
$edit = [
'name' => $style_name,
'label' => $style_label,
);
];
foreach ($style->getEffects() as $uuid => $effect) {
$edit['effects[' . $uuid . '][weight]'] = $weight;
$weight--;
@ -191,7 +191,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// 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->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path]));
$this->drupalPostForm($style_path, $edit, t('Update style'));
@ -200,13 +200,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// 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)));
$this->assertTitle(t('Edit style @name | Drupal', ['@name' => $style_label]));
$this->assertResponse(200, format_string('Image style %original renamed to %new', ['%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())));
$this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', ['%style' => $style->label()]));
// Load the style by the new name with the new weights.
$style = ImageStyle::load($style_name);
@ -227,14 +227,14 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// 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)));
$this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%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'));
$this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', [], 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())));
$this->assertRaw(t('The image effect %name has been deleted.', ['%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
@ -243,18 +243,18 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
$style = $entity_type_manager->getStorage('image_style')->loadUnchanged($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(
$edit = [
'data[degrees]' => 5,
'data[random]' => 0,
'data[bgcolor]' => '',
);
$this->drupalPostForm($style_path, array('new' => 'image_rotate'), t('Add'));
];
$this->drupalPostForm($style_path, ['new' => 'image_rotate'], t('Add'));
$this->drupalPostForm(NULL, $edit, t('Add effect'));
$entity_type_manager = $this->container->get('entity_type.manager');
$style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style_name);
@ -263,13 +263,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Style deletion form.
// Delete the style.
$this->drupalPostForm($style_path . '/delete', array(), t('Delete'));
$this->drupalPostForm($style_path . '/delete', [], 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(is_dir($directory), format_string('Image style %style directory removed on style deletion.', ['%style' => $style->label()]));
$this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', array('%style' => $style->label())));
$this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', ['%style' => $style->label()]));
// Test empty text when there are no image styles.
@ -330,11 +330,11 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
/**
* Test deleting a style and choosing a replacement style.
*/
function testStyleReplacement() {
public function testStyleReplacement() {
// Create a new style.
$style_name = strtolower($this->randomMachineName(10));
$style_label = $this->randomString();
$style = ImageStyle::create(array('name' => $style_name, 'label' => $style_label));
$style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]);
$style->save();
$style_path = 'admin/config/media/image-styles/manage/';
@ -342,10 +342,10 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
$field_name = strtolower($this->randomMachineName(10));
$this->createImageField($field_name, 'article');
entity_get_display('node', 'article', 'default')
->setComponent($field_name, array(
->setComponent($field_name, [
'type' => 'image',
'settings' => array('image_style' => $style_name),
))
'settings' => ['image_style' => $style_name],
])
->save();
// Create a new node with an image attached.
@ -359,17 +359,17 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Test that image is displayed using newly created style.
$this->drupalGet('node/' . $nid);
$this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', array('@style' => $style_name)));
$this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name]));
// Rename the style and make sure the image field is updated.
$new_style_name = strtolower($this->randomMachineName(10));
$new_style_label = $this->randomString();
$edit = array(
$edit = [
'name' => $new_style_name,
'label' => $new_style_label,
);
];
$this->drupalPostForm($style_path . $style_name, $edit, t('Update style'));
$this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', array('%name' => $style_name, '%new_name' => $new_style_name)));
$this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', ['%name' => $style_name, '%new_name' => $new_style_name]));
$this->drupalGet('node/' . $nid);
// Reload the image style using the new name.
@ -377,11 +377,11 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
$this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.');
// Delete the style and choose a replacement style.
$edit = array(
$edit = [
'replacement' => 'thumbnail',
);
];
$this->drupalPostForm($style_path . $new_style_name . '/delete', $edit, t('Delete'));
$message = t('The image style %name has been deleted.', array('%name' => $new_style_label));
$message = t('The image style %name has been deleted.', ['%name' => $new_style_label]);
$this->assertRaw($message);
$replacement_style = ImageStyle::load('thumbnail');
@ -392,18 +392,18 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
/**
* Verifies that editing an image effect does not cause it to be duplicated.
*/
function testEditEffect() {
public function testEditEffect() {
// Add a scale effect.
$style_name = 'test_style_effect_edit';
$this->drupalGet('admin/config/media/image-styles/add');
$this->drupalPostForm(NULL, array('label' => 'Test style effect edit', 'name' => $style_name), t('Create new style'));
$this->drupalPostForm(NULL, array('new' => 'image_scale_and_crop'), t('Add'));
$this->drupalPostForm(NULL, array('data[width]' => '300', 'data[height]' => '200'), t('Add effect'));
$this->drupalPostForm(NULL, ['label' => 'Test style effect edit', 'name' => $style_name], t('Create new style'));
$this->drupalPostForm(NULL, ['new' => 'image_scale_and_crop'], t('Add'));
$this->drupalPostForm(NULL, ['data[width]' => '300', 'data[height]' => '200'], t('Add effect'));
$this->assertText(t('Scale and crop 300×200'));
// There should normally be only one edit link on this page initially.
$this->clickLink(t('Edit'));
$this->drupalPostForm(NULL, array('data[width]' => '360', 'data[height]' => '240'), t('Update effect'));
$this->drupalPostForm(NULL, ['data[width]' => '360', 'data[height]' => '240'], t('Update effect'));
$this->assertText(t('Scale and crop 360×240'));
// Check that the previous effect is replaced.
@ -411,17 +411,17 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Add another scale effect.
$this->drupalGet('admin/config/media/image-styles/add');
$this->drupalPostForm(NULL, array('label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'), t('Create new style'));
$this->drupalPostForm(NULL, array('new' => 'image_scale'), t('Add'));
$this->drupalPostForm(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect'));
$this->drupalPostForm(NULL, ['label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'], t('Create new style'));
$this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add'));
$this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect'));
// Edit the scale effect that was just added.
$this->clickLink(t('Edit'));
$this->drupalPostForm(NULL, array('data[width]' => '24', 'data[height]' => '19'), t('Update effect'));
$this->drupalPostForm(NULL, array('new' => 'image_scale'), t('Add'));
$this->drupalPostForm(NULL, ['data[width]' => '24', 'data[height]' => '19'], t('Update effect'));
$this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add'));
// Add another scale effect and make sure both exist.
$this->drupalPostForm(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect'));
$this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect'));
$this->assertText(t('Scale 24×19'));
$this->assertText(t('Scale 12×19'));
@ -439,7 +439,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Create a new style.
$style_name = strtolower($this->randomMachineName(10));
$style = ImageStyle::create(array('name' => $style_name, 'label' => $this->randomString()));
$style = ImageStyle::create(['name' => $style_name, 'label' => $this->randomString()]);
$style->save();
// Create an image to make sure it gets flushed.
@ -456,7 +456,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
$this->assertLinkByHref($flush_path);
// Flush the image style derivatives using the user interface.
$this->drupalPostForm($flush_path, array(), t('Flush'));
$this->drupalPostForm($flush_path, [], t('Flush'));
// The derivative image file should have been deleted.
$this->assertEqual($this->getImageCount($style), 0);
@ -465,21 +465,21 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
/**
* Tests image style configuration import that does a delete.
*/
function testConfigImport() {
public function testConfigImport() {
// Create a new style.
$style_name = strtolower($this->randomMachineName(10));
$style_label = $this->randomString();
$style = ImageStyle::create(array('name' => $style_name, 'label' => $style_label));
$style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]);
$style->save();
// Create an image field that uses the new style.
$field_name = strtolower($this->randomMachineName(10));
$this->createImageField($field_name, 'article');
entity_get_display('node', 'article', 'default')
->setComponent($field_name, array(
->setComponent($field_name, [
'type' => 'image',
'settings' => array('image_style' => $style_name),
))
'settings' => ['image_style' => $style_name],
])
->save();
// Create a new node with an image attached.
@ -493,7 +493,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
// Test that image is displayed using newly created style.
$this->drupalGet('node/' . $nid);
$this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', array('@style' => $style_name)));
$this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name]));
// Copy config to sync, and delete the image style.
$sync = $this->container->get('config.storage.sync');
@ -515,7 +515,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
* Tests access for the image style listing.
*/
public function testImageStyleAccess() {
$style = ImageStyle::create(array('name' => 'style_foo', 'label' => $this->randomString()));
$style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]);
$style->save();
$this->drupalGet('admin/config/media/image-styles');

View file

@ -17,14 +17,14 @@ class ImageDimensionsTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('image', 'image_module_test');
public static $modules = ['image', 'image_module_test'];
protected $profile = 'testing';
/**
* Test styled image dimensions cumulatively.
*/
function testImageDimensions() {
public function testImageDimensions() {
$image_factory = $this->container->get('image.factory');
// Create a working copy of the file.
$files = $this->drupalGetTestFiles('image');
@ -33,33 +33,33 @@ class ImageDimensionsTest extends WebTestBase {
// Create a style.
/** @var $style \Drupal\image\ImageStyleInterface */
$style = ImageStyle::create(array('name' => 'test', 'label' => 'Test'));
$style = ImageStyle::create(['name' => 'test', 'label' => 'Test']);
$style->save();
$generated_uri = 'public://styles/test/public/' . \Drupal::service('file_system')->basename($original_uri);
$url = file_url_transform_relative($style->buildUrl($original_uri));
$variables = array(
$variables = [
'#theme' => 'image_style',
'#style_name' => 'test',
'#uri' => $original_uri,
'#width' => 40,
'#height' => 20,
);
];
// Verify that the original image matches the hard-coded values.
$image_file = $image_factory->get($original_uri);
$this->assertEqual($image_file->getWidth(), $variables['#width']);
$this->assertEqual($image_file->getHeight(), $variables['#height']);
// Scale an image that is wider than it is high.
$effect = array(
$effect = [
'id' => 'image_scale',
'data' => array(
'data' => [
'width' => 120,
'height' => 90,
'upscale' => TRUE,
),
],
'weight' => 0,
);
];
$style->addImageEffect($effect);
$style->save();
@ -73,14 +73,14 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 60);
// Rotate 90 degrees anticlockwise.
$effect = array(
$effect = [
'id' => 'image_rotate',
'data' => array(
'data' => [
'degrees' => -90,
'random' => FALSE,
),
],
'weight' => 1,
);
];
$style->addImageEffect($effect);
$style->save();
@ -94,15 +94,15 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 120);
// Scale an image that is higher than it is wide (rotated by previous effect).
$effect = array(
$effect = [
'id' => 'image_scale',
'data' => array(
'data' => [
'width' => 120,
'height' => 90,
'upscale' => TRUE,
),
],
'weight' => 2,
);
];
$style->addImageEffect($effect);
$style->save();
@ -116,15 +116,15 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 90);
// Test upscale disabled.
$effect = array(
$effect = [
'id' => 'image_scale',
'data' => array(
'data' => [
'width' => 400,
'height' => 200,
'upscale' => FALSE,
),
],
'weight' => 3,
);
];
$style->addImageEffect($effect);
$style->save();
@ -138,11 +138,11 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 90);
// Add a desaturate effect.
$effect = array(
$effect = [
'id' => 'image_desaturate',
'data' => array(),
'data' => [],
'weight' => 4,
);
];
$style->addImageEffect($effect);
$style->save();
@ -156,14 +156,14 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 90);
// Add a random rotate effect.
$effect = array(
$effect = [
'id' => 'image_rotate',
'data' => array(
'data' => [
'degrees' => 180,
'random' => TRUE,
),
],
'weight' => 5,
);
];
$style->addImageEffect($effect);
$style->save();
@ -175,15 +175,15 @@ class ImageDimensionsTest extends WebTestBase {
// Add a crop effect.
$effect = array(
$effect = [
'id' => 'image_crop',
'data' => array(
'data' => [
'width' => 30,
'height' => 30,
'anchor' => 'center-center',
),
],
'weight' => 6,
);
];
$style->addImageEffect($effect);
$style->save();
@ -197,14 +197,14 @@ class ImageDimensionsTest extends WebTestBase {
$this->assertEqual($image_file->getHeight(), 30);
// Rotate to a non-multiple of 90 degrees.
$effect = array(
$effect = [
'id' => 'image_rotate',
'data' => array(
'data' => [
'degrees' => 57,
'random' => FALSE,
),
],
'weight' => 7,
);
];
$effect_id = $style->addImageEffect($effect);
$style->save();
@ -221,11 +221,11 @@ class ImageDimensionsTest extends WebTestBase {
$style->deleteImageEffect($effect_plugin);
// Ensure that an effect can unset dimensions.
$effect = array(
$effect = [
'id' => 'image_module_test_null',
'data' => array(),
'data' => [],
'weight' => 8,
);
];
$style->addImageEffect($effect);
$style->save();

View file

@ -19,7 +19,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
*
* @var array
*/
public static $modules = array('field_ui');
public static $modules = ['field_ui'];
/**
* Tests CRUD for fields and fields fields with default images.
@ -36,8 +36,8 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$file = File::create(['uri' => $desired_filepath, 'filename' => $filename, 'name' => $filename]);
$file->save();
}
$default_images = array();
foreach (array('field', 'field', 'field2', 'field_new', 'field_new') as $image_target) {
$default_images = [];
foreach (['field', 'field', 'field2', 'field_new', 'field_new'] as $image_target) {
$file = File::create((array) array_pop($files));
$file->save();
$default_images[$image_target] = $file;
@ -45,23 +45,23 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
// Create an image field and add an field to the article content type.
$field_name = strtolower($this->randomMachineName());
$storage_settings['default_image'] = array(
$storage_settings['default_image'] = [
'uuid' => $default_images['field']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
'height' => 0,
);
$field_settings['default_image'] = array(
];
$field_settings['default_image'] = [
'uuid' => $default_images['field']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
'height' => 0,
);
$widget_settings = array(
];
$widget_settings = [
'preview_image_style' => 'medium',
);
];
$field = $this->createImageField($field_name, 'article', $storage_settings, $field_settings, $widget_settings);
// The field default image id should be 2.
@ -84,15 +84,15 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
'bundle' => 'page',
'label' => $field->label(),
'required' => $field->isRequired(),
'settings' => array(
'default_image' => array(
'settings' => [
'default_image' => [
'uuid' => $default_images['field2']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
'height' => 0,
),
),
],
],
]);
$field2->save();
@ -112,7 +112,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field']->id(),
format_string(
'Article image field default equals expected file ID of @fid.',
array('@fid' => $default_images['field']->id())
['@fid' => $default_images['field']->id()]
)
);
// Confirm the defaults are present on the article field edit form.
@ -122,7 +122,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field']->id(),
format_string(
'Article image field field default equals expected file ID of @fid.',
array('@fid' => $default_images['field']->id())
['@fid' => $default_images['field']->id()]
)
);
@ -133,7 +133,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field']->id(),
format_string(
'Page image field default equals expected file ID of @fid.',
array('@fid' => $default_images['field']->id())
['@fid' => $default_images['field']->id()]
)
);
// Confirm the defaults are present on the page field edit form.
@ -144,38 +144,38 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field2']->id(),
format_string(
'Page image field field default equals expected file ID of @fid.',
array('@fid' => $default_images['field2']->id())
['@fid' => $default_images['field2']->id()]
)
);
// Confirm that the image default is shown for a new article node.
$article = $this->drupalCreateNode(array('type' => 'article'));
$article = $this->drupalCreateNode(['type' => 'article']);
$article_built = $this->drupalBuildEntityView($article);
$this->assertEqual(
$article_built[$field_name][0]['#item']->target_id,
$default_images['field']->id(),
format_string(
'A new article node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field']->id())
['@fid' => $default_images['field']->id()]
)
);
// Also check that the field renders without warnings when the label is
// hidden.
EntityViewDisplay::load('node.article.default')
->setComponent($field_name, array('label' => 'hidden', 'type' => 'image'))
->setComponent($field_name, ['label' => 'hidden', 'type' => 'image'])
->save();
$this->drupalGet('node/' . $article->id());
// Confirm that the image default is shown for a new page node.
$page = $this->drupalCreateNode(array('type' => 'page'));
$page = $this->drupalCreateNode(['type' => 'page']);
$page_built = $this->drupalBuildEntityView($page);
$this->assertEqual(
$page_built[$field_name][0]['#item']->target_id,
$default_images['field2']->id(),
format_string(
'A new page node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field2']->id())
['@fid' => $default_images['field2']->id()]
)
);
@ -192,12 +192,12 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field_new']->id(),
format_string(
'Updated image field default equals expected file ID of @fid.',
array('@fid' => $default_images['field_new']->id())
['@fid' => $default_images['field_new']->id()]
)
);
// Reload the nodes and confirm the field field defaults are used.
$node_storage->resetCache(array($article->id(), $page->id()));
$node_storage->resetCache([$article->id(), $page->id()]);
$article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id()));
$page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id()));
$this->assertEqual(
@ -205,7 +205,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field']->id(),
format_string(
'An existing article node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field']->id())
['@fid' => $default_images['field']->id()]
)
);
$this->assertEqual(
@ -213,7 +213,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field2']->id(),
format_string(
'An existing page node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field2']->id())
['@fid' => $default_images['field2']->id()]
)
);
@ -231,12 +231,12 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field_new']->id(),
format_string(
'Updated article image field field default equals expected file ID of @fid.',
array('@fid' => $default_images['field_new']->id())
['@fid' => $default_images['field_new']->id()]
)
);
// Reload the nodes.
$node_storage->resetCache(array($article->id(), $page->id()));
$node_storage->resetCache([$article->id(), $page->id()]);
$article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id()));
$page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id()));
@ -246,7 +246,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field_new']->id(),
format_string(
'An existing article node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field_new']->id())
['@fid' => $default_images['field_new']->id()]
)
);
// Confirm the page remains unchanged.
@ -255,7 +255,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field2']->id(),
format_string(
'An existing page node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field2']->id())
['@fid' => $default_images['field2']->id()]
)
);
@ -279,7 +279,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
);
// Reload the nodes.
$node_storage->resetCache(array($article->id(), $page->id()));
$node_storage->resetCache([$article->id(), $page->id()]);
$article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id()));
$page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id()));
// Confirm the article uses the new field (not field) default.
@ -288,7 +288,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field_new']->id(),
format_string(
'An existing article node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field_new']->id())
['@fid' => $default_images['field_new']->id()]
)
);
// Confirm the page remains unchanged.
@ -297,12 +297,12 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$default_images['field2']->id(),
format_string(
'An existing page node without an image has the expected default image file ID of @fid.',
array('@fid' => $default_images['field2']->id())
['@fid' => $default_images['field2']->id()]
)
);
$non_image = $this->drupalGetTestFiles('text');
$this->drupalPostForm(NULL, array('files[settings_default_image_uuid]' => drupal_realpath($non_image[0]->uri)), t("Upload"));
$this->drupalPostForm(NULL, ['files[settings_default_image_uuid]' => drupal_realpath($non_image[0]->uri)], t("Upload"));
$this->assertText('The specified file text-0.txt could not be uploaded.');
$this->assertText('Only files with the following extensions are allowed: png gif jpg jpeg.');
@ -316,16 +316,16 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
* Tests image field and field having an invalid default image.
*/
public function testInvalidDefaultImage() {
$field_storage = FieldStorageConfig::create(array(
$field_storage = FieldStorageConfig::create([
'field_name' => Unicode::strtolower($this->randomMachineName()),
'entity_type' => 'node',
'type' => 'image',
'settings' => array(
'default_image' => array(
'settings' => [
'default_image' => [
'uuid' => 100000,
)
),
));
]
],
]);
$field_storage->save();
$settings = $field_storage->getSettings();
// The non-existent default image should not be saved.
@ -335,11 +335,11 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
'field_storage' => $field_storage,
'bundle' => 'page',
'label' => $this->randomMachineName(),
'settings' => array(
'default_image' => array(
'settings' => [
'default_image' => [
'uuid' => 100000,
)
),
]
],
]);
$field->save();
$settings = $field->getSettings();

View file

@ -21,55 +21,55 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
*
* @var array
*/
public static $modules = array('field_ui');
public static $modules = ['field_ui'];
/**
* Test image formatters on node display for public files.
*/
function testImageFieldFormattersPublic() {
public function testImageFieldFormattersPublic() {
$this->_testImageFieldFormatters('public');
}
/**
* Test image formatters on node display for private files.
*/
function testImageFieldFormattersPrivate() {
public function testImageFieldFormattersPrivate() {
// Remove access content permission from anonymous users.
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access content' => FALSE));
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, ['access content' => FALSE]);
$this->_testImageFieldFormatters('private');
}
/**
* Test image formatters on node display.
*/
function _testImageFieldFormatters($scheme) {
public function _testImageFieldFormatters($scheme) {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
$node_storage = $this->container->get('entity.manager')->getStorage('node');
$field_name = strtolower($this->randomMachineName());
$field_settings = array('alt_field_required' => 0);
$instance = $this->createImageField($field_name, 'article', array('uri_scheme' => $scheme), $field_settings);
$field_settings = ['alt_field_required' => 0];
$instance = $this->createImageField($field_name, 'article', ['uri_scheme' => $scheme], $field_settings);
// Go to manage display page.
$this->drupalGet("admin/structure/types/manage/article/display");
// Test for existence of link to image styles configuration.
$this->drupalPostAjaxForm(NULL, array(), "{$field_name}_settings_edit");
$this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit");
$this->assertLinkByHref(\Drupal::url('entity.image_style.collection'), 0, 'Link to image styles configuration is found');
// Remove 'administer image styles' permission from testing admin user.
$admin_user_roles = $this->adminUser->getRoles(TRUE);
user_role_change_permissions(reset($admin_user_roles), array('administer image styles' => FALSE));
user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => FALSE]);
// Go to manage display page again.
$this->drupalGet("admin/structure/types/manage/article/display");
// Test for absence of link to image styles configuration.
$this->drupalPostAjaxForm(NULL, array(), "{$field_name}_settings_edit");
$this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit");
$this->assertNoLinkByHref(\Drupal::url('entity.image_style.collection'), 'Link to image styles configuration is absent when permissions are insufficient');
// Restore 'administer image styles' permission to testing admin user
user_role_change_permissions(reset($admin_user_roles), array('administer image styles' => TRUE));
user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => TRUE]);
// Create a new node with an image attached.
$test_image = current($this->drupalGetTestFiles('image'));
@ -87,38 +87,38 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Save node.
$nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
$node_storage->resetCache(array($nid));
$node_storage->resetCache([$nid]);
$node = $node_storage->load($nid);
// Test that the default formatter is being used.
$file = $node->{$field_name}->entity;
$image_uri = $file->getFileUri();
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $image_uri,
'#width' => 40,
'#height' => 20,
'#alt' => $alt,
);
];
$default_output = str_replace("\n", NULL, $renderer->renderRoot($image));
$this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.');
// Test the image linked to file formatter.
$display_options = array(
$display_options = [
'type' => 'image',
'settings' => array('image_link' => 'file'),
);
'settings' => ['image_link' => 'file'],
];
$display = entity_get_display('node', $node->getType(), 'default');
$display->setComponent($field_name, $display_options)
->save();
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $image_uri,
'#width' => 40,
'#height' => 20,
'#alt' => $alt,
);
];
$default_output = '<a href="' . file_create_url($image_uri) . '">' . $renderer->renderRoot($image) . '</a>';
$this->drupalGet('node/' . $nid);
$this->assertCacheTag($file->getCacheTags()[0]);
@ -148,25 +148,25 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$display_options['settings']['image_link'] = 'content';
$display->setComponent($field_name, $display_options)
->save();
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $image_uri,
'#width' => 40,
'#height' => 20,
);
];
$this->drupalGet('node/' . $nid);
$this->assertCacheTag($file->getCacheTags()[0]);
$cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
$this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
$elements = $this->xpath(
'//a[@href=:path]/img[@src=:url and @alt=:alt and @width=:width and @height=:height]',
array(
[
':path' => $node->url(),
':url' => file_url_transform_relative(file_create_url($image['#uri'])),
':width' => $image['#width'],
':height' => $image['#height'],
':alt' => $alt,
)
]
);
$this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.');
@ -179,14 +179,14 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Ensure the derivative image is generated so we do not have to deal with
// image style callback paths.
$this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri));
$image_style = array(
$image_style = [
'#theme' => 'image_style',
'#uri' => $image_uri,
'#width' => 40,
'#height' => 20,
'#style_name' => 'thumbnail',
'#alt' => $alt,
);
];
$default_output = $renderer->renderRoot($image_style);
$this->drupalGet('node/' . $nid);
$image_style = ImageStyle::load('thumbnail');
@ -199,30 +199,43 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri));
$this->assertResponse('403', 'Access denied to image style thumbnail as anonymous user.');
}
// Test the image URL formatter without an image style.
$display_options = [
'type' => 'image_url',
'settings' => ['image_style' => ''],
];
$expected_url = file_url_transform_relative(file_create_url($image_uri));
$this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']);
// Test the image URL formatter with an image style.
$display_options['settings']['image_style'] = 'thumbnail';
$expected_url = file_url_transform_relative(ImageStyle::load('thumbnail')->buildUrl($image_uri));
$this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']);
}
/**
* Tests for image field settings.
*/
function testImageFieldSettings() {
public function testImageFieldSettings() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
$node_storage = $this->container->get('entity.manager')->getStorage('node');
$test_image = current($this->drupalGetTestFiles('image'));
list(, $test_image_extension) = explode('.', $test_image->filename);
$field_name = strtolower($this->randomMachineName());
$field_settings = array(
$field_settings = [
'alt_field' => 1,
'file_extensions' => $test_image_extension,
'max_filesize' => '50 KB',
'max_resolution' => '100x100',
'min_resolution' => '10x10',
'title_field' => 1,
);
$widget_settings = array(
];
$widget_settings = [
'preview_image_style' => 'medium',
);
$field = $this->createImageField($field_name, 'article', array(), $field_settings, $widget_settings);
];
$field = $this->createImageField($field_name, 'article', [], $field_settings, $widget_settings);
// Verify that the min/max resolution set on the field are properly
// extracted, and displayed, on the image field's configuration form.
@ -234,7 +247,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->drupalGet('node/add/article');
$this->assertText(t('50 KB limit.'), 'Image widget max file size is displayed on article form.');
$this->assertText(t('Allowed types: @extensions.', array('@extensions' => $test_image_extension)), 'Image widget allowed file types displayed on article form.');
$this->assertText(t('Allowed types: @extensions.', ['@extensions' => $test_image_extension]), 'Image widget allowed file types displayed on article form.');
$this->assertText(t('Images must be larger than 10x10 pixels. Images larger than 100x100 pixels will be resized.'), 'Image widget allowed resolution displayed on article form.');
// We have to create the article first and then edit it because the alt
@ -249,7 +262,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.');
// Verify that the attached image is being previewed using the 'medium'
// style.
$node_storage->resetCache(array($nid));
$node_storage->resetCache([$nid]);
$node = $node_storage->load($nid);
$file = $node->{$field_name}->entity;
@ -257,38 +270,38 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->assertTrue($this->cssSelect('img[width=40][height=20][class=image-style-medium][src="' . $url . '"]'));
// Add alt/title fields to the image and verify that they are displayed.
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $file->getFileUri(),
'#alt' => $alt,
'#title' => $this->randomMachineName(),
'#width' => 40,
'#height' => 20,
);
$edit = array(
];
$edit = [
$field_name . '[0][alt]' => $image['#alt'],
$field_name . '[0][title]' => $image['#title'],
);
];
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$default_output = str_replace("\n", NULL, $renderer->renderRoot($image));
$this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.');
// Verify that alt/title longer than allowed results in a validation error.
$test_size = 2000;
$edit = array(
$edit = [
$field_name . '[0][alt]' => $this->randomMachineName($test_size),
$field_name . '[0][title]' => $this->randomMachineName($test_size),
);
];
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$schema = $field->getFieldStorageDefinition()->getSchema();
$this->assertRaw(t('Alternative text cannot be longer than %max characters but is currently %length characters long.', array(
$this->assertRaw(t('Alternative text cannot be longer than %max characters but is currently %length characters long.', [
'%max' => $schema['columns']['alt']['length'],
'%length' => $test_size,
)));
$this->assertRaw(t('Title cannot be longer than %max characters but is currently %length characters long.', array(
]));
$this->assertRaw(t('Title cannot be longer than %max characters but is currently %length characters long.', [
'%max' => $schema['columns']['title']['length'],
'%length' => $test_size,
)));
]));
// Set cardinality to unlimited and add upload a second image.
// The image widget is extending on the file widget, but the image field
@ -297,20 +310,20 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// 1, so we need to make sure the file widget prevents these notices by
// providing all settings, even if they are not used.
// @see FileWidget::formMultipleElements().
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $field_name . '/storage', array('cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED), t('Save field settings'));
$edit = array(
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $field_name . '/storage', ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED], t('Save field settings'));
$edit = [
'files[' . $field_name . '_1][]' => drupal_realpath($test_image->uri),
);
];
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
// Add the required alt text.
$this->drupalPostForm(NULL, [$field_name . '[1][alt]' => $alt], t('Save and keep published'));
$this->assertText(format_string('Article @title has been updated.', array('@title' => $node->getTitle())));
$this->assertText(format_string('Article @title has been updated.', ['@title' => $node->getTitle()]));
// Assert ImageWidget::process() calls FieldWidget::process().
$this->drupalGet('node/' . $node->id() . '/edit');
$edit = array(
$edit = [
'files[' . $field_name . '_2][]' => drupal_realpath($test_image->uri),
);
];
$this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button');
$this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="js-form-file form-file">');
$this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="js-form-file form-file">');
@ -319,7 +332,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
/**
* Test use of a default image with an image field.
*/
function testImageFieldDefaultImage() {
public function testImageFieldDefaultImage() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
@ -330,7 +343,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Create a new node, with no images and verify that no images are
// displayed.
$node = $this->drupalCreateNode(array('type' => 'article'));
$node = $this->drupalCreateNode(['type' => 'article']);
$this->drupalGet('node/' . $node->id());
// Verify that no image is displayed on the page by checking for the class
// that would be used on the image field.
@ -342,12 +355,12 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$images = $this->drupalGetTestFiles('image');
$alt = $this->randomString(512);
$title = $this->randomString(1024);
$edit = array(
$edit = [
// Get the path of the 'image-test.png' file.
'files[settings_default_image_uuid]' => drupal_realpath($images[0]->uri),
'settings[default_image][alt]' => $alt,
'settings[default_image][title]' => $title,
);
];
$this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings'));
// Clear field definition cache so the new default image is detected.
\Drupal::entityManager()->clearCachedFieldDefinitions();
@ -355,14 +368,14 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$default_image = $field_storage->getSetting('default_image');
$file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']);
$this->assertTrue($file->isPermanent(), 'The default image status is permanent.');
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $file->getFileUri(),
'#alt' => $alt,
'#title' => $title,
'#width' => 40,
'#height' => 20,
);
];
$default_output = str_replace("\n", NULL, $renderer->renderRoot($image));
$this->drupalGet('node/' . $node->id());
$this->assertCacheTag($file->getCacheTags()[0]);
@ -378,16 +391,16 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Upload the 'image-test.gif' file.
$nid = $this->uploadNodeImage($images[2], $field_name, 'article', $alt);
$node_storage->resetCache(array($nid));
$node_storage->resetCache([$nid]);
$node = $node_storage->load($nid);
$file = $node->{$field_name}->entity;
$image = array(
$image = [
'#theme' => 'image',
'#uri' => $file->getFileUri(),
'#width' => 40,
'#height' => 20,
'#alt' => $alt,
);
];
$image_output = str_replace("\n", NULL, $renderer->renderRoot($image));
$this->drupalGet('node/' . $nid);
$this->assertCacheTag($file->getCacheTags()[0]);
@ -397,9 +410,9 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->assertRaw($image_output, 'User supplied image is displayed.');
// Remove default image from the field and make sure it is no longer used.
$edit = array(
$edit = [
'settings[default_image][uuid][fids]' => 0,
);
];
$this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings'));
// Clear field definition cache so the new default image is detected.
\Drupal::entityManager()->clearCachedFieldDefinitions();
@ -409,14 +422,14 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Create an image field that uses the private:// scheme and test that the
// default image works as expected.
$private_field_name = strtolower($this->randomMachineName());
$this->createImageField($private_field_name, 'article', array('uri_scheme' => 'private'));
$this->createImageField($private_field_name, 'article', ['uri_scheme' => 'private']);
// Add a default image to the new field.
$edit = array(
$edit = [
// Get the path of the 'image-test.gif' file.
'files[settings_default_image_uuid]' => drupal_realpath($images[2]->uri),
'settings[default_image][alt]' => $alt,
'settings[default_image][title]' => $title,
);
];
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $private_field_name . '/storage', $edit, t('Save field settings'));
// Clear field definition cache so the new default image is detected.
\Drupal::entityManager()->clearCachedFieldDefinitions();
@ -428,15 +441,15 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$this->assertTrue($file->isPermanent(), 'The default image status is permanent.');
// Create a new node with no image attached and ensure that default private
// image is displayed.
$node = $this->drupalCreateNode(array('type' => 'article'));
$image = array(
$node = $this->drupalCreateNode(['type' => 'article']);
$image = [
'#theme' => 'image',
'#uri' => $file->getFileUri(),
'#alt' => $alt,
'#title' => $title,
'#width' => 40,
'#height' => 20,
);
];
$default_output = str_replace("\n", NULL, $renderer->renderRoot($image));
$this->drupalGet('node/' . $node->id());
$this->assertCacheTag($file->getCacheTags()[0]);

View file

@ -20,6 +20,9 @@ use Drupal\simpletest\WebTestBase;
/**
* This class provides methods specifically for testing Image's field handling.
*
* @deprecated Scheduled for removal in Drupal 9.0.0.
* Use \Drupal\Tests\image\Functional\ImageFieldTestBase instead.
*/
abstract class ImageFieldTestBase extends WebTestBase {
@ -30,7 +33,7 @@ abstract class ImageFieldTestBase extends WebTestBase {
*
* @var array
*/
public static $modules = array('node', 'image', 'field_ui', 'image_module_test');
public static $modules = ['node', 'image', 'field_ui', 'image_module_test'];
/**
* An user with permissions to administer content types and image styles.
@ -44,11 +47,11 @@ abstract class ImageFieldTestBase extends WebTestBase {
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
$this->adminUser = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer node fields', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer node display'));
$this->adminUser = $this->drupalCreateUser(['access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer node fields', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer node display']);
$this->drupalLogin($this->adminUser);
}
@ -62,10 +65,10 @@ abstract class ImageFieldTestBase extends WebTestBase {
* @param string $type
* The type of node to create.
*/
function previewNodeImage($image, $field_name, $type) {
$edit = array(
public function previewNodeImage($image, $field_name, $type) {
$edit = [
'title[0][value]' => $this->randomMachineName(),
);
];
$edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('node/add/' . $type, $edit, t('Preview'));
}
@ -82,10 +85,10 @@ abstract class ImageFieldTestBase extends WebTestBase {
* @param $alt
* The alt text for the image. Use if the field settings require alt text.
*/
function uploadNodeImage($image, $field_name, $type, $alt = '') {
$edit = array(
public function uploadNodeImage($image, $field_name, $type, $alt = '') {
$edit = [
'title[0][value]' => $this->randomMachineName(),
);
];
$edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish'));
if ($alt) {
@ -94,7 +97,7 @@ abstract class ImageFieldTestBase extends WebTestBase {
}
// Retrieve ID of the newly created node from the current URL.
$matches = array();
$matches = [];
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
return isset($matches[1]) ? $matches[1] : FALSE;
}

View file

@ -11,7 +11,7 @@ class ImageFieldValidateTest extends ImageFieldTestBase {
/**
* Test min/max resolution settings.
*/
function testResolution() {
public function testResolution() {
$field_names = [
0 => strtolower($this->randomMachineName()),
1 => strtolower($this->randomMachineName()),
@ -85,16 +85,16 @@ class ImageFieldValidateTest extends ImageFieldTestBase {
/**
* Test that required alt/title fields gets validated right.
*/
function testRequiredAttributes() {
public function testRequiredAttributes() {
$field_name = strtolower($this->randomMachineName());
$field_settings = array(
$field_settings = [
'alt_field' => 1,
'alt_field_required' => 1,
'title_field' => 1,
'title_field_required' => 1,
'required' => 1,
);
$instance = $this->createImageField($field_name, 'article', array(), $field_settings);
];
$instance = $this->createImageField($field_name, 'article', [], $field_settings);
$images = $this->drupalGetTestFiles('image');
// Let's just use the first image.
$image = $images[0];
@ -116,9 +116,9 @@ class ImageFieldValidateTest extends ImageFieldTestBase {
$instance->setSetting('title_field_required', 0);
$instance->save();
$edit = array(
$edit = [
'title[0][value]' => $this->randomMachineName(),
);
];
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
$this->assertNoText(t('Alternative text field is required.'));
@ -129,9 +129,9 @@ class ImageFieldValidateTest extends ImageFieldTestBase {
$instance->setSetting('title_field_required', 1);
$instance->save();
$edit = array(
$edit = [
'title[0][value]' => $this->randomMachineName(),
);
];
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
$this->assertNoText(t('Alternative text field is required.'));

View file

@ -14,7 +14,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('language', 'content_translation', 'field_ui');
public static $modules = ['language', 'content_translation', 'field_ui'];
/**
* The name of the image field used in the test.
@ -39,7 +39,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->createImageField($this->fieldName, 'basicpage', [], ['title_field' => 1]);
// Create and log in user.
$permissions = array(
$permissions = [
'access administration pages',
'administer content translation',
'administer content types',
@ -50,16 +50,16 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
'edit any basicpage content',
'translate any entity',
'delete any basicpage content',
);
];
$admin_user = $this->drupalCreateUser($permissions);
$this->drupalLogin($admin_user);
// Add a second and third language.
$edit = array();
$edit = [];
$edit['predefined_langcode'] = 'fr';
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
$edit = array();
$edit = [];
$edit['predefined_langcode'] = 'nl';
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
}
@ -69,7 +69,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
*/
public function testSyncedImages() {
// Enable translation for "Basic page" nodes.
$edit = array(
$edit = [
'entity_types[node]' => 1,
'settings[node][basicpage][translatable]' => 1,
"settings[node][basicpage][fields][$this->fieldName]" => 1,
@ -78,7 +78,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
// checkboxes on the form.
"settings[node][basicpage][columns][$this->fieldName][alt]" => FALSE,
"settings[node][basicpage][columns][$this->fieldName][title]" => FALSE,
);
];
$this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration');
// Verify that the image field on the "Basic basic" node type is
@ -87,10 +87,10 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node image field is translatable.');
// Create a default language node.
$default_language_node = $this->drupalCreateNode(array('type' => 'basicpage', 'title' => 'Lost in translation'));
$default_language_node = $this->drupalCreateNode(['type' => 'basicpage', 'title' => 'Lost in translation']);
// Edit the node to upload a file.
$edit = array();
$edit = [];
$name = 'files[' . $this->fieldName . '_0]';
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('image')[0]->uri);
$this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save'));
@ -99,10 +99,10 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$first_fid = $this->getLastFileId();
// Translate the node into French: remove the existing file.
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', array(), t('Remove'));
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', [], t('Remove'));
// Upload a different file.
$edit = array();
$edit = [];
$edit['title[0][value]'] = 'Scarlett Johansson';
$name = 'files[' . $this->fieldName . '_0]';
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('image')[1]->uri);
@ -131,10 +131,10 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->assertTrue($file->isPermanent());
// Translate the node into dutch: remove the existing file.
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', array(), t('Remove'));
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', [], t('Remove'));
// Upload a different file.
$edit = array();
$edit = [];
$edit['title[0][value]'] = 'Akiko Takeshita';
$name = 'files[' . $this->fieldName . '_0]';
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('image')[2]->uri);
@ -166,10 +166,10 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->assertTrue($file->isPermanent());
// Edit the second translation: remove the existing file.
$this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', array(), t('Remove'));
$this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', [], t('Remove'));
// Upload a different file.
$edit = array();
$edit = [];
$edit['title[0][value]'] = 'Giovanni Ribisi';
$name = 'files[' . $this->fieldName . '_0]';
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('image')[3]->uri);
@ -194,7 +194,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->assertTrue($file->isPermanent());
// Delete the third translation.
$this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', array(), t('Delete Dutch translation'));
$this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', [], t('Delete Dutch translation'));
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
@ -210,7 +210,7 @@ class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
$this->assertTrue($file->isTemporary());
// Delete the all translations.
$this->drupalPostForm('node/' . $default_language_node->id() . '/delete', array(), t('Delete all translations'));
$this->drupalPostForm('node/' . $default_language_node->id() . '/delete', [], t('Delete all translations'));
\Drupal::entityTypeManager()->getStorage('file')->resetCache();

View file

@ -14,7 +14,7 @@ class ImageStyleFlushTest extends ImageFieldTestBase {
/**
* Given an image style and a wrapper, generate an image.
*/
function createSampleImage($style, $wrapper) {
public function createSampleImage($style, $wrapper) {
static $file;
if (!isset($file)) {
@ -34,42 +34,42 @@ class ImageStyleFlushTest extends ImageFieldTestBase {
/**
* Count the number of images currently created for a style in a wrapper.
*/
function getImageCount($style, $wrapper) {
public function getImageCount($style, $wrapper) {
return count(file_scan_directory($wrapper . '://styles/' . $style->id(), '/.*/'));
}
/**
* General test to flush a style.
*/
function testFlush() {
public function testFlush() {
// 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/config/media/image-styles/manage/' . $style_name;
$effect_edits = array(
'image_resize' => array(
$effect_edits = [
'image_resize' => [
'data[width]' => 100,
'data[height]' => 101,
),
'image_scale' => array(
],
'image_scale' => [
'data[width]' => 110,
'data[height]' => 111,
'data[upscale]' => 1,
),
);
],
];
// Add style form.
$edit = array(
$edit = [
'name' => $style_name,
'label' => $style_label,
);
];
$this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style'));
// Add each sample effect to the style.
foreach ($effect_edits as $effect => $edit) {
// Add the effect.
$this->drupalPostForm($style_path, array('new' => $effect), t('Add'));
$this->drupalPostForm($style_path, ['new' => $effect], t('Add'));
if (!empty($edit)) {
$this->drupalPostForm(NULL, $edit, t('Add effect'));
}
@ -82,29 +82,29 @@ class ImageStyleFlushTest extends ImageFieldTestBase {
$image_path = $this->createSampleImage($style, 'public');
// Expecting to find 2 images, one is the sample.png image shown in
// image style preview.
$this->assertEqual($this->getImageCount($style, 'public'), 2, format_string('Image style %style image %file successfully generated.', array('%style' => $style->label(), '%file' => $image_path)));
$this->assertEqual($this->getImageCount($style, 'public'), 2, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path]));
// Create an image for the 'private' wrapper.
$image_path = $this->createSampleImage($style, 'private');
$this->assertEqual($this->getImageCount($style, 'private'), 1, format_string('Image style %style image %file successfully generated.', array('%style' => $style->label(), '%file' => $image_path)));
$this->assertEqual($this->getImageCount($style, 'private'), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path]));
// Remove the 'image_scale' effect and updates the style, which in turn
// forces an image style flush.
$style_path = 'admin/config/media/image-styles/manage/' . $style->id();
$uuids = array();
$uuids = [];
foreach ($style->getEffects() as $uuid => $effect) {
$uuids[$effect->getPluginId()] = $uuid;
}
$this->drupalPostForm($style_path . '/effects/' . $uuids['image_scale'] . '/delete', array(), t('Delete'));
$this->drupalPostForm($style_path . '/effects/' . $uuids['image_scale'] . '/delete', [], t('Delete'));
$this->assertResponse(200);
$this->drupalPostForm($style_path, array(), t('Update style'));
$this->drupalPostForm($style_path, [], t('Update style'));
$this->assertResponse(200);
// Post flush, expected 1 image in the 'public' wrapper (sample.png).
$this->assertEqual($this->getImageCount($style, 'public'), 1, format_string('Image style %style flushed correctly for %wrapper wrapper.', array('%style' => $style->label(), '%wrapper' => 'public')));
$this->assertEqual($this->getImageCount($style, 'public'), 1, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'public']));
// Post flush, expected no image in the 'private' wrapper.
$this->assertEqual($this->getImageCount($style, 'private'), 0, format_string('Image style %style flushed correctly for %wrapper wrapper.', array('%style' => $style->label(), '%wrapper' => 'private')));
$this->assertEqual($this->getImageCount($style, 'private'), 0, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'private']));
}
}

View file

@ -17,7 +17,7 @@ class ImageStylesPathAndUrlTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('image', 'image_module_test');
public static $modules = ['image', 'image_module_test'];
/**
* @var \Drupal\image\ImageStyleInterface
@ -27,14 +27,14 @@ class ImageStylesPathAndUrlTest extends WebTestBase {
protected function setUp() {
parent::setUp();
$this->style = ImageStyle::create(array('name' => 'style_foo', 'label' => $this->randomString()));
$this->style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]);
$this->style->save();
}
/**
* Tests \Drupal\image\ImageStyleInterface::buildUri().
*/
function testImageStylePath() {
public function testImageStylePath() {
$scheme = 'public';
$actual = $this->style->buildUri("$scheme://foo/bar.gif");
$expected = "$scheme://styles/" . $this->style->id() . "/$scheme/foo/bar.gif";
@ -48,42 +48,42 @@ class ImageStylesPathAndUrlTest extends WebTestBase {
/**
* Tests an image style URL using the "public://" scheme.
*/
function testImageStyleUrlAndPathPublic() {
public function testImageStyleUrlAndPathPublic() {
$this->doImageStyleUrlAndPathTests('public');
}
/**
* Tests an image style URL using the "private://" scheme.
*/
function testImageStyleUrlAndPathPrivate() {
public function testImageStyleUrlAndPathPrivate() {
$this->doImageStyleUrlAndPathTests('private');
}
/**
* Tests an image style URL with the "public://" scheme and unclean URLs.
*/
function testImageStyleUrlAndPathPublicUnclean() {
public function testImageStyleUrlAndPathPublicUnclean() {
$this->doImageStyleUrlAndPathTests('public', FALSE);
}
/**
* Tests an image style URL with the "private://" schema and unclean URLs.
*/
function testImageStyleUrlAndPathPrivateUnclean() {
public function testImageStyleUrlAndPathPrivateUnclean() {
$this->doImageStyleUrlAndPathTests('private', FALSE);
}
/**
* Tests an image style URL with a file URL that has an extra slash in it.
*/
function testImageStyleUrlExtraSlash() {
public function testImageStyleUrlExtraSlash() {
$this->doImageStyleUrlAndPathTests('public', TRUE, TRUE);
}
/**
* Tests that an invalid source image returns a 404.
*/
function testImageStyleUrlForMissingSourceImage() {
public function testImageStyleUrlForMissingSourceImage() {
$non_existent_uri = 'public://foo.png';
$generated_url = $this->style->buildUrl($non_existent_uri);
$this->drupalGet($generated_url);
@ -93,7 +93,7 @@ class ImageStylesPathAndUrlTest extends WebTestBase {
/**
* Tests building an image style URL.
*/
function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash = FALSE) {
public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash = FALSE) {
$this->prepareRequestForGenerator($clean_url);
// Make the default scheme neither "public" nor "private" to verify the

View file

@ -23,7 +23,7 @@ class ImageThemeFunctionTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('image', 'entity_test');
public static $modules = ['image', 'entity_test'];
/**
* Created file entity.
@ -40,12 +40,12 @@ class ImageThemeFunctionTest extends WebTestBase {
protected function setUp() {
parent::setUp();
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'image_test',
'type' => 'image',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
))->save();
])->save();
FieldConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'image_test',
@ -62,7 +62,7 @@ class ImageThemeFunctionTest extends WebTestBase {
/**
* Tests usage of the image field formatters.
*/
function testImageFormatterTheme() {
public function testImageFormatterTheme() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
@ -72,7 +72,7 @@ class ImageThemeFunctionTest extends WebTestBase {
$original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
// Create a style.
$style = ImageStyle::create(array('name' => 'test', 'label' => 'Test'));
$style = ImageStyle::create(['name' => 'test', 'label' => 'Test']);
$style->save();
$url = file_url_transform_relative($style->buildUrl($original_uri));
@ -86,17 +86,17 @@ class ImageThemeFunctionTest extends WebTestBase {
// Create the base element that we'll use in the tests below.
$path = $this->randomMachineName();
$base_element = array(
$base_element = [
'#theme' => 'image_formatter',
'#image_style' => 'test',
'#item' => $entity->image_test,
'#url' => Url::fromUri('base:' . $path),
);
];
// Test using theme_image_formatter() with a NULL value for the alt option.
$element = $base_element;
$this->setRawContent($renderer->renderRoot($element));
$elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height]', array(':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()));
$elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]);
$this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders with a NULL value for the alt option.');
// Test using theme_image_formatter() without an image title, alt text, or
@ -104,7 +104,7 @@ class ImageThemeFunctionTest extends WebTestBase {
$element = $base_element;
$element['#item']->alt = '';
$this->setRawContent($renderer->renderRoot($element));
$elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', array(':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()));
$elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]);
$this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders without title, alt, or path options.');
// Link the image to a fragment on the page, and not a full URL.
@ -112,19 +112,19 @@ class ImageThemeFunctionTest extends WebTestBase {
$element = $base_element;
$element['#url'] = Url::fromRoute('<none>', [], ['fragment' => $fragment]);
$this->setRawContent($renderer->renderRoot($element));
$elements = $this->xpath('//a[@href=:fragment]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', array(
$elements = $this->xpath('//a[@href=:fragment]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [
':fragment' => '#' . $fragment,
':url' => $url,
':width' => $image->getWidth(),
':height' => $image->getHeight()
));
]);
$this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders a link fragment.');
}
/**
* Tests usage of the image style theme function.
*/
function testImageStyleTheme() {
public function testImageStyleTheme() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
@ -134,87 +134,87 @@ class ImageThemeFunctionTest extends WebTestBase {
$original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
// Create a style.
$style = ImageStyle::create(array('name' => 'image_test', 'label' => 'Test'));
$style = ImageStyle::create(['name' => 'image_test', 'label' => 'Test']);
$style->save();
$url = file_url_transform_relative($style->buildUrl($original_uri));
// Create the base element that we'll use in the tests below.
$base_element = array(
$base_element = [
'#theme' => 'image_style',
'#style_name' => 'image_test',
'#uri' => $original_uri,
);
];
$element = $base_element;
$this->setRawContent($renderer->renderRoot($element));
$elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url and @alt=""]', array(':url' => $url));
$elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url and @alt=""]', [':url' => $url]);
$this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly.');
// Test using theme_image_style() with a NULL value for the alt option.
$element = $base_element;
$element['#alt'] = NULL;
$this->setRawContent($renderer->renderRoot($element));
$elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url]', array(':url' => $url));
$elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url]', [':url' => $url]);
$this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly with a NULL value for the alt option.');
}
/**
* Tests image alt attribute functionality.
*/
function testImageAltFunctionality() {
public function testImageAltFunctionality() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
// Test using alt directly with alt attribute.
$image_with_alt_property = array(
$image_with_alt_property = [
'#theme' => 'image',
'#uri' => '/core/themes/bartik/logo.svg',
'#alt' => 'Regular alt',
'#title' => 'Test title',
'#width' => '50%',
'#height' => '50%',
'#attributes' => array('class' => 'image-with-regular-alt', 'id' => 'my-img'),
);
'#attributes' => ['class' => 'image-with-regular-alt', 'id' => 'my-img'],
];
$this->setRawContent($renderer->renderRoot($image_with_alt_property));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', array(":class" => "image-with-regular-alt", ":alt" => "Regular alt"));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-regular-alt", ":alt" => "Regular alt"]);
$this->assertEqual(count($elements), 1, 'Regular alt displays correctly');
// Test using alt attribute inside attributes.
$image_with_alt_attribute_alt_attribute = array(
$image_with_alt_attribute_alt_attribute = [
'#theme' => 'image',
'#uri' => '/core/themes/bartik/logo.svg',
'#width' => '50%',
'#height' => '50%',
'#attributes' => array(
'#attributes' => [
'class' => 'image-with-attribute-alt',
'id' => 'my-img',
'title' => 'New test title',
'alt' => 'Attribute alt',
),
);
],
];
$this->setRawContent($renderer->renderRoot($image_with_alt_attribute_alt_attribute));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', array(":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]);
$this->assertEqual(count($elements), 1, 'Attribute alt displays correctly');
// Test using alt attribute as property and inside attributes.
$image_with_alt_attribute_both = array(
$image_with_alt_attribute_both = [
'#theme' => 'image',
'#uri' => '/core/themes/bartik/logo.svg',
'#width' => '50%',
'#height' => '50%',
'#alt' => 'Kitten sustainable',
'#attributes' => array(
'#attributes' => [
'class' => 'image-with-attribute-alt',
'id' => 'my-img',
'title' => 'New test title',
'alt' => 'Attribute alt',
),
);
],
];
$this->setRawContent($renderer->renderRoot($image_with_alt_attribute_both));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', array(":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"));
$elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]);
$this->assertEqual(count($elements), 1, 'Attribute alt overrides alt property if both set.');
}

View file

@ -0,0 +1,186 @@
<?php
namespace Drupal\image\Tests;
use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
use Drupal\simpletest\WebTestBase;
/**
* Tests the endpoints used by the "image" in-place editor.
*
* @group image
*/
class QuickEditImageControllerTest extends WebTestBase {
use ImageFieldCreationTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'image', 'quickedit'];
/**
* The machine name of our image field.
*
* @var string
*/
protected $fieldName;
/**
* A user with permissions to edit articles and use Quick Edit.
*
* @var \Drupal\user\UserInterface
*/
protected $contentAuthorUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create the Article node type.
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
// Log in as a content author who can use Quick Edit and edit Articles.
$this->contentAuthorUser = $this->drupalCreateUser([
'access contextual links',
'access in-place editing',
'access content',
'create article content',
'edit any article content',
'delete any article content',
]);
$this->drupalLogin($this->contentAuthorUser);
// Create a field with basic resolution validators.
$this->fieldName = strtolower($this->randomMachineName());
$field_settings = [
'max_resolution' => '100x',
'min_resolution' => '50x',
];
$this->createImageField($this->fieldName, 'article', [], $field_settings);
}
/**
* Tests that routes restrict access for un-privileged users.
*/
public function testAccess() {
// Create an anonymous user.
$user = $this->createUser();
$this->drupalLogin($user);
// Create a test Node.
$node = $this->drupalCreateNode([
'type' => 'article',
'title' => t('Test Node'),
]);
$this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default');
$this->assertResponse('403');
$this->drupalPost('quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', 'application/json', []);
$this->assertResponse('403');
}
/**
* Tests that the field info route returns expected data.
*/
public function testFieldInfo() {
// Create a test Node.
$node = $this->drupalCreateNode([
'type' => 'article',
'title' => t('Test Node'),
]);
$info = $this->drupalGetJSON('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default');
// Assert that the default settings for our field are respected by our JSON
// endpoint.
$this->assertTrue($info['alt_field']);
$this->assertFalse($info['title_field']);
}
/**
* Tests that uploading a valid image works.
*/
public function testValidImageUpload() {
// Create a test Node.
$node = $this->drupalCreateNode([
'type' => 'article',
'title' => t('Test Node'),
]);
// We want a test image that is a valid size.
$valid_image = FALSE;
$image_factory = $this->container->get('image.factory');
foreach ($this->drupalGetTestFiles('image') as $image) {
$image_file = $image_factory->get($image->uri);
if ($image_file->getWidth() > 50 && $image_file->getWidth() < 100) {
$valid_image = $image;
break;
}
}
$this->assertTrue($valid_image);
$this->uploadImage($valid_image, $node->id(), $this->fieldName, $node->language()->getId());
$this->assertText('fid', t('Valid upload completed successfully.'));
}
/**
* Tests that uploading a invalid image does not work.
*/
public function testInvalidUpload() {
// Create a test Node.
$node = $this->drupalCreateNode([
'type' => 'article',
'title' => t('Test Node'),
]);
// We want a test image that will fail validation.
$invalid_image = FALSE;
/** @var \Drupal\Core\Image\ImageFactory $image_factory */
$image_factory = $this->container->get('image.factory');
foreach ($this->drupalGetTestFiles('image') as $image) {
/** @var \Drupal\Core\Image\ImageInterface $image_file */
$image_file = $image_factory->get($image->uri);
if ($image_file->getWidth() < 50 || $image_file->getWidth() > 100 ) {
$invalid_image = $image;
break;
}
}
$this->assertTrue($invalid_image);
$this->uploadImage($invalid_image, $node->id(), $this->fieldName, $node->language()->getId());
$this->assertText('main_error', t('Invalid upload returned errors.'));
}
/**
* Uploads an image using the image module's Quick Edit route.
*
* @param object $image
* The image to upload.
* @param int $nid
* The target node ID.
* @param string $field_name
* The target field machine name.
* @param string $langcode
* The langcode to use when setting the field's value.
*
* @return mixed
* The content returned from the call to $this->curlExec().
*/
public function uploadImage($image, $nid, $field_name, $langcode) {
$filepath = $this->container->get('file_system')->realpath($image->uri);
$data = [
'files[image]' => curl_file_create($filepath),
];
$path = 'quickedit/image/upload/node/' . $nid . '/' . $field_name . '/' . $langcode . '/default';
// We assemble the curl request ourselves as drupalPost cannot process file
// uploads, and drupalPostForm only works with typical Drupal forms.
return $this->curlExec([
CURLOPT_URL => $this->buildUrl($path, []),
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: multipart/form-data',
],
]);
}
}

View file

@ -21,25 +21,25 @@ class RelationshipUserImageDataTest extends ViewTestBase {
*
* @var array
*/
public static $modules = array('image', 'image_test_views', 'user');
public static $modules = ['image', 'image_test_views', 'user'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_image_user_image_data');
public static $testViews = ['test_image_user_image_data'];
protected function setUp() {
parent::setUp();
// Create the user profile field and instance.
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'user',
'field_name' => 'user_picture',
'type' => 'image',
'translatable' => '0',
))->save();
])->save();
FieldConfig::create([
'label' => 'User Picture',
'description' => '',
@ -49,7 +49,7 @@ class RelationshipUserImageDataTest extends ViewTestBase {
'required' => 0,
])->save();
ViewTestData::createTestViews(get_class($this), array('image_test_views'));
ViewTestData::createTestViews(get_class($this), ['image_test_views']);
}
/**
@ -84,12 +84,12 @@ class RelationshipUserImageDataTest extends ViewTestBase {
];
$this->assertIdentical($expected, $view->getDependencies());
$this->executeView($view);
$expected_result = array(
array(
$expected_result = [
[
'file_managed_user__user_picture_fid' => '2',
),
);
$column_map = array('file_managed_user__user_picture_fid' => 'file_managed_user__user_picture_fid');
],
];
$column_map = ['file_managed_user__user_picture_fid' => 'file_managed_user__user_picture_fid'];
$this->assertIdenticalResultset($view, $expected_result, $column_map);
}

View file

@ -10,7 +10,7 @@ use Drupal\image\ImageStyleInterface;
function image_module_test_file_download($uri) {
$default_uri = \Drupal::state()->get('image.test_file_download') ?: FALSE;
if ($default_uri == $uri) {
return array('X-Image-Owned-By' => 'image_module_test');
return ['X-Image-Owned-By' => 'image_module_test'];
}
}

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\image\Tests;
namespace Drupal\Tests\image\Functional;
use Drupal\image\Entity\ImageStyle;
use Drupal\system\Tests\Image\ToolkitTestBase;
@ -17,7 +17,7 @@ class ImageEffectsTest extends ToolkitTestBase {
*
* @var array
*/
public static $modules = array('image', 'image_test', 'image_module_test');
public static $modules = ['image', 'image_test', 'image_module_test'];
/**
* The image effect manager.
@ -34,12 +34,12 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_resize_effect() function.
*/
function testResizeEffect() {
$this->assertImageEffect('image_resize', array(
public function testResizeEffect() {
$this->assertImageEffect('image_resize', [
'width' => 1,
'height' => 2,
));
$this->assertToolkitOperationsCalled(array('resize'));
]);
$this->assertToolkitOperationsCalled(['resize']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -50,13 +50,13 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_scale_effect() function.
*/
function testScaleEffect() {
public function testScaleEffect() {
// @todo: need to test upscaling.
$this->assertImageEffect('image_scale', array(
$this->assertImageEffect('image_scale', [
'width' => 10,
'height' => 10,
));
$this->assertToolkitOperationsCalled(array('scale'));
]);
$this->assertToolkitOperationsCalled(['scale']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -67,14 +67,14 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_crop_effect() function.
*/
function testCropEffect() {
public function testCropEffect() {
// @todo should test the keyword offsets.
$this->assertImageEffect('image_crop', array(
$this->assertImageEffect('image_crop', [
'anchor' => 'top-1',
'width' => 3,
'height' => 4,
));
$this->assertToolkitOperationsCalled(array('crop'));
]);
$this->assertToolkitOperationsCalled(['crop']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -87,12 +87,12 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Tests the ConvertImageEffect plugin.
*/
function testConvertEffect() {
public function testConvertEffect() {
// Test jpeg.
$this->assertImageEffect('image_convert', array(
$this->assertImageEffect('image_convert', [
'extension' => 'jpeg',
));
$this->assertToolkitOperationsCalled(array('convert'));
]);
$this->assertToolkitOperationsCalled(['convert']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -102,12 +102,12 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_scale_and_crop_effect() function.
*/
function testScaleAndCropEffect() {
$this->assertImageEffect('image_scale_and_crop', array(
public function testScaleAndCropEffect() {
$this->assertImageEffect('image_scale_and_crop', [
'width' => 5,
'height' => 10,
));
$this->assertToolkitOperationsCalled(array('scale_and_crop'));
]);
$this->assertToolkitOperationsCalled(['scale_and_crop']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -118,9 +118,9 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_desaturate_effect() function.
*/
function testDesaturateEffect() {
$this->assertImageEffect('image_desaturate', array());
$this->assertToolkitOperationsCalled(array('desaturate'));
public function testDesaturateEffect() {
$this->assertImageEffect('image_desaturate', []);
$this->assertToolkitOperationsCalled(['desaturate']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -130,13 +130,13 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test the image_rotate_effect() function.
*/
function testRotateEffect() {
public function testRotateEffect() {
// @todo: need to test with 'random' => TRUE
$this->assertImageEffect('image_rotate', array(
$this->assertImageEffect('image_rotate', [
'degrees' => 90,
'bgcolor' => '#fff',
));
$this->assertToolkitOperationsCalled(array('rotate'));
]);
$this->assertToolkitOperationsCalled(['rotate']);
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
@ -147,7 +147,7 @@ class ImageEffectsTest extends ToolkitTestBase {
/**
* Test image effect caching.
*/
function testImageEffectsCaching() {
public function testImageEffectsCaching() {
$image_effect_definitions_called = &drupal_static('image_module_test_image_effect_info_alter');
// First call should grab a fresh copy of the data.
@ -195,7 +195,7 @@ class ImageEffectsTest extends ToolkitTestBase {
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertImageEffect($effect_name, array $data) {
$effect = $this->manager->createInstance($effect_name, array('data' => $data));
$effect = $this->manager->createInstance($effect_name, ['data' => $data]);
return $this->assertTrue($effect->applyEffect($this->image), 'Function returned the expected value.');
}

View file

@ -0,0 +1,109 @@
<?php
namespace Drupal\Tests\image\Functional;
use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
use Drupal\Tests\BrowserTestBase;
/**
* TODO: Test the following functions.
*
* image.effects.inc:
* image_style_generate()
* \Drupal\image\ImageStyleInterface::createDerivative()
*
* image.module:
* image_style_options()
* \Drupal\image\ImageStyleInterface::flush()
* image_filter_keyword()
*/
/**
* This class provides methods specifically for testing Image's field handling.
*/
abstract class ImageFieldTestBase extends BrowserTestBase {
use ImageFieldCreationTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'image', 'field_ui', 'image_module_test'];
/**
* An user with permissions to administer content types and image styles.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
$this->adminUser = $this->drupalCreateUser(['access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer node fields', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer node display']);
$this->drupalLogin($this->adminUser);
}
/**
* Preview an image in a node.
*
* @param \Drupal\Core\Image\ImageInterface $image
* A file object representing the image to upload.
* @param string $field_name
* Name of the image field the image should be attached to.
* @param string $type
* The type of node to create.
*/
public function previewNodeImage($image, $field_name, $type) {
$edit = [
'title[0][value]' => $this->randomMachineName(),
];
$edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('node/add/' . $type, $edit, t('Preview'));
}
/**
* Upload an image to a node.
*
* @param $image
* A file object representing the image to upload.
* @param $field_name
* Name of the image field the image should be attached to.
* @param $type
* The type of node to create.
* @param $alt
* The alt text for the image. Use if the field settings require alt text.
*/
public function uploadNodeImage($image, $field_name, $type, $alt = '') {
$edit = [
'title[0][value]' => $this->randomMachineName(),
];
$edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish'));
if ($alt) {
// Add alt text.
$this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save and publish'));
}
// Retrieve ID of the newly created node from the current URL.
$matches = [];
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
return isset($matches[1]) ? $matches[1] : FALSE;
}
/**
* Retrieves the fid of the last inserted file.
*/
protected function getLastFileId() {
return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
}
}

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\image\Tests;
namespace Drupal\Tests\image\Functional;
/**
* Tests the image field widget.
@ -17,14 +17,15 @@ class ImageFieldWidgetTest extends ImageFieldTestBase {
$field_name = strtolower($this->randomMachineName());
$min_resolution = 50;
$max_resolution = 100;
$field_settings = array(
$field_settings = [
'max_resolution' => $max_resolution . 'x' . $max_resolution,
'min_resolution' => $min_resolution . 'x' . $min_resolution,
'alt_field' => 0,
);
$this->createImageField($field_name, 'article', array(), $field_settings, array(), array(), 'Image test on [site:name]');
];
$this->createImageField($field_name, 'article', [], $field_settings, [], [], 'Image test on [site:name]');
$this->drupalGet('node/add/article');
$this->assertNotEqual(0, count($this->xpath('//div[contains(@class, "field--widget-image-image")]')), 'Image field widget found on add/node page', 'Browser');
$this->assertNotEqual(0, count($this->xpath('//input[contains(@accept, "image/*")]')), 'Image field widget limits accepted files.', 'Browser');
$this->assertNoText('Image test on [site:name]');
}

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\image\Tests;
namespace Drupal\Tests\image\Functional;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;

View file

@ -0,0 +1,172 @@
<?php
namespace Drupal\Tests\image\FunctionalJavascript;
use Drupal\file\Entity\File;
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
use Drupal\Tests\TestFileCreationTrait;
/**
* Tests the JavaScript functionality of the "image" in-place editor.
*
* @group image
*/
class QuickEditImageTest extends JavascriptTestBase {
use ImageFieldCreationTrait;
use TestFileCreationTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'image', 'field_ui', 'contextual', 'quickedit', 'toolbar'];
/**
* A user with permissions to edit Articles and use Quick Edit.
*
* @var \Drupal\user\UserInterface
*/
protected $contentAuthorUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create the Article node type.
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
// Log in as a content author who can use Quick Edit and edit Articles.
$this->contentAuthorUser = $this->drupalCreateUser([
'access contextual links',
'access toolbar',
'access in-place editing',
'access content',
'create article content',
'edit any article content',
'delete any article content',
]);
$this->drupalLogin($this->contentAuthorUser);
}
/**
* Tests if an image can be uploaded inline with Quick Edit.
*/
public function testUpload() {
// Create a field with a basic filetype restriction.
$field_name = strtolower($this->randomMachineName());
$field_settings = [
'file_extensions' => 'png',
];
$formatter_settings = [
'image_style' => 'large',
'image_link' => '',
];
$this->createImageField($field_name, 'article', [], $field_settings, [], $formatter_settings);
// Find images that match our field settings.
$valid_images = [];
foreach ($this->getTestFiles('image') as $image) {
// This regex is taken from file_validate_extensions().
$regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($field_settings['file_extensions'])) . ')$/i';
if (preg_match($regex, $image->filename)) {
$valid_images[] = $image;
}
}
// Ensure we have at least two valid images.
$this->assertGreaterThanOrEqual(2, count($valid_images));
// Create a File entity for the initial image.
$file = File::create([
'uri' => $valid_images[0]->uri,
'uid' => $this->contentAuthorUser->id(),
'status' => FILE_STATUS_PERMANENT,
]);
$file->save();
// Use the first valid image to create a new Node.
$image_factory = $this->container->get('image.factory');
$image = $image_factory->get($valid_images[0]->uri);
$node = $this->drupalCreateNode([
'type' => 'article',
'title' => t('Test Node'),
$field_name => [
'target_id' => $file->id(),
'alt' => 'Hello world',
'title' => '',
'width' => $image->getWidth(),
'height' => $image->getHeight(),
],
]);
// Visit the new Node.
$this->drupalGet('node/' . $node->id());
// Assemble common CSS selectors.
$entity_selector = '[data-quickedit-entity-id="node/' . $node->id() . '"]';
$field_selector = '[data-quickedit-field-id="node/' . $node->id() . '/' . $field_name . '/' . $node->language()->getId() . '/full"]';
$original_image_selector = 'img[src*="' . $valid_images[0]->filename . '"][alt="Hello world"]';
$new_image_selector = 'img[src*="' . $valid_images[1]->filename . '"][alt="New text"]';
// Assert that the initial image is present.
$this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector);
// Wait until Quick Edit loads.
$condition = "jQuery('" . $entity_selector . " .quickedit').length > 0";
$this->assertJsCondition($condition, 10000);
// Initiate Quick Editing.
$this->click('.contextual-toolbar-tab button');
$this->click($entity_selector . ' [data-contextual-id] > button');
$this->click($entity_selector . ' [data-contextual-id] .quickedit > a');
$this->click($field_selector);
// Wait for the field info to load and set new alt text.
$condition = "jQuery('.quickedit-image-field-info').length > 0";
$this->assertJsCondition($condition, 10000);
$input = $this->assertSession()->elementExists('css', '.quickedit-image-field-info input[name="alt"]');
$input->setValue('New text');
// Check that our Dropzone element exists.
$this->assertSession()->elementExists('css', $field_selector . ' .quickedit-image-dropzone');
// Our headless browser can't drag+drop files, but we can mock the event.
// Append a hidden upload element to the DOM.
$script = 'jQuery("<input id=\"quickedit-image-test-input\" type=\"file\" />").appendTo("body")';
$this->getSession()->executeScript($script);
// Find the element, and set its value to our new image.
$input = $this->assertSession()->elementExists('css', '#quickedit-image-test-input');
$filepath = $this->container->get('file_system')->realpath($valid_images[1]->uri);
$input->attachFile($filepath);
// Trigger the upload logic with a mock "drop" event.
$script = 'var e = jQuery.Event("drop");'
. 'e.originalEvent = {dataTransfer: {files: jQuery("#quickedit-image-test-input").get(0).files}};'
. 'e.preventDefault = e.stopPropagation = function () {};'
. 'jQuery(".quickedit-image-dropzone").trigger(e);';
$this->getSession()->executeScript($script);
// Wait for the dropzone element to be removed (i.e. loading is done).
$condition = "jQuery('" . $field_selector . " .quickedit-image-dropzone').length == 0";
$this->assertJsCondition($condition, 20000);
// To prevent 403s on save, we re-set our request (cookie) state.
$this->prepareRequest();
// Save the change.
$this->click('.quickedit-button.action-save');
$this->assertSession()->assertWaitOnAjaxRequest();
// Re-visit the page to make sure the edit worked.
$this->drupalGet('node/' . $node->id());
// Check that the new image appears as expected.
$this->assertSession()->elementNotExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector);
$this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $new_image_selector);
}
}

View file

@ -30,14 +30,14 @@ trait ImageFieldCreationTrait {
* @param string $description
* (optional) A description for the field. Defaults to ''.
*/
protected function createImageField($name, $type_name, $storage_settings = array(), $field_settings = array(), $widget_settings = array(), $formatter_settings = array(), $description = '') {
FieldStorageConfig::create(array(
protected function createImageField($name, $type_name, $storage_settings = [], $field_settings = [], $widget_settings = [], $formatter_settings = [], $description = '') {
FieldStorageConfig::create([
'field_name' => $name,
'entity_type' => 'node',
'type' => 'image',
'settings' => $storage_settings,
'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1,
))->save();
])->save();
$field_config = FieldConfig::create([
'field_name' => $name,
@ -51,17 +51,17 @@ trait ImageFieldCreationTrait {
$field_config->save();
entity_get_form_display('node', $type_name, 'default')
->setComponent($name, array(
->setComponent($name, [
'type' => 'image_image',
'settings' => $widget_settings,
))
])
->save();
entity_get_display('node', $type_name, 'default')
->setComponent($name, array(
->setComponent($name, [
'type' => 'image',
'settings' => $formatter_settings,
))
])
->save();
return $field_config;

View file

@ -21,7 +21,7 @@ class ImageFormatterTest extends FieldKernelTestBase {
*
* @var array
*/
public static $modules = array('file', 'image');
public static $modules = ['file', 'image'];
/**
* @var string
@ -52,18 +52,18 @@ class ImageFormatterTest extends FieldKernelTestBase {
$this->installConfig(['field']);
$this->installEntitySchema('entity_test');
$this->installEntitySchema('file');
$this->installSchema('file', array('file_usage'));
$this->installSchema('file', ['file_usage']);
$this->entityType = 'entity_test';
$this->bundle = $this->entityType;
$this->fieldName = Unicode::strtolower($this->randomMachineName());
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => $this->entityType,
'field_name' => $this->fieldName,
'type' => 'image',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
))->save();
])->save();
FieldConfig::create([
'entity_type' => $this->entityType,
'field_name' => $this->fieldName,
@ -84,7 +84,7 @@ class ImageFormatterTest extends FieldKernelTestBase {
/**
* Tests the cache tags from image formatters.
*/
function testImageFormatterCacheTags() {
public function testImageFormatterCacheTags() {
// Create a test entity with the image field set.
$entity = EntityTest::create([
'name' => $this->randomMachineName(),

View file

@ -23,7 +23,7 @@ class ImageItemTest extends FieldKernelTestBase {
*
* @var array
*/
public static $modules = array('file', 'image');
public static $modules = ['file', 'image'];
/**
* Created file entity.
@ -41,14 +41,14 @@ class ImageItemTest extends FieldKernelTestBase {
parent::setUp();
$this->installEntitySchema('file');
$this->installSchema('file', array('file_usage'));
$this->installSchema('file', ['file_usage']);
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'image_test',
'type' => 'image',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
))->save();
])->save();
FieldConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'image_test',
@ -114,11 +114,11 @@ class ImageItemTest extends FieldKernelTestBase {
// Delete the image and try to save the entity again.
$this->image->delete();
$entity = EntityTest::create(array('mame' => $this->randomMachineName()));
$entity = EntityTest::create(['mame' => $this->randomMachineName()]);
$entity->save();
// Test image item properties.
$expected = array('target_id', 'entity', 'alt', 'title', 'width', 'height');
$expected = ['target_id', 'entity', 'alt', 'title', 'width', 'height'];
$properties = $entity->getFieldDefinition('image_test')->getFieldStorageDefinition()->getPropertyDefinitions();
$this->assertEqual(array_keys($properties), $expected);

View file

@ -28,9 +28,9 @@ class MigrateImageCacheTest extends MigrateDrupal6TestBase {
*/
public function testMissingTable() {
$this->sourceDatabase->update('system')
->fields(array(
->fields([
'status' => 0,
))
])
->condition('name', 'imagecache')
->condition('type', 'module')
->execute();
@ -88,14 +88,14 @@ class MigrateImageCacheTest extends MigrateDrupal6TestBase {
*/
public function testMissingEffectPlugin() {
Database::getConnection('default', 'migrate')->insert("imagecache_action")
->fields([
->fields([
'presetid',
'weight',
'module',
'action',
'data',
])
->values([
->values([
'presetid' => '1',
'weight' => '0',
'module' => 'imagecache',
@ -121,14 +121,14 @@ class MigrateImageCacheTest extends MigrateDrupal6TestBase {
*/
public function testInvalidCropValues() {
Database::getConnection('default', 'migrate')->insert("imagecache_action")
->fields([
->fields([
'presetid',
'weight',
'module',
'action',
'data',
])
->values([
->values([
'presetid' => '1',
'weight' => '0',
'module' => 'imagecache',

View file

@ -17,7 +17,7 @@ class MigrateImageStylesTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('image');
public static $modules = ['image'];
/**
* {@inheritdoc}

View file

@ -38,7 +38,7 @@ class ImageStylesTest extends MigrateSqlSourceTestBase {
'isid' => 1,
'weight' => 1,
'name' => 'image_desaturate',
'data' => serialize(array()),
'data' => serialize([]),
],
];

View file

@ -19,7 +19,7 @@ class ImageViewsDataTest extends ViewsKernelTestBase {
*
* @var array
*/
public static $modules = array('image', 'file', 'views', 'entity_test', 'user', 'field');
public static $modules = ['image', 'file', 'views', 'entity_test', 'user', 'field'];
/**
* Tests views data generated for image field relationship.
@ -29,16 +29,16 @@ class ImageViewsDataTest extends ViewsKernelTestBase {
*/
public function testRelationshipViewsData() {
// Create image field to entity_test.
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'field_base_image',
'type' => 'image',
))->save();
FieldConfig::create(array(
])->save();
FieldConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'field_base_image',
'bundle' => 'entity_test',
))->save();
])->save();
// Check the generated views data.
$views_data = Views::viewsData()->get('entity_test__field_base_image');
$relationship = $views_data['field_base_image_target_id']['relationship'];
@ -59,16 +59,16 @@ class ImageViewsDataTest extends ViewsKernelTestBase {
$this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]);
// Create image field to entity_test_mul.
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test_mul',
'field_name' => 'field_data_image',
'type' => 'image',
))->save();
FieldConfig::create(array(
])->save();
FieldConfig::create([
'entity_type' => 'entity_test_mul',
'field_name' => 'field_data_image',
'bundle' => 'entity_test_mul',
))->save();
])->save();
// Check the generated views data.
$views_data = Views::viewsData()->get('entity_test_mul__field_data_image');
$relationship = $views_data['field_data_image_target_id']['relationship'];

View file

@ -44,7 +44,7 @@ class ImageStyleTest extends UnitTestCase {
* @return \Drupal\image\ImageStyleInterface
* The mocked image style.
*/
protected function getImageStyleMock($image_effect_id, $image_effect, $stubs = array()) {
protected function getImageStyleMock($image_effect_id, $image_effect, $stubs = []) {
$effectManager = $this->getMockBuilder('\Drupal\image\ImageEffectManager')
->disableOriginalConstructor()
->getMock();
@ -52,17 +52,17 @@ class ImageStyleTest extends UnitTestCase {
->method('createInstance')
->with($image_effect_id)
->will($this->returnValue($image_effect));
$default_stubs = array(
$default_stubs = [
'getImageEffectPluginManager',
'fileUriScheme',
'fileUriTarget',
'fileDefaultScheme',
);
];
$image_style = $this->getMockBuilder('\Drupal\image\Entity\ImageStyle')
->setConstructorArgs(array(
array('effects' => array($image_effect_id => array('id' => $image_effect_id))),
->setConstructorArgs([
['effects' => [$image_effect_id => ['id' => $image_effect_id]]],
$this->entityTypeId,
))
])
->setMethods(array_merge($default_stubs, $stubs))
->getMock();
@ -71,13 +71,13 @@ class ImageStyleTest extends UnitTestCase {
->will($this->returnValue($effectManager));
$image_style->expects($this->any())
->method('fileUriScheme')
->will($this->returnCallback(array($this, 'fileUriScheme')));
->will($this->returnCallback([$this, 'fileUriScheme']));
$image_style->expects($this->any())
->method('fileUriTarget')
->will($this->returnCallback(array($this, 'fileUriTarget')));
->will($this->returnCallback([$this, 'fileUriTarget']));
$image_style->expects($this->any())
->method('fileDefaultScheme')
->will($this->returnCallback(array($this, 'fileDefaultScheme')));
->will($this->returnCallback([$this, 'fileDefaultScheme']));
return $image_style;
}
@ -106,7 +106,7 @@ class ImageStyleTest extends UnitTestCase {
$image_effect_id = $this->randomMachineName();
$logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')->getMock();
$image_effect = $this->getMockBuilder('\Drupal\image\ImageEffectBase')
->setConstructorArgs(array(array(), $image_effect_id, array(), $logger))
->setConstructorArgs([[], $image_effect_id, [], $logger])
->getMock();
$image_effect->expects($this->any())
->method('getDerivativeExtension')
@ -114,7 +114,7 @@ class ImageStyleTest extends UnitTestCase {
$image_style = $this->getImageStyleMock($image_effect_id, $image_effect);
$extensions = array('jpeg', 'gif', 'png');
$extensions = ['jpeg', 'gif', 'png'];
foreach ($extensions as $extension) {
$extensionReturned = $image_style->getDerivativeExtension($extension);
$this->assertEquals($extensionReturned, 'png');
@ -129,7 +129,7 @@ class ImageStyleTest extends UnitTestCase {
$image_effect_id = $this->randomMachineName();
$logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')->getMock();
$image_effect = $this->getMockBuilder('\Drupal\image\ImageEffectBase')
->setConstructorArgs(array(array(), $image_effect_id, array(), $logger))
->setConstructorArgs([[], $image_effect_id, [], $logger])
->getMock();
$image_effect->expects($this->any())
->method('getDerivativeExtension')
@ -141,7 +141,7 @@ class ImageStyleTest extends UnitTestCase {
// Image style that doesn't change the extension.
$image_effect_id = $this->randomMachineName();
$image_effect = $this->getMockBuilder('\Drupal\image\ImageEffectBase')
->setConstructorArgs(array(array(), $image_effect_id, array(), $logger))
->setConstructorArgs([[], $image_effect_id, [], $logger])
->getMock();
$image_effect->expects($this->any())
->method('getDerivativeExtension')
@ -162,19 +162,19 @@ class ImageStyleTest extends UnitTestCase {
// Image style that changes the extension.
$image_effect_id = $this->randomMachineName();
$image_effect = $this->getMockBuilder('\Drupal\image\ImageEffectBase')
->setConstructorArgs(array(array(), $image_effect_id, array(), $logger))
->setConstructorArgs([[], $image_effect_id, [], $logger])
->getMock();
$image_effect->expects($this->any())
->method('getDerivativeExtension')
->will($this->returnValue('png'));
$image_style = $this->getImageStyleMock($image_effect_id, $image_effect, array('getPrivateKey', 'getHashSalt'));
$image_style = $this->getImageStyleMock($image_effect_id, $image_effect, ['getPrivateKey', 'getHashSalt']);
$image_style->expects($this->any())
->method('getPrivateKey')
->will($this->returnValue($private_key));
->method('getPrivateKey')
->will($this->returnValue($private_key));
$image_style->expects($this->any())
->method('getHashSalt')
->will($this->returnValue($hash_salt));
->method('getHashSalt')
->will($this->returnValue($hash_salt));
// Assert the extension has been added to the URI before creating the token.
$this->assertEquals($image_style->getPathToken('public://test.jpeg.png'), $image_style->getPathToken('public://test.jpeg'));
@ -184,19 +184,19 @@ class ImageStyleTest extends UnitTestCase {
// Image style that doesn't change the extension.
$image_effect_id = $this->randomMachineName();
$image_effect = $this->getMockBuilder('\Drupal\image\ImageEffectBase')
->setConstructorArgs(array(array(), $image_effect_id, array(), $logger))
->setConstructorArgs([[], $image_effect_id, [], $logger])
->getMock();
$image_effect->expects($this->any())
->method('getDerivativeExtension')
->will($this->returnArgument(0));
$image_style = $this->getImageStyleMock($image_effect_id, $image_effect, array('getPrivateKey', 'getHashSalt'));
$image_style = $this->getImageStyleMock($image_effect_id, $image_effect, ['getPrivateKey', 'getHashSalt']);
$image_style->expects($this->any())
->method('getPrivateKey')
->will($this->returnValue($private_key));
->method('getPrivateKey')
->will($this->returnValue($private_key));
$image_style->expects($this->any())
->method('getHashSalt')
->will($this->returnValue($hash_salt));
->method('getHashSalt')
->will($this->returnValue($hash_salt));
// Assert no extension has been added to the uri before creating the token.
$this->assertNotEquals($image_style->getPathToken('public://test.jpeg.png'), $image_style->getPathToken('public://test.jpeg'));
$this->assertNotEquals(substr(Crypt::hmacBase64($image_style->id() . ':' . 'public://test.jpeg.png', $private_key . $hash_salt), 0, 8), $image_style->getPathToken('public://test.jpeg'));