class FileAddForm in File Entity (fieldable files) 8.2
Form controller for file type forms.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\file_entity\Form\FileAddForm uses UploadValidatorsTrait
Expanded class hierarchy of FileAddForm
1 string reference to 'FileAddForm'
File
- src/
Form/ FileAddForm.php, line 25
Namespace
Drupal\file_entity\FormView source
class FileAddForm extends FormBase {
use UploadValidatorsTrait;
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* {@inheritdoc}
*/
public function __construct(RendererInterface $renderer, EntityTypeManagerInterface $entity_type_manager, FileSystemInterface $file_system, MessengerInterface $messenger) {
$this->renderer = $renderer;
$this->entityTypeManager = $entity_type_manager;
$this->fileSystem = $file_system;
$this->messenger = $messenger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('renderer'), $container
->get('entity_type.manager'), $container
->get('file_system'), $container
->get('messenger'));
}
/**
* Returns a unique string identifying the form.
*
* @return string
* The unique string identifying the form.
*/
public function getFormId() {
return 'file_add';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, array $options = array()) {
$step = in_array($form_state
->get('step'), array(
1,
2,
3,
4,
)) ? $form_state
->get('step') : 1;
$form_state
->set('step', $step);
$form_state
->set('options', $options);
switch ($step) {
case 1:
return $this
->stepUpload($form, $form_state, $options);
case 2:
return $this
->stepFileType($form, $form_state);
case 3:
return $this
->stepScheme($form, $form_state);
case 4:
return $this
->stepFields($form, $form_state);
}
return FALSE;
}
/**
* Step 1
* Generate form fields for the first step in the add file wizard.
*
* @param array $form
* Holds form data
* @param FormStateInterface $form_state
* Holds form state data
* @return array
* Returns form data
*/
function stepUpload(array $form, FormStateInterface $form_state) {
$options = [
'file_extensions' => \Drupal::config('file_entity.settings')
->get('default_allowed_extensions'),
];
$options = $form_state
->get('options') ? $form_state
->get('options') : $options;
$validators = $this
->getUploadValidators($options);
$form['upload'] = array(
'#type' => 'managed_file',
'#title' => t('Upload a new file'),
'#upload_location' => $this
->getUploadDestinationUri($form_state
->get('options')),
'#upload_validators' => $validators,
'#progress_indicator' => 'bar',
'#required' => TRUE,
'#default_value' => $form_state
->has('file') ? array(
$form_state
->get('file')
->id(),
) : NULL,
);
$file_upload_help = array(
'#theme' => 'file_upload_help',
'#upload_validators' => $form['upload']['#upload_validators'],
);
$form['upload']['#description'] = $this->renderer
->render($file_upload_help);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['next'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => t('Next'),
);
return $form;
}
/**
* Determines the upload location for the file add upload form.
*
* @param array $params
* An array of parameters from the media browser.
* @param array $data
* (optional) An array of token objects to pass to token_replace().
*
* @return string
* A file directory URI with tokens replaced.
*
* @see token_replace()
*/
function getUploadDestinationUri(array $params, array $data = array()) {
$params += array(
'uri_scheme' => $this
->config('system.file')
->get('default_scheme'),
'file_directory' => '',
);
$destination = trim($params['file_directory'], '/');
// Replace tokens.
$destination = \Drupal::token()
->replace($destination, $data);
return $params['uri_scheme'] . '://' . $destination;
}
/**
* Form Step 2
* Select file types.
*
* Skipped if there is only one file type known for the uploaded file.
*
* @param $form
* @param $form_state
*/
function stepFileType(array $form, FormStateInterface $form_state) {
$file = $form_state
->get('file');
$form['type'] = array(
'#type' => 'radios',
'#title' => t('File type'),
'#options' => $this
->getCandidateFileTypes($file),
'#default_value' => $form_state
->get('type'),
'#required' => TRUE,
);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => t('Previous'),
'#limit_validation_errors' => array(),
);
$form['actions']['next'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => t('Next'),
);
return $form;
}
/**
* Get the candidate filetypes for a given file.
*
* Only filetypes for which the user has access to create entities are returned.
*
* @param \Drupal\file\FileInterface $file
* An upload file from form_state.
*
* @return array
* An array of file type bundles that support the file's mime type.
*/
function getCandidateFileTypes(FileInterface $file) {
$types = \Drupal::moduleHandler()
->invokeAll('file_type', array(
$file,
));
\Drupal::moduleHandler()
->alter('file_type', $types, $file);
$candidates = array();
foreach ($types as $type) {
if ($has_access = $this->entityTypeManager
->getAccessControlHandler('file')
->createAccess($type)) {
$candidates[$type] = FileType::load($type)
->label();
}
}
return $candidates;
}
/**
* Form Step 3
*
* @param $form
* @param $form_state
* @return mixed
*/
function stepScheme(array $form, FormStateInterface $form_state) {
$options = array();
foreach (\Drupal::service('stream_wrapper_manager')
->getDescriptions(StreamWrapperInterface::WRITE_VISIBLE) as $scheme => $description) {
$options[$scheme] = Html::escape($description);
}
$form['scheme'] = array(
'#type' => 'radios',
'#title' => t('Destination'),
'#options' => $options,
'#default_value' => $form_state
->get('scheme') ?: $this
->config('system.file')
->get('default_scheme'),
'#required' => TRUE,
);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => t('Previous'),
'#limit_validation_errors' => array(),
);
$form['actions']['next'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => t('Next'),
);
return $form;
}
/**
* Step 4
*
* @param $form
* @param $form_state
*/
function stepFields(array $form, FormStateInterface $form_state) {
// Load the file and overwrite the filetype set on the previous screen.
/** @var \Drupal\file\FileInterface$file*/
$file = $form_state
->get('file');
$form_state
->set('form_display', EntityFormDisplay::collectRenderDisplay($file, 'default'));
$form_state
->get('form_display')
->buildForm($file, $form, $form_state);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => t('Previous'),
'#limit_validation_errors' => array(),
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => t('Save'),
);
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state
->get('step') == 4) {
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
$form_display = $form_state
->get('form_display');
$form_display
->extractFormValues($form_state
->get('file'), $form, $form_state);
$form_display
->validateFormValues($form_state
->get('file'), $form, $form_state);
}
parent::validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// This var is set to TRUE when we are ready to save the file.
$save = FALSE;
$trigger = $form_state
->getTriggeringElement()['#id'];
$current_step = $form_state
->get('step');
// Store select values in $form_state.
foreach (array(
'type',
'scheme',
) as $key) {
if ($form_state
->hasValue($key)) {
$form_state
->set($key, $form_state
->getValue($key));
}
}
$steps_to_check = array(
2,
3,
);
if ($trigger == 'edit-previous') {
// If the previous button was hit,
// the step checking order should be reversed 3, 2.
$steps_to_check = array_reverse($steps_to_check);
}
/* @var \Drupal\file\FileInterface $file */
if ($form_state
->has('file')) {
$file = $form_state
->get('file');
}
else {
$file = File::load($form_state
->getValue(array(
'upload',
0,
)));
$form_state
->set('file', $file);
}
foreach ($steps_to_check as $step) {
// Check if we can skip step 2 and 3.
if ($current_step == $step - 1 && $trigger == 'edit-next' || $current_step == $step + 1 && $trigger == 'edit-previous') {
if ($step == 2) {
// Check if we can skip step 2.
$candidates = $this
->getCandidateFileTypes($file);
if (count($candidates) == 1) {
$candidates_keys = array_keys($candidates);
// There is only one possible filetype for this file.
// Skip the second page.
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('type', reset($candidates_keys));
}
elseif (\Drupal::config('file_entity.settings')
->get('wizard_skip_file_type')) {
// Do not assign the file a file type.
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('type', FILE_TYPE_NONE);
}
}
else {
// Check if we can skip step 3.
$schemes = \Drupal::service('stream_wrapper_manager')
->getWrappers(StreamWrapperInterface::WRITE_VISIBLE);
if (!$file
->isWritable()) {
// The file is read-only (remote) and must use its provided scheme.
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', StreamWrapperManager::getScheme($file
->getFileUri()));
}
elseif (count($schemes) == 1) {
// There is only one possible stream wrapper for this file.
// Skip the third page.
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', key($schemes));
}
elseif (\Drupal::config('file_entity.settings')
->get('wizard_skip_scheme')) {
// Assign the file the default scheme.
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', $this
->config('system.file')
->get('default_scheme'));
}
}
}
}
// We have the filetype, check if we can skip step 4.
if ($current_step == 3 && $trigger == 'edit-next') {
$file
->updateBundle($form_state
->get('type'));
$save = TRUE;
foreach ($file
->getFieldDefinitions() as $field_definition) {
if ($field_definition instanceof FieldConfigInterface) {
// This filetype does have configurable fields, do not save as we
// do step 4 first.
$save = FALSE;
break;
}
}
if ($this
->config('file_entity.settings')
->get('wizard_skip_fields', FALSE)) {
// Save the file with blanks fields.
$save = TRUE;
}
}
// Form id's can vary depending on how many other forms are displayed, so we
// need to do string comparissons. e.g edit-submit--2.
if (strpos($trigger, 'edit-next') !== FALSE) {
$current_step++;
}
elseif (strpos($trigger, 'edit-previous') !== FALSE) {
$current_step--;
}
elseif (strpos($trigger, 'edit-submit') !== FALSE) {
$save = TRUE;
}
$form_state
->set('step', $current_step);
if ($save) {
if (StreamWrapperManager::getScheme($file
->getFileUri()) != $form_state
->get('scheme')) {
// @TODO: Users should not be allowed to create private files without permission ('view private files')
if ($moved_file = file_move($file, $form_state
->get('scheme') . '://' . StreamWrapperManager::getTarget($file
->getFileUri()), FileSystemInterface::EXISTS_RENAME)) {
// Only re-assign the file object if file_move() did not fail.
$moved_file
->setFilename($file
->getFilename());
$file = $moved_file;
}
}
$file->display = TRUE;
// Change the file from temporary to permanent.
$file->status = FILE_STATUS_PERMANENT;
// Save entity
$file
->save();
$form_state
->set('file', $file);
$this->messenger
->addMessage(t('@type %name was uploaded.', array(
'@type' => $file->type->entity
->label(),
'%name' => $file
->getFilename(),
)));
// Figure out destination.
if (\Drupal::currentUser()
->hasPermission('administer files')) {
$form_state
->setRedirect('entity.file.collection');
}
else {
$form_state
->setRedirectUrl($file
->toUrl());
}
}
else {
$form_state
->setRebuild();
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FileAddForm:: |
protected | property | The entity type manager. | |
FileAddForm:: |
protected | property | The file system service. | |
FileAddForm:: |
protected | property |
The messenger. Overrides MessengerTrait:: |
|
FileAddForm:: |
protected | property | The renderer. | |
FileAddForm:: |
public | function |
Form constructor. Overrides FormInterface:: |
|
FileAddForm:: |
public static | function |
Instantiates a new instance of this class. Overrides FormBase:: |
|
FileAddForm:: |
function | Get the candidate filetypes for a given file. | ||
FileAddForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
FileAddForm:: |
function | Determines the upload location for the file add upload form. | ||
FileAddForm:: |
function | Step 4 | ||
FileAddForm:: |
function | Form Step 2 Select file types. | ||
FileAddForm:: |
function | Form Step 3 | ||
FileAddForm:: |
function | Step 1 Generate form fields for the first step in the add file wizard. | ||
FileAddForm:: |
public | function |
Form submission handler. Overrides FormInterface:: |
|
FileAddForm:: |
public | function |
Form validation handler. Overrides FormBase:: |
|
FileAddForm:: |
public | function | ||
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UploadValidatorsTrait:: |
public | function | Retrieves the upload validators for a file or archive. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |