Commit b8016410 authored by catch's avatar catch

Issue #2015697 by claudiu.cristea, yched, Berdir, splatio: Convert field type...

Issue #2015697 by claudiu.cristea, yched, Berdir, splatio: Convert field type to typed data plugin for file and image modules.
parent ef874408
......@@ -470,10 +470,10 @@ function content_translation_translatable_batch($translatable, $field_name, &$co
// We need a two-step approach while updating field translations: given
// that field-specific update functions might rely on the stored values to
// perform their processing, see for instance file_field_update(), first
// we need to store the new translations and only after we can remove the
// old ones. Otherwise we might have data loss, since the removal of the
// old translations might occur before the new ones are stored.
// perform their processing first we need to store the new translations
// and only after we can remove the old ones. Otherwise we might have data
// loss, since the removal of the old translations might occur before the
// new ones are stored.
if ($translatable && isset($entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED])) {
// If the field is being switched to translatable and has data for
// Language::LANGCODE_NOT_SPECIFIED then we need to move the data to the right
......
This diff is collapsed.
......@@ -152,44 +152,6 @@ function file_schema() {
return $schema;
}
/**
* Implements hook_field_schema().
*/
function file_field_schema($field) {
return array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the target entity.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
),
'display' => array(
'description' => 'Flag to control whether this file should be displayed when viewing content.',
'type' => 'int',
'size' => 'tiny',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
),
'description' => array(
'description' => 'A description of the file.',
'type' => 'text',
'not null' => FALSE,
),
),
'indexes' => array(
'target_id' => array('target_id'),
),
'foreign keys' => array(
'target_id' => array(
'table' => 'file_managed',
'columns' => array('target_id' => 'fid'),
),
),
);
}
/**
* Implements hook_requirements().
*
......
<?php
/**
* @file
* Contains \Drupal\file\Plugin\field\field_type\FileField.
*/
namespace Drupal\file\Plugin\field\field_type;
use Drupal\field\Plugin\Type\FieldType\ConfigField;
/**
* Represents a configurable entity file field.
*/
class FileField extends ConfigField {
/**
* {@inheritdoc}
*/
public function defaultValuesForm(array &$form, array &$form_state) { }
/**
* {@inheritdoc}
*/
public function update() {
parent::update();
$this->updateFileUsage();
}
/**
* Updates the file usage.
*/
protected function updateFileUsage() {
$entity = $this->getRoot();
// On new revisions, all files are considered to be a new usage and no
// deletion of previous file usages are necessary.
if (!empty($entity->original) && $entity->getRevisionId() != $entity->original->getRevisionId()) {
foreach ($this->list as $item) {
file_usage()->add($item->entity, 'file', $entity->entityType(), $entity->id());
}
return;
}
// Build a list of the current target IDs.
$fids = array();
foreach ($this->list as $item) {
$fids[] = $item->target_id;
}
// Compare the original field values with the ones that are being saved.
$field_name = $this->getFieldDefinition()->getFieldName();
$original_fids = array();
$original_items = $entity->original->getTranslation($this->getLangcode())->$field_name;
foreach ($original_items as $item) {
$original_fids[] = $item->target_id;
if ($item->target_id && !in_array($item->target_id, $fids)) {
// Decrement the file usage count by 1.
file_usage()->delete($item->entity, 'file', $entity->entityType(), $entity->id());
}
}
// Add new usage entries for newly added files.
foreach ($this->list as $item) {
if ($item->target_id && !in_array($item->target_id, $original_fids)) {
file_usage()->add($item->entity, 'file', $entity->entityType(), $entity->id());
}
}
}
}
......@@ -180,8 +180,6 @@ public function formElement(FieldInterface $items, $delta, array $element, $lang
// The field settings include defaults for the field type. However, this
// widget is a base class for other widgets (e.g., ImageWidget) that may act
// on field types without these expected settings.
// @todo Add support for merging settings of base types to implementations
// of FieldDefinitionInterface::getFieldSettings().
$field_settings += array(
'display_default' => NULL,
'display_field' => NULL,
......@@ -200,8 +198,8 @@ public function formElement(FieldInterface $items, $delta, array $element, $lang
$element_info = element_info('managed_file');
$element += array(
'#type' => 'managed_file',
'#upload_location' => file_field_widget_uri($field_settings),
'#upload_validators' => file_field_widget_upload_validators($field_settings),
'#upload_location' => $items[$delta]->getUploadLocation(),
'#upload_validators' => $items[$delta]->getUploadValidators(),
'#value_callback' => 'file_field_widget_value',
'#process' => array_merge($element_info['#process'], array('file_field_widget_process')),
'#progress_indicator' => $this->getSetting('progress_indicator'),
......
<?php
/**
* @file
* Contains \Drupal\file\Type\FileField.
*/
namespace Drupal\file\Type;
use Drupal\field\Plugin\field\field_type\LegacyConfigField;
/**
* Represents a configurable entity file field.
*/
class FileField extends LegacyConfigField {
/**
* {@inheritdoc}
*/
public function defaultValuesForm(array &$form, array &$form_state) { }
}
<?php
/**
* @file
* Contains \Drupal\file\Type\FileItem.
*/
namespace Drupal\file\Type;
use Drupal\field\Plugin\Type\FieldType\ConfigEntityReferenceItemBase;
/**
* Defines the 'file_field' entity field item.
*/
class FileItem extends ConfigEntityReferenceItemBase {
/**
* Property definitions of the contained properties.
*
* @see FileItem::getPropertyDefinitions()
*
* @var array
*/
static $propertyDefinitions;
/**
* {@inheritdoc}
*/
public function getPropertyDefinitions() {
$this->definition['settings']['target_type'] = 'file';
// Definitions vary by entity type and bundle, so key them accordingly.
$key = $this->definition['settings']['target_type'] . ':';
$key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : '';
if (!isset(static::$propertyDefinitions[$key])) {
static::$propertyDefinitions[$key] = parent::getPropertyDefinitions();
static::$propertyDefinitions[$key]['display'] = array(
'type' => 'boolean',
'label' => t('Flag to control whether this file should be displayed when viewing content.'),
);
static::$propertyDefinitions[$key]['description'] = array(
'type' => 'string',
'label' => t('A description of the file.'),
);
}
return static::$propertyDefinitions[$key];
}
}
......@@ -6,273 +6,12 @@
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_field_info().
* Implements hook_field_info_alter().
*/
function image_field_info() {
return array(
'image' => array(
'label' => t('Image'),
'description' => t('This field stores the ID of an image file as an integer value.'),
'settings' => array(
'uri_scheme' => file_default_scheme(),
'default_image' => 0,
'column_groups' => array(
'file' => array(
'label' => t('File'),
'columns' => array('target_id', 'width', 'height'),
),
'alt' => array(
'label' => t('Alt'),
'translatable' => TRUE,
),
'title' => array(
'label' => t('Title'),
'translatable' => TRUE,
),
),
),
'instance_settings' => array(
'file_extensions' => 'png gif jpg jpeg',
'file_directory' => '',
'max_filesize' => '',
'alt_field' => 0,
'alt_field_required' => 0,
'title_field' => 0,
'title_field_required' => 0,
'max_resolution' => '',
'min_resolution' => '',
'default_image' => 0,
),
'default_widget' => 'image_image',
'default_formatter' => 'image',
'class' => '\Drupal\image\Type\ImageItem',
'list_class' => '\Drupal\image\Type\ImageField',
),
);
}
/**
* Implements hook_field_settings_form().
*/
function image_field_settings_form($field, $instance) {
$defaults = \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($field['type']);
$settings = array_merge($defaults, $field['settings']);
$scheme_options = array();
foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $stream_wrapper) {
$scheme_options[$scheme] = $stream_wrapper['name'];
}
$form['uri_scheme'] = array(
'#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.'),
);
// When the user sets the scheme on the UI, even for the first time, it's
// updating a field because fields are created on the "Manage fields"
// page. So image_field_update_field() can handle this change.
$form['default_image'] = array(
'#title' => t('Default image'),
'#type' => 'managed_file',
'#description' => t('If no image is uploaded, this image will be shown on display.'),
'#default_value' => empty($field['settings']['default_image']) ? array() : array($field['settings']['default_image']),
'#upload_location' => $settings['uri_scheme'] . '://default_images/',
);
return $form;
}
/**
* Implements hook_field_instance_settings_form().
*/
function image_field_instance_settings_form($field, $instance) {
$settings = $instance['settings'];
// Use the file field instance settings form as a basis.
$form = file_field_instance_settings_form($field, $instance);
// Add maximum and minimum resolution settings.
$max_resolution = explode('x', $settings['max_resolution']) + array('', '');
$form['max_resolution'] = array(
'#type' => 'item',
'#title' => t('Maximum image resolution'),
'#element_validate' => array('_image_field_resolution_validate'),
'#weight' => 4.1,
'#field_prefix' => '<div class="container-inline">',
'#field_suffix' => '</div>',
'#description' => t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). 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="@url">EXIF data</a> in the image.', array('@url' => 'http://en.wikipedia.org/wiki/Exchangeable_image_file_format')),
);
$form['max_resolution']['x'] = array(
'#type' => 'number',
'#title' => t('Maximum width'),
'#title_display' => 'invisible',
'#default_value' => $max_resolution[0],
'#min' => 1,
'#field_suffix' => ' x ',
);
$form['max_resolution']['y'] = array(
'#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('', '');
$form['min_resolution'] = array(
'#type' => 'item',
'#title' => t('Minimum image resolution'),
'#element_validate' => array('_image_field_resolution_validate'),
'#weight' => 4.2,
'#field_prefix' => '<div class="container-inline">',
'#field_suffix' => '</div>',
'#description' => t('The minimum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'),
);
$form['min_resolution']['x'] = array(
'#type' => 'number',
'#title' => t('Minimum width'),
'#title_display' => 'invisible',
'#default_value' => $min_resolution[0],
'#min' => 1,
'#field_suffix' => ' x ',
);
$form['min_resolution']['y'] = array(
'#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($form['description_field']);
// Add title and alt configuration options.
$form['alt_field'] = array(
'#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.'),
'#weight' => 9,
);
$form['alt_field_required'] = array(
'#type' => 'checkbox',
'#title' => t('<em>Alt</em> field required'),
'#default_value' => $settings['alt_field_required'],
'#weight' => 10,
'#states' => array(
'visible' => array(
':input[name="instance[settings][alt_field]"]' => array('checked' => TRUE),
),
),
);
$form['title_field'] = array(
'#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.'),
'#weight' => 11,
);
$form['title_field_required'] = array(
'#type' => 'checkbox',
'#title' => t('<em>Title</em> field required'),
'#default_value' => $settings['title_field_required'],
'#weight' => 12,
'#states' => array(
'visible' => array(
':input[name="instance[settings][title_field]"]' => array('checked' => TRUE),
),
),
);
// Add the default image to the instance.
$form['default_image'] = array(
'#title' => t('Default image'),
'#type' => 'managed_file',
'#description' => t("If no image is uploaded, this image will be shown on display and will override the field's default image."),
'#default_value' => empty($settings['default_image']) ? array() : array($settings['default_image']),
'#upload_location' => $field['settings']['uri_scheme'] . '://default_images/',
);
return $form;
}
/**
* Element validate function for resolution fields.
*/
function _image_field_resolution_validate($element, &$form_state) {
if (!empty($element['x']['#value']) || !empty($element['y']['#value'])) {
foreach (array('x', 'y') as $dimension) {
if (!$element[$dimension]['#value']) {
form_error($element[$dimension], t('Both a height and width value must be specified in the !name field.', array('!name' => $element['#title'])));
return;
}
}
form_set_value($element, $element['x']['#value'] . 'x' . $element['y']['#value'], $form_state);
}
else {
form_set_value($element, '', $form_state);
}
}
/**
* Implements hook_field_presave().
*/
function image_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) {
$image_factory = Drupal::service('image.factory');
// Determine the dimensions if necessary.
foreach ($items as &$item) {
if (!isset($item['width']) || !isset($item['height'])) {
$image = $image_factory->get(file_load($item['target_id'])->getFileUri());
if ($image->getExtension()) {
$item['width'] = $image->getWidth();
$item['height'] = $image->getHeight();
}
}
}
}
/**
* Implements hook_field_insert().
*/
function image_field_insert(EntityInterface $entity, $field, $instance, $langcode, &$items) {
file_field_insert($entity, $field, $instance, $langcode, $items);
}
/**
* Implements hook_field_update().
*/
function image_field_update(EntityInterface $entity, $field, $instance, $langcode, &$items) {
file_field_update($entity, $field, $instance, $langcode, $items);
}
/**
* Implements hook_field_delete().
*/
function image_field_delete(EntityInterface $entity, $field, $instance, $langcode, &$items) {
file_field_delete($entity, $field, $instance, $langcode, $items);
}
/**
* Implements hook_field_delete_revision().
*/
function image_field_delete_revision(EntityInterface $entity, $field, $instance, $langcode, &$items) {
file_field_delete_revision($entity, $field, $instance, $langcode, $items);
}
/**
* Implements hook_field_is_empty().
*/
function image_field_is_empty($item, $field_type) {
return file_field_is_empty($item, $field_type);
function image_field_info_alter(&$info) {
$info['image']['settings']['uri_scheme'] = file_default_scheme();
}
/**
......
......@@ -24,53 +24,6 @@ function image_uninstall() {
file_unmanaged_delete_recursive(file_default_scheme() . '://styles');
}
/**
* Implements hook_field_schema().
*/
function image_field_schema($field) {
return array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the target entity.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
),
'alt' => array(
'description' => "Alternative image text, for the image's 'alt' attribute.",
'type' => 'varchar',
'length' => 512,
'not null' => FALSE,
),
'title' => array(
'description' => "Image title text, for the image's 'title' attribute.",
'type' => 'varchar',
'length' => 1024,
'not null' => FALSE,
),
'width' => array(
'description' => 'The width of the image in pixels.',
'type' => 'int',
'unsigned' => TRUE,
),
'height' => array(
'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(
'table' => 'file_managed',
'columns' => array('target_id' => 'fid'),
),
),
);
}
/**
* Implements hook_requirements() to check the PHP GD Library.
*
......
<?php
/**
* @file
* Contains \Drupal\image\Type\ImageField.
*/
namespace Drupal\image\Type;
use Drupal\field\Plugin\field\field_type\LegacyConfigField;
/**
* Represents a configurable entity image field.
*/
class ImageField extends LegacyConfigField {
/**
* {@inheritdoc}
*/
public function defaultValuesForm(array &$form, array &$form_state) { }
}
<?php
/**
* @image
* Contains \Drupal\image\Type\ImageItem.
*/
namespace Drupal\image\Type;
use Drupal\field\Plugin\Type\FieldType\ConfigEntityReferenceItemBase;
/**
* Defines the 'image_field' entity field item.
*/
class ImageItem extends ConfigEntityReferenceItemBase {
/**
* Property definitions of the contained properties.
*
* @see ImageItem::getPropertyDefinitions()
*
* @var array
*/
static $propertyDefinitions;
/**
* {@inheritdoc}
*/
public function getPropertyDefinitions() {
$this->definition['settings']['target_type'] = 'file';
// Definitions vary by entity type and bundle, so key them accordingly.
$key = $this->definition['settings']['target_type'] . ':';
$key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : '';
if (!isset(static::$propertyDefinitions[$key])) {
static::$propertyDefinitions[$key] = parent::getPropertyDefinitions();
static::$propertyDefinitions[$key]['alt'] = array(
'type' => 'string',
'label' => t("Alternative image text, for the image's 'alt' attribute."),
);
static::$propertyDefinitions[$key]['title'] = array(
'type' => 'string',
'label' => t("Image title text, for the image's 'title' attribute."),
);
static::$propertyDefinitions[$key]['width'] = array(
'type' => 'integer',
'label' => t('The width of the image in pixels.'),
);
static::$propertyDefinitions[$key]['height'] = array(
'type' => 'integer',
'label' => t('The height of the image in pixels.'),
);
}
return static::$propertyDefinitions[$key];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment