View source
<?php
namespace Drupal\file\Plugin\Field\FieldType;
use Drupal\Component\Utility\Bytes;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Utility\Random;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\TypedData\DataDefinition;
class FileItem extends EntityReferenceItem {
public static function defaultStorageSettings() {
return array(
'target_type' => 'file',
'display_field' => FALSE,
'display_default' => FALSE,
'uri_scheme' => file_default_scheme(),
) + parent::defaultStorageSettings();
}
public static function defaultFieldSettings() {
return array(
'file_extensions' => 'txt',
'file_directory' => '[date:custom:Y]-[date:custom:m]',
'max_filesize' => '',
'description_field' => 0,
) + parent::defaultFieldSettings();
}
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the file entity.',
'type' => 'int',
'unsigned' => TRUE,
),
'display' => array(
'description' => 'Flag to control whether this file should be displayed when viewing content.',
'type' => 'int',
'size' => 'tiny',
'unsigned' => TRUE,
'default' => 1,
),
'description' => array(
'description' => 'A description of the file.',
'type' => 'text',
),
),
'indexes' => array(
'target_id' => array(
'target_id',
),
),
'foreign keys' => array(
'target_id' => array(
'table' => 'file_managed',
'columns' => array(
'target_id' => 'fid',
),
),
),
);
}
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties = parent::propertyDefinitions($field_definition);
$properties['display'] = DataDefinition::create('boolean')
->setLabel(t('Display'))
->setDescription(t('Flag to control whether this file should be displayed when viewing content'));
$properties['description'] = DataDefinition::create('string')
->setLabel(t('Description'));
return $properties;
}
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element = array();
$element['#attached']['library'][] = 'file/drupal.file';
$element['display_field'] = array(
'#type' => 'checkbox',
'#title' => t('Enable <em>Display</em> field'),
'#default_value' => $this
->getSetting('display_field'),
'#description' => t('The display option allows users to choose if a file should be shown when viewing the content.'),
);
$element['display_default'] = array(
'#type' => 'checkbox',
'#title' => t('Files displayed by default'),
'#default_value' => $this
->getSetting('display_default'),
'#description' => t('This setting only has an effect if the display option is enabled.'),
'#states' => array(
'visible' => array(
':input[name="settings[display_field]"]' => array(
'checked' => TRUE,
),
),
),
);
$scheme_options = \Drupal::service('stream_wrapper_manager')
->getNames(StreamWrapperInterface::WRITE_VISIBLE);
$element['uri_scheme'] = array(
'#type' => 'radios',
'#title' => t('Upload destination'),
'#options' => $scheme_options,
'#default_value' => $this
->getSetting('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.'),
'#disabled' => $has_data,
);
return $element;
}
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = array();
$settings = $this
->getSettings();
$element['file_directory'] = array(
'#type' => 'textfield',
'#title' => t('File directory'),
'#default_value' => $settings['file_directory'],
'#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
'#element_validate' => array(
array(
get_class($this),
'validateDirectory',
),
),
'#weight' => 3,
);
$extensions = str_replace(' ', ', ', $settings['file_extensions']);
$element['file_extensions'] = array(
'#type' => 'textfield',
'#title' => t('Allowed file extensions'),
'#default_value' => $extensions,
'#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
'#element_validate' => array(
array(
get_class($this),
'validateExtensions',
),
),
'#weight' => 1,
'#maxlength' => 256,
'#required' => TRUE,
);
$element['max_filesize'] = array(
'#type' => 'textfield',
'#title' => t('Maximum upload size'),
'#default_value' => $settings['max_filesize'],
'#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', array(
'%limit' => format_size(file_upload_max_size()),
)),
'#size' => 10,
'#element_validate' => array(
array(
get_class($this),
'validateMaxFilesize',
),
),
'#weight' => 5,
);
$element['description_field'] = array(
'#type' => 'checkbox',
'#title' => t('Enable <em>Description</em> field'),
'#default_value' => isset($settings['description_field']) ? $settings['description_field'] : '',
'#description' => t('The description field allows users to enter a description about the uploaded file.'),
'#weight' => 11,
);
return $element;
}
public static function validateDirectory($element, FormStateInterface $form_state) {
$value = trim($element['#value'], '\\/');
$form_state
->setValueForElement($element, $value);
}
public static function validateExtensions($element, FormStateInterface $form_state) {
if (!empty($element['#value'])) {
$extensions = preg_replace('/([, ]+\\.?)/', ' ', trim(strtolower($element['#value'])));
$extensions = array_filter(explode(' ', $extensions));
$extensions = implode(' ', array_unique($extensions));
if (!preg_match('/^([a-z0-9]+([.][a-z0-9])* ?)+$/', $extensions)) {
$form_state
->setError($element, t('The list of allowed extensions is not valid, be sure to exclude leading dots and to separate extensions with a comma or space.'));
}
else {
$form_state
->setValueForElement($element, $extensions);
}
}
}
public static function validateMaxFilesize($element, FormStateInterface $form_state) {
if (!empty($element['#value']) && !is_numeric(Bytes::toInt($element['#value']))) {
$form_state
->setError($element, t('The "@name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', array(
'@name' => $element['title'],
)));
}
}
public function getUploadLocation($data = array()) {
return static::doGetUploadLocation($this
->getSettings(), $data);
}
protected static function doGetUploadLocation(array $settings, $data = []) {
$destination = trim($settings['file_directory'], '/');
$destination = PlainTextOutput::renderFromHtml(\Drupal::token()
->replace($destination, $data));
return $settings['uri_scheme'] . '://' . $destination;
}
public function getUploadValidators() {
$validators = array();
$settings = $this
->getSettings();
$max_filesize = Bytes::toInt(file_upload_max_size());
if (!empty($settings['max_filesize'])) {
$max_filesize = min($max_filesize, Bytes::toInt($settings['max_filesize']));
}
$validators['file_validate_size'] = array(
$max_filesize,
);
if (!empty($settings['file_extensions'])) {
$validators['file_validate_extensions'] = array(
$settings['file_extensions'],
);
}
return $validators;
}
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
$random = new Random();
$settings = $field_definition
->getSettings();
$dirname = static::doGetUploadLocation($settings);
file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
$destination = $dirname . '/' . $random
->name(10, TRUE) . '.txt';
$data = $random
->paragraphs(3);
$file = file_save_data($data, $destination, FILE_EXISTS_ERROR);
$values = array(
'target_id' => $file
->id(),
'display' => (int) $settings['display_default'],
'description' => $random
->sentences(10),
);
return $values;
}
public function isDisplayed() {
if ($this
->getSetting('display_field')) {
return (bool) $this->display;
}
return TRUE;
}
public static function getPreconfiguredOptions() {
return [];
}
}