Completed
Pull Request — 8.x-1.x (#153)
by
unknown
02:38
created

Upload::buildConfigurationForm()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 20
nc 2
nop 2
dl 0
loc 31
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\entity_browser\Plugin\EntityBrowser\Widget;
4
5
use Drupal\Component\Utility\NestedArray;
6
use Drupal\Core\Entity\EntityTypeManagerInterface;
7
use Drupal\Core\Extension\ModuleHandlerInterface;
8
use Drupal\Core\Form\FormStateInterface;
9
use Drupal\Core\Utility\Token;
10
use Drupal\entity_browser\WidgetBase;
11
use Drupal\entity_browser\WidgetValidationManager;
12
use Drupal\file\FileInterface;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
16
/**
17
 * Uses a view to provide entity listing in a browser's widget.
18
 *
19
 * @EntityBrowserWidget(
20
 *   id = "upload",
21
 *   label = @Translation("Upload"),
22
 *   description = @Translation("Adds an upload field browser's widget."),
23
 *   autoSelect = FALSE
24
 * )
25
 */
26
class Upload extends WidgetBase {
27
28
  /**
29
   * The module handler service.
30
   *
31
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
32
   */
33
  protected $moduleHandler;
34
35
  /**
36
   * The token service.
37
   *
38
   * @var \Drupal\Core\Utility\Token
39
   */
40
  protected $token;
41
42
  /**
43
   * Upload constructor.
44
   *
45
   * @param array $configuration
46
   *   A configuration array containing information about the plugin instance.
47
   * @param string $plugin_id
48
   *   The plugin_id for the plugin instance.
49
   * @param mixed $plugin_definition
50
   *   The plugin implementation definition.
51
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
52
   *   Event dispatcher service.
53
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
54
   *   The entity type manager service.
55
   * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
56
   *   The Widget Validation Manager service.
57
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
58
   *   The module handler.
59
   * @param \Drupal\Core\Utility\Token $token
60
   *   The token service.
61
   */
62
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager, ModuleHandlerInterface $module_handler, Token $token) {
63
    parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_type_manager, $validation_manager);
64
    $this->moduleHandler = $module_handler;
65
    $this->token = $token;
66
  }
67
68
  /**
69
   * {@inheritdoc}
70
   */
71
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
72
    return new static(
73
      $configuration,
74
      $plugin_id,
75
      $plugin_definition,
76
      $container->get('event_dispatcher'),
77
      $container->get('entity_type.manager'),
78
      $container->get('plugin.manager.entity_browser.widget_validation'),
79
      $container->get('module_handler'),
80
      $container->get('token')
81
    );
82
  }
83
84
  /**
85
   * {@inheritdoc}
86
   */
87
  public function defaultConfiguration() {
88
    return [
89
      'upload_location' => 'public://',
90
      'submit_text' => $this->t('Select files'),
91
    ] + parent::defaultConfiguration();
92
  }
93
94
  /**
95
   * {@inheritdoc}
96
   */
97
  public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
98
    $form = parent::getForm($original_form, $form_state, $additional_widget_parameters);
99
    $form['upload'] = [
100
      '#type' => 'managed_file',
101
      '#title' => $this->t('Choose a file'),
102
      '#title_display' => 'invisible',
103
      '#upload_location' => $this->token->replace($this->configuration['upload_location']),
104
      '#multiple' => TRUE,
105
    ];
106
107
    return $form;
108
  }
109
110
  /**
111
   * {@inheritdoc}
112
   */
113
  protected function prepareEntities(array $form, FormStateInterface $form_state) {
114
    $files = [];
115
    foreach ($form_state->getValue(['upload'], []) as $fid) {
116
      $files[] = $this->entityTypeManager->getStorage('file')->load($fid);
117
    }
118
    return $files;
119
  }
120
121
  /**
122
   * {@inheritdoc}
123
   */
124
  public function submit(array &$element, array &$form, FormStateInterface $form_state) {
125
    if (!empty($form_state->getTriggeringElement()['#eb_widget_main_submit'])) {
126
      $files = $this->prepareEntities($form, $form_state);
127
      array_walk(
128
        $files,
129
        function (FileInterface $file) {
130
          $file->setPermanent();
131
          $file->save();
132
        }
133
      );
134
      $this->selectEntities($files, $form_state);
135
      $this->clearFormValues($element, $form_state);
136
    }
137
  }
138
139
  /**
140
   * Clear values from upload form element.
141
   *
142
   * @param array $element
143
   *   Upload form element.
144
   * @param \Drupal\Core\Form\FormStateInterface $form_state
145
   *   Form state object.
146
   */
147
  protected function clearFormValues(array &$element, FormStateInterface $form_state) {
148
    // We propagated entities to the other parts of the system. We can now remove
149
    // them from our values.
150
    $form_state->setValueForElement($element['upload']['fids'], '');
151
    NestedArray::setValue($form_state->getUserInput(), $element['upload']['fids']['#parents'], '');
152
  }
153
154
  /**
155
   * {@inheritdoc}
156
   */
157
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
158
    $form['upload_location'] = [
159
      '#type' => 'textfield',
160
      '#title' => $this->t('Upload location'),
161
      '#default_value' => $this->configuration['upload_location'],
162
    ];
163
164
    $form['submit_text'] = [
165
      '#type' => 'textfield',
166
      '#title' => $this->t('Submit button text'),
167
      '#default_value' => $this->configuration['submit_text'],
168
    ];
169
170
    // Allow "auto_select" setting when autoSelect is supported by widget.
171
    $form['auto_select'] = [
172
      '#type' => 'checkbox',
173
      '#title' => $this->t('Automatically submit selection'),
174
      '#default_value' => $this->configuration['auto_select'],
175
      '#disabled' => !$this->getPluginDefinition()['autoSelect'],
176
    ];
177
178
    if ($this->moduleHandler->moduleExists('token')) {
179
      $form['token_help'] = [
180
        '#theme' => 'token_tree_link',
181
        '#token_types' => ['file'],
182
      ];
183
      $form['upload_location']['#description'] = $this->t('You can use tokens in the upload location.');
184
    }
185
186
    return $form;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $form; (array<string,array>) is incompatible with the return type of the parent method Drupal\entity_browser\Wi...:buildConfigurationForm of type array<string,array>.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
187
  }
188
189
}
190