class FileItem

Same name and namespace in other branches
  1. 10 core/modules/file/src/Plugin/Field/FieldType/FileItem.php \Drupal\file\Plugin\Field\FieldType\FileItem
  2. 11.x core/modules/file/src/Plugin/Field/FieldType/FileItem.php \Drupal\file\Plugin\Field\FieldType\FileItem
  3. 9 core/modules/file/src/Plugin/Field/FieldType/FileItem.php \Drupal\file\Plugin\Field\FieldType\FileItem
  4. 8.9.x core/modules/file/src/Plugin/Field/FieldType/FileItem.php \Drupal\file\Plugin\Field\FieldType\FileItem

Plugin implementation of the 'file' field type.

Attributes

#[FieldType(id: "file", label: new TranslatableMarkup("File"), description: [ new TranslatableMarkup("Downloadable files"), new TranslatableMarkup("Configure allowed file extensions, maximum upload size, and storage location"), new TranslatableMarkup("Examples: document (pdf, txt), audio (mp3), video (avi, mov), downloadable image (jpeg, png, webp, gif), etc."), ], category: "file_upload", default_widget: "file_generic", default_formatter: "file_default", list_class: FileFieldItemList::class, constraints: [ "ReferenceAccess" => [], "FileValidation" => [], ], column_groups: [ 'target_id' => [ 'label' => new TranslatableMarkup('File'), 'translatable' => TRUE, ], 'display' => [ 'label' => new TranslatableMarkup('Display'), 'translatable' => TRUE, ], 'description' => [ 'label' => new TranslatableMarkup('Description'), 'translatable' => TRUE, ], ])]

Hierarchy

Expanded class hierarchy of FileItem

5 files declare their use of FileItem
FileItemTest.php in core/modules/file/tests/src/Kernel/FileItemTest.php
FileUploadForm.php in core/modules/media_library/src/Form/FileUploadForm.php
FileUploadLocationTrait.php in core/modules/file/src/Upload/FileUploadLocationTrait.php
ImageItem.php in core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
XmlEntityNormalizationQuirksTrait.php in core/modules/rest/tests/src/Functional/EntityResource/XmlEntityNormalizationQuirksTrait.php

File

core/modules/file/src/Plugin/Field/FieldType/FileItem.php, line 25

Namespace

Drupal\file\Plugin\Field\FieldType
View source
class FileItem extends EntityReferenceItem {
  use FileValidatorSettingsTrait;
  
  /**
   * {@inheritdoc}
   */
  public static function defaultStorageSettings() {
    return [
      'target_type' => 'file',
      'display_field' => FALSE,
      'display_default' => FALSE,
      'uri_scheme' => \Drupal::config('system.file')->get('default_scheme'),
    ] + parent::defaultStorageSettings();
  }
  
  /**
   * {@inheritdoc}
   */
  public static function defaultFieldSettings() {
    return [
      'file_extensions' => 'txt',
      'file_directory' => '[date:custom:Y]-[date:custom:m]',
      'max_filesize' => '',
      'description_field' => 0,
    ] + parent::defaultFieldSettings();
  }
  
  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'target_id' => [
          'description' => 'The ID of the file entity.',
          'type' => 'int',
          'unsigned' => TRUE,
        ],
        'display' => [
          'description' => 'Flag to control whether this file should be displayed when viewing content.',
          'type' => 'int',
          'size' => 'tiny',
          'unsigned' => TRUE,
          'default' => 1,
        ],
        'description' => [
          'description' => 'A description of the file.',
          'type' => 'text',
        ],
      ],
      'indexes' => [
        'target_id' => [
          'target_id',
        ],
      ],
      'foreign keys' => [
        'target_id' => [
          'table' => 'file_managed',
          'columns' => [
            'target_id' => 'fid',
          ],
        ],
      ],
    ];
  }
  
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties = parent::propertyDefinitions($field_definition);
    $properties['display'] = DataDefinition::create('boolean')->setLabel(new TranslatableMarkup('Display'))
      ->setDescription(new TranslatableMarkup('Flag to control whether this file should be displayed when viewing content'));
    $properties['description'] = DataDefinition::create('string')->setLabel(new TranslatableMarkup('Description'));
    return $properties;
  }
  
  /**
   * {@inheritdoc}
   */
  public static function storageSettingsSummary(FieldStorageDefinitionInterface $storage_definition) : array {
    // Bypass the parent setting summary as it produces redundant information.
    return [];
  }
  
  /**
   * {@inheritdoc}
   */
  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
    $element = [];
    $element['#attached']['library'][] = 'file/drupal.file';
    $element['display_field'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable <em>Display</em> field'),
      '#default_value' => $this->getSetting('display_field'),
      '#description' => $this->t('The display option allows users to choose if a file should be shown when viewing the content.'),
    ];
    $element['display_default'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Files displayed by default'),
      '#default_value' => $this->getSetting('display_default'),
      '#description' => $this->t('This setting only has an effect if the display option is enabled.'),
      '#states' => [
        'visible' => [
          ':input[name="field_storage[subform][settings][display_field]"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    $scheme_options = \Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::WRITE_VISIBLE);
    $element['uri_scheme'] = [
      '#type' => 'radios',
      '#title' => $this->t('Upload destination'),
      '#options' => $scheme_options,
      '#default_value' => $this->getSetting('uri_scheme'),
      '#description' => $this->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;
  }
  
  /**
   * {@inheritdoc}
   */
  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
    $element = [];
    $settings = $this->getSettings();
    $element['file_directory'] = [
      '#type' => 'textfield',
      '#title' => $this->t('File directory'),
      '#default_value' => $settings['file_directory'],
      '#description' => $this->t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
      '#element_validate' => [
        [
          static::class,
          'validateDirectory',
        ],
      ],
      '#weight' => 3,
    ];
    // Make the extension list a little more human-friendly by comma-separation.
    $extensions = str_replace(' ', ', ', $settings['file_extensions']);
    $element['file_extensions'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Allowed file extensions'),
      '#default_value' => $extensions,
      '#description' => $this->t("Separate extensions with a comma or space. Each extension can contain alphanumeric characters, '.', and '_', and should start and end with an alphanumeric character."),
      '#element_validate' => [
        [
          static::class,
          'validateExtensions',
        ],
      ],
      '#weight' => 1,
      '#maxlength' => 256,
      // By making this field required, we prevent a potential security issue
      // that would allow files of any type to be uploaded.
'#required' => TRUE,
    ];
    $element['max_filesize'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Maximum upload size'),
      '#default_value' => $settings['max_filesize'],
      '#description' => $this->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 could be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', [
        '%limit' => ByteSizeMarkup::create(Environment::getUploadMaxSize()),
      ]),
      '#size' => 10,
      '#element_validate' => [
        [
          static::class,
          'validateMaxFilesize',
        ],
      ],
      '#weight' => 5,
    ];
    $element['description_field'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable <em>Description</em> field'),
      '#default_value' => $settings['description_field'] ?? '',
      '#description' => $this->t('The description field allows users to enter a description about the uploaded file.'),
      '#weight' => 11,
    ];
    return $element;
  }
  
  /**
   * Form API callback.
   *
   * Removes slashes from the beginning and end of the destination value and
   * ensures that the file directory path is not included at the beginning of
   * the value.
   *
   * This function is assigned as an #element_validate callback in
   * fieldSettingsForm().
   */
  public static function validateDirectory($element, FormStateInterface $form_state) {
    // Strip slashes from the beginning and end of $element['file_directory'].
    $value = trim($element['#value'], '\\/');
    $form_state->setValueForElement($element, $value);
  }
  
  /**
   * Form API callback.
   *
   * This function is assigned as an #element_validate callback in
   * fieldSettingsForm().
   *
   * This doubles as a convenience clean-up function and a validation routine.
   * Commas are allowed by the end-user, but ultimately the value will be stored
   * as a space-separated list for compatibility with the 'FileExtension'
   * constraint.
   */
  public static function validateExtensions($element, FormStateInterface $form_state) {
    if (!empty($element['#value'])) {
      $extensions = preg_replace('/([, ]+\\.?)/', ' ', trim(strtolower($element['#value'])));
      $extension_array = array_unique(array_filter(explode(' ', $extensions)));
      $extensions = implode(' ', $extension_array);
      if (!preg_match('/^([a-z0-9]+([._][a-z0-9])* ?)+$/', $extensions)) {
        $form_state->setError($element, new TranslatableMarkup("The list of allowed extensions is not valid. Allowed characters are a-z, 0-9, '.', and '_'. The first and last characters cannot be '.' or '_', and these two characters cannot appear next to each other. Separate extensions with a comma or space."));
      }
      else {
        $form_state->setValueForElement($element, $extensions);
      }
      // If insecure uploads are not allowed and txt is not in the list of
      // allowed extensions, ensure that no insecure extensions are allowed.
      if (!in_array('txt', $extension_array, TRUE) && !\Drupal::config('system.file')->get('allow_insecure_uploads')) {
        foreach ($extension_array as $extension) {
          if (preg_match(FileSystemInterface::INSECURE_EXTENSION_REGEX, 'test.' . $extension)) {
            $form_state->setError($element, new TranslatableMarkup('Add %txt_extension to the list of allowed extensions to securely upload files with a %extension extension. The %txt_extension extension will then be added automatically.', [
              '%extension' => $extension,
              '%txt_extension' => 'txt',
            ]));
            break;

          }
        }
      }
    }
  }
  
  /**
   * Form API callback.
   *
   * Ensures that a size has been entered and that it can be parsed by
   * \Drupal\Component\Utility\Bytes::toNumber().
   *
   * This function is assigned as an #element_validate callback in
   * fieldSettingsForm().
   */
  public static function validateMaxFilesize($element, FormStateInterface $form_state) {
    $element['#value'] = trim($element['#value']);
    $form_state->setValue([
      'settings',
      'max_filesize',
    ], $element['#value']);
    if (!empty($element['#value']) && !Bytes::validate($element['#value'])) {
      $form_state->setError($element, new TranslatableMarkup('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).', [
        '@name' => $element['#title'],
      ]));
    }
  }
  
  /**
   * Determines the URI for a file field.
   *
   * @param array $data
   *   An array of token objects to pass to Token::replace().
   *
   * @return string
   *   An unsanitized file directory URI with tokens replaced. The result of
   *   the token replacement is then converted to plain text and returned.
   *
   * @see \Drupal\Core\Utility\Token::replace()
   */
  public function getUploadLocation($data = []) {
    return static::doGetUploadLocation($this->getSettings(), $data);
  }
  
  /**
   * Determines the URI for a file field.
   *
   * @param array $settings
   *   The array of field settings.
   * @param array $data
   *   An array of token objects to pass to Token::replace().
   *
   * @return string
   *   An unsanitized file directory URI with tokens replaced. The result of
   *   the token replacement is then converted to plain text and returned.
   *
   * @see \Drupal\Core\Utility\Token::replace()
   */
  protected static function doGetUploadLocation(array $settings, $data = []) {
    $destination = trim($settings['file_directory'], '/');
    // Replace tokens. As the tokens might contain HTML we convert it to plain
    // text.
    $destination = PlainTextOutput::renderFromHtml(\Drupal::token()->replace($destination, $data));
    return $settings['uri_scheme'] . '://' . $destination;
  }
  
  /**
   * Retrieves the upload validators for a file field.
   *
   * @return array
   *   An array suitable for passing to file_save_upload() or the file field
   *   element's '#upload_validators' property.
   */
  public function getUploadValidators() {
    return $this->getFileUploadValidators($this->getSettings());
  }
  
  /**
   * {@inheritdoc}
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
    $random = new Random();
    $settings = $field_definition->getSettings();
    // Prepare destination.
    $dirname = static::doGetUploadLocation($settings);
    \Drupal::service('file_system')->prepareDirectory($dirname, FileSystemInterface::CREATE_DIRECTORY);
    // Ensure directory ends with a slash.
    $dirname .= str_ends_with($dirname, '/') ? '' : '/';
    // Determine which extension to use when generating.
    $extension = 'txt';
    if (!empty($settings['file_extensions'])) {
      $extensions = explode(' ', $settings['file_extensions']);
      $extension = array_rand(array_flip($extensions), 1);
    }
    // Generate a file entity.
    $destination = $dirname . $random->name(10, TRUE) . '.' . $extension;
    $data = $random->paragraphs(3);
    /** @var \Drupal\file\FileRepositoryInterface $file_repository */
    $file_repository = \Drupal::service('file.repository');
    $file = $file_repository->writeData($data, $destination, FileExists::Error);
    $values = [
      'target_id' => $file->id(),
      'display' => (int) $settings['display_default'],
      'description' => $random->sentences(10),
    ];
    return $values;
  }
  
  /**
   * Determines whether an item should be displayed when rendering the field.
   *
   * @return bool
   *   TRUE if the item should be displayed, FALSE if not.
   */
  public function isDisplayed() {
    if ($this->getSetting('display_field')) {
      return (bool) $this->display;
    }
    return TRUE;
  }
  
  /**
   * {@inheritdoc}
   */
  public static function getPreconfiguredOptions() {
    return [];
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 2
DependencySerializationTrait::__wakeup public function 2
EntityReferenceItem::calculateDependencies public static function Overrides FieldItemBase::calculateDependencies
EntityReferenceItem::calculateStorageDependencies public static function Overrides FieldItemBase::calculateStorageDependencies
EntityReferenceItem::fieldSettingsAjaxProcess public static function Render API callback: Processes the field settings form.
EntityReferenceItem::fieldSettingsAjaxProcessElement public static function Adds the field settings to AJAX form elements.
EntityReferenceItem::fieldSettingsFormValidate public static function Form element validation handler; Invokes selection plugin&#039;s validation.
EntityReferenceItem::fieldSettingsSummary public static function Overrides FieldItemBase::fieldSettingsSummary
EntityReferenceItem::formProcessMergeParent public static function Render API callback that moves entity reference elements up a level.
EntityReferenceItem::getConstraints public function Overrides TypedData::getConstraints
EntityReferenceItem::getPossibleOptions public function Overrides OptionsProviderInterface::getPossibleOptions
EntityReferenceItem::getPossibleValues public function Overrides OptionsProviderInterface::getPossibleValues
EntityReferenceItem::getRandomBundle protected static function Gets a bundle for a given entity type and selection options.
EntityReferenceItem::getReferenceableBundles public static function Overrides EntityReferenceItemInterface::getReferenceableBundles
EntityReferenceItem::getSettableOptions public function Overrides OptionsProviderInterface::getSettableOptions
EntityReferenceItem::getSettableValues public function Overrides OptionsProviderInterface::getSettableValues
EntityReferenceItem::getValue public function Overrides Map::getValue
EntityReferenceItem::hasNewEntity public function Determines whether the item holds an unsaved entity. 1
EntityReferenceItem::isEmpty public function Overrides Map::isEmpty 1
EntityReferenceItem::mainPropertyName public static function Overrides FieldItemBase::mainPropertyName 1
EntityReferenceItem::onChange public function Overrides Map::onChange 1
EntityReferenceItem::onDependencyRemoval public static function Overrides FieldItemBase::onDependencyRemoval
EntityReferenceItem::preSave public function Overrides FieldItemBase::preSave 2
EntityReferenceItem::settingsAjaxSubmit public static function Submit handler for the non-JS case.
EntityReferenceItem::setValue public function Overrides FieldItemBase::setValue 1
EntityReferenceItemBase::__get public function Overrides FieldItemBase::__get
FieldItemBase::delete public function Overrides FieldItemInterface::delete 2
FieldItemBase::deleteRevision public function Overrides FieldItemInterface::deleteRevision
FieldItemBase::fieldSettingsFromConfigData public static function Overrides FieldItemInterface::fieldSettingsFromConfigData 1
FieldItemBase::fieldSettingsToConfigData public static function Overrides FieldItemInterface::fieldSettingsToConfigData 1
FieldItemBase::getEntity public function Overrides FieldItemInterface::getEntity
FieldItemBase::getFieldDefinition public function Overrides FieldItemInterface::getFieldDefinition
FieldItemBase::getLangcode public function Overrides FieldItemInterface::getLangcode
FieldItemBase::getSetting protected function Returns the value of a field setting.
FieldItemBase::getSettings protected function Returns the array of field settings.
FieldItemBase::postSave public function Overrides FieldItemInterface::postSave 2
FieldItemBase::storageSettingsFromConfigData public static function Overrides FieldItemInterface::storageSettingsFromConfigData 2
FieldItemBase::storageSettingsToConfigData public static function Overrides FieldItemInterface::storageSettingsToConfigData 2
FieldItemBase::view public function Overrides FieldItemInterface::view
FieldItemBase::writePropertyValue protected function Different to the parent Map class, we avoid creating property objects as
far as possible in order to optimize performance. Thus we just update
$this-&gt;values if no property object has been created yet.
Overrides Map::writePropertyValue
FieldItemBase::__construct public function Overrides TypedData::__construct 3
FieldItemBase::__isset public function Overrides FieldItemInterface::__isset
FieldItemBase::__set public function Overrides FieldItemInterface::__set 1
FieldItemBase::__unset public function Overrides FieldItemInterface::__unset
FileItem::defaultFieldSettings public static function Defines the field-level settings for this plugin. Overrides EntityReferenceItem::defaultFieldSettings 1
FileItem::defaultStorageSettings public static function Defines the storage-level settings for this plugin. Overrides EntityReferenceItem::defaultStorageSettings 1
FileItem::doGetUploadLocation protected static function Determines the URI for a file field.
FileItem::fieldSettingsForm public function Returns a form for the field-level settings. Overrides EntityReferenceItem::fieldSettingsForm 1
FileItem::generateSampleValue public static function Generates placeholder field values. Overrides EntityReferenceItem::generateSampleValue 1
FileItem::getPreconfiguredOptions public static function Returns preconfigured field options for a field type. Overrides EntityReferenceItem::getPreconfiguredOptions
FileItem::getUploadLocation public function Determines the URI for a file field.
FileItem::getUploadValidators public function Retrieves the upload validators for a file field.
FileItem::isDisplayed public function Determines whether an item should be displayed when rendering the field. 1
FileItem::propertyDefinitions public static function Defines field item properties. Overrides EntityReferenceItem::propertyDefinitions 1
FileItem::schema public static function Returns the schema for the field. Overrides EntityReferenceItem::schema 1
FileItem::storageSettingsForm public function Returns a form for the storage-level settings. Overrides EntityReferenceItem::storageSettingsForm 1
FileItem::storageSettingsSummary public static function Returns a short summary of the field&#039;s storage-level settings. Overrides EntityReferenceItem::storageSettingsSummary 1
FileItem::validateDirectory public static function Form API callback.
FileItem::validateExtensions public static function Form API callback.
FileItem::validateMaxFilesize public static function Form API callback.
FileValidatorSettingsTrait::getFileUploadValidators public function Gets the upload validators for the specified settings.
Map::$definition protected property The data definition. Overrides TypedData::$definition
Map::$properties protected property The array of properties.
Map::$values protected property An array of values for the contained properties.
Map::applyDefaultValue public function Overrides TypedData::applyDefaultValue 4
Map::get public function Overrides ComplexDataInterface::get
Map::getIterator public function Retrieves the iterator for the object.
Map::getProperties public function Overrides ComplexDataInterface::getProperties
Map::getString public function Overrides TypedData::getString
Map::set public function Overrides ComplexDataInterface::set
Map::toArray public function Overrides ComplexDataInterface::toArray 1
Map::__clone public function Magic method: Implements a deep clone.
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language. 1
TypedData::$name protected property The property name.
TypedData::$parent protected property The parent typed data object.
TypedData::createInstance public static function Overrides TypedDataInterface::createInstance
TypedData::getDataDefinition public function Overrides TypedDataInterface::getDataDefinition
TypedData::getName public function Overrides TypedDataInterface::getName
TypedData::getParent public function Overrides TypedDataInterface::getParent
TypedData::getPluginDefinition public function Overrides PluginInspectionInterface::getPluginDefinition
TypedData::getPluginId public function Overrides PluginInspectionInterface::getPluginId
TypedData::getPropertyPath public function Overrides TypedDataInterface::getPropertyPath
TypedData::getRoot public function Overrides TypedDataInterface::getRoot
TypedData::setContext public function Overrides TypedDataInterface::setContext
TypedData::validate public function Overrides TypedDataInterface::validate
TypedDataTrait::$typedDataManager protected property The typed data manager used for creating the data types.
TypedDataTrait::getTypedDataManager public function Gets the typed data manager. 2
TypedDataTrait::setTypedDataManager public function Sets the typed data manager. 2

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.