View source
<?php
namespace Drupal\file_entity\Form;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\field\FieldConfigInterface;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\file_entity\Entity\FileType;
use Drupal\file_entity\UploadValidatorsTrait;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FileAddForm extends FormBase {
use UploadValidatorsTrait;
protected $renderer;
protected $entityTypeManager;
protected $fileSystem;
protected $messenger;
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;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('renderer'), $container
->get('entity_type.manager'), $container
->get('file_system'), $container
->get('messenger'));
}
public function getFormId() {
return 'file_add';
}
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;
}
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;
}
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'], '/');
$destination = \Drupal::token()
->replace($destination, $data);
return $params['uri_scheme'] . '://' . $destination;
}
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;
}
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;
}
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;
}
function stepFields(array $form, FormStateInterface $form_state) {
$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;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state
->get('step') == 4) {
$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);
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$save = FALSE;
$trigger = $form_state
->getTriggeringElement()['#id'];
$current_step = $form_state
->get('step');
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') {
$steps_to_check = array_reverse($steps_to_check);
}
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) {
if ($current_step == $step - 1 && $trigger == 'edit-next' || $current_step == $step + 1 && $trigger == 'edit-previous') {
if ($step == 2) {
$candidates = $this
->getCandidateFileTypes($file);
if (count($candidates) == 1) {
$candidates_keys = array_keys($candidates);
$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')) {
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('type', FILE_TYPE_NONE);
}
}
else {
$schemes = \Drupal::service('stream_wrapper_manager')
->getWrappers(StreamWrapperInterface::WRITE_VISIBLE);
if (!$file
->isWritable()) {
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', StreamWrapperManager::getScheme($file
->getFileUri()));
}
elseif (count($schemes) == 1) {
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', key($schemes));
}
elseif (\Drupal::config('file_entity.settings')
->get('wizard_skip_scheme')) {
$current_step += $trigger == 'edit-previous' ? -1 : 1;
$form_state
->set('scheme', $this
->config('system.file')
->get('default_scheme'));
}
}
}
}
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) {
$save = FALSE;
break;
}
}
if ($this
->config('file_entity.settings')
->get('wizard_skip_fields', FALSE)) {
$save = TRUE;
}
}
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')) {
if ($moved_file = file_move($file, $form_state
->get('scheme') . '://' . StreamWrapperManager::getTarget($file
->getFileUri()), FileSystemInterface::EXISTS_RENAME)) {
$moved_file
->setFilename($file
->getFilename());
$file = $moved_file;
}
}
$file->display = TRUE;
$file->status = FILE_STATUS_PERMANENT;
$file
->save();
$form_state
->set('file', $file);
$this->messenger
->addMessage(t('@type %name was uploaded.', array(
'@type' => $file->type->entity
->label(),
'%name' => $file
->getFilename(),
)));
if (\Drupal::currentUser()
->hasPermission('administer files')) {
$form_state
->setRedirect('entity.file.collection');
}
else {
$form_state
->setRedirectUrl($file
->toUrl());
}
}
else {
$form_state
->setRebuild();
}
}
}