Issues (71)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/WidgetBase.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Drupal\entity_browser;
4
5
use Drupal\Component\Utility\NestedArray;
6
use Drupal\Core\Access\AccessResult;
7
use Drupal\Core\Entity\EntityTypeManagerInterface;
8
use Drupal\Core\Plugin\PluginBase;
9
use Drupal\Core\Form\FormStateInterface;
10
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
11
use Drupal\entity_browser\Events\EntitySelectionEvent;
12
use Drupal\entity_browser\Events\Events;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\Validator\ConstraintViolationList;
16
17
/**
18
 * Base class for widget plugins.
19
 */
20
abstract class WidgetBase extends PluginBase implements WidgetInterface, ContainerFactoryPluginInterface {
21
22
  use PluginConfigurationFormTrait;
23
24
  /**
25
   * Plugin id.
26
   *
27
   * @var string
28
   */
29
  protected $id;
30
31
  /**
32
   * Plugin uuid.
33
   *
34
   * @var string
35
   */
36
  protected $uuid;
37
  /**
38
   * Plugin label.
39
   *
40
   * @var string
41
   */
42
  protected $label;
43
44
  /**
45
   * Plugin weight.
46
   *
47
   * @var int
48
   */
49
  protected $weight;
50
51
  /**
52
   * Event dispatcher service.
53
   *
54
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
55
   */
56
  protected $eventDispatcher;
57
58
  /**
59
   * Entity type manager service.
60
   *
61
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
62
   */
63
  protected $entityTypeManager;
64
65
  /**
66
   * The Widget Validation Manager service.
67
   *
68
   * @var \Drupal\entity_browser\WidgetValidationManager
69
   */
70
  protected $validationManager;
71
72
  /**
73
   * WidgetBase constructor.
74
   *
75
   * @param array $configuration
76
   *   A configuration array containing information about the plugin instance.
77
   * @param string $plugin_id
78
   *   The plugin_id for the plugin instance.
79
   * @param mixed $plugin_definition
80
   *   The plugin implementation definition.
81
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
82
   *   Event dispatcher service.
83
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
84
   *   The entity type manager service.
85
   * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
86
   *   The Widget Validation Manager service.
87
   */
88 View Code Duplication
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
    parent::__construct($configuration, $plugin_id, $plugin_definition);
90
    $this->eventDispatcher = $event_dispatcher;
91
    $this->entityTypeManager = $entity_type_manager;
92
    $this->validationManager = $validation_manager;
93
    $this->setConfiguration($configuration);
94
  }
95
96
  /**
97
   * {@inheritdoc}
98
   */
99 View Code Duplication
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
    return new static(
101
      $configuration,
102
      $plugin_id,
103
      $plugin_definition,
104
      $container->get('event_dispatcher'),
105
      $container->get('entity_type.manager'),
106
      $container->get('plugin.manager.entity_browser.widget_validation')
107
    );
108
  }
109
110
  /**
111
   * {@inheritdoc}
112
   */
113
  public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
114
    $form = [];
115
116
    if ($form_state->has(['entity_browser', 'widget_context'])) {
117
      $this->handleWidgetContext($form_state->get(['entity_browser', 'widget_context']));
118
    }
119
120
    // Check if widget supports auto select functionality and expose config to
121
    // front-end javascript.
122
    $autoSelect = FALSE;
123
    if ($this->getPluginDefinition()['auto_select']) {
124
      $autoSelect = $this->configuration['auto_select'];
125
      $form['#attached']['drupalSettings']['entity_browser_widget']['auto_select'] = $autoSelect;
126
    }
127
128
    // In case of auto select, widget will handle adding entities in JS.
129
    if (!$autoSelect) {
130
      $form['actions'] = [
131
        '#type' => 'actions',
132
        'submit' => [
133
          '#type' => 'submit',
134
          '#value' => $this->configuration['submit_text'],
135
          '#eb_widget_main_submit' => TRUE,
136
          '#attributes' => ['class' => ['is-entity-browser-submit']],
137
          '#button_type' => 'primary',
138
        ],
139
      ];
140
    }
141
142
    return $form;
143
  }
144
145
  /**
146
   * {@inheritdoc}
147
   */
148
  public function defaultConfiguration() {
149
    $defaultConfig = [
150
      'submit_text' => $this->t('Select entities'),
151
    ];
152
153
    // If auto select is supported by Widget, append default configuration.
154
    if ($this->getPluginDefinition()['auto_select']) {
155
      $defaultConfig['auto_select'] = FALSE;
156
    }
157
158
    return $defaultConfig;
159
  }
160
161
  /**
162
   * {@inheritdoc}
163
   */
164
  public function getConfiguration() {
165
    return [
166
      'settings' => array_diff_key(
167
        $this->configuration,
168
        ['entity_browser_id' => 0]
169
      ),
170
      'uuid' => $this->uuid(),
171
      'weight' => $this->getWeight(),
172
      'label' => $this->label(),
173
      'id' => $this->id(),
174
    ];
175
  }
176
177
  /**
178
   * {@inheritdoc}
179
   */
180
  public function setConfiguration(array $configuration) {
181
    $configuration += [
182
      'settings' => [],
183
      'uuid' => '',
184
      'weight' => '',
185
      'label' => '',
186
      'id' => '',
187
    ];
188
189
    $this->configuration = NestedArray::mergeDeep(
190
      $this->defaultConfiguration(),
191
      $configuration['settings']
192
    );
193
    $this->label = $configuration['label'];
194
    $this->weight = $configuration['weight'];
195
    $this->uuid = $configuration['uuid'];
196
    $this->id = $configuration['id'];
197
  }
198
199
  /**
200
   * {@inheritdoc}
201
   */
202
  public function calculateDependencies() {
203
    return [];
204
  }
205
206
  /**
207
   * {@inheritdoc}
208
   */
209
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
210
    $form['submit_text'] = [
211
      '#type' => 'textfield',
212
      '#title' => $this->t('Submit button text'),
213
      '#default_value' => $this->configuration['submit_text'],
214
    ];
215
216
    // Allow "auto_select" setting when auto_select is supported by widget.
217
    if ($this->getPluginDefinition()['auto_select']) {
218
      $form['auto_select'] = [
219
        '#type' => 'checkbox',
220
        '#title' => $this->t('Automatically submit selection'),
221
        '#default_value' => $this->configuration['auto_select'],
222
      ];
223
    }
224
225
    return $form;
226
  }
227
228
  /**
229
   * {@inheritdoc}
230
   */
231
  public function id() {
232
    return $this->id;
233
  }
234
235
  /**
236
   * {@inheritdoc}
237
   */
238
  public function uuid() {
239
    return $this->uuid;
240
  }
241
242
  /**
243
   * {@inheritdoc}
244
   */
245
  public function label() {
246
    return $this->label;
247
  }
248
249
  /**
250
   * {@inheritdoc}
251
   */
252
  public function setLabel($label) {
253
    $this->label = $label;
254
    return $this;
255
  }
256
257
  /**
258
   * {@inheritdoc}
259
   */
260
  public function getWeight() {
261
    return $this->weight;
262
  }
263
264
  /**
265
   * {@inheritdoc}
266
   */
267
  public function setWeight($weight) {
268
    $this->weight = $weight;
269
    return $this;
270
  }
271
272
  /**
273
   * Prepares the entities without saving them.
274
   *
275
   * We need this method when we want to validate or perform other operations
276
   * before submit.
277
   *
278
   * @param array $form
279
   *   Complete form.
280
   * @param \Drupal\Core\Form\FormStateInterface $form_state
281
   *   The form state object.
282
   *
283
   * @return \Drupal\Core\Entity\EntityInterface[]
284
   *   Array of entities.
285
   */
286
  abstract protected function prepareEntities(array $form, FormStateInterface $form_state);
287
288
  /**
289
   * {@inheritdoc}
290
   */
291
  public function validate(array &$form, FormStateInterface $form_state) {
292
    $entities = $this->prepareEntities($form, $form_state);
293
    $validators = $form_state->get(['entity_browser', 'validators']);
294
    if ($validators) {
295
      $violations = $this->runWidgetValidators($entities, $validators);
296
      foreach ($violations as $violation) {
297
        $form_state->setError($form['widget'], $violation->getMessage());
298
      }
299
    }
300
  }
301
302
  /**
303
   * Run widget validators.
304
   *
305
   * @param array $entities
306
   *   Array of entity ids to validate.
307
   * @param array $validators
308
   *   Array of widget validator ids.
309
   *
310
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
311
   *   A list of constraint violations. If the list is empty, validation
312
   *   succeeded.
313
   */
314
  protected function runWidgetValidators(array $entities, $validators = []) {
315
    $violations = new ConstraintViolationList();
316
    foreach ($validators as $validator_id => $options) {
317
      /** @var \Drupal\entity_browser\WidgetValidationInterface $widget_validator */
318
      $widget_validator = $this->validationManager->createInstance($validator_id, []);
319
      if ($widget_validator) {
320
        $violations->addAll($widget_validator->validate($entities, $options));
321
      }
322
    }
323
324
    return $violations;
325
  }
326
327
  /**
328
   * {@inheritdoc}
329
   */
330
  public function submit(array &$element, array &$form, FormStateInterface $form_state) {}
331
332
  /**
333
   * Dispatches event that informs all subscribers about new selected entities.
334
   *
335
   * @param array $entities
336
   *   Array of entities.
337
   */
338
  protected function selectEntities(array $entities, FormStateInterface $form_state) {
339
    $selected_entities = &$form_state->get(['entity_browser', 'selected_entities']);
340
    $selected_entities = array_merge($selected_entities, $entities);
341
342
    $this->eventDispatcher->dispatch(
343
      Events::SELECTED,
344
      new EntitySelectionEvent(
345
        $this->configuration['entity_browser_id'],
346
        $form_state->get(['entity_browser', 'instance_uuid']),
347
        $entities
348
      ));
349
  }
350
351
  /**
352
   * {@inheritdoc}
353
   */
354
  public function requiresJsCommands() {
355
    return $this->getPluginDefinition()['auto_select'] && $this->getConfiguration()['settings']['auto_select'];
356
  }
357
358
  /**
359
   * Allow configuration overrides at runtime based on widget context passed to
360
   * this widget from the Entity Browser element.
361
   *
362
   * Widgets can override this method to replace the default behavior of
363
   * replacing configuration with widget context if array keys match.
364
   *
365
   * @param array $widget_context
366
   *   The widget context.
367
   */
368
  protected function handleWidgetContext($widget_context) {
369
    foreach ($this->defaultConfiguration() as $key => $value) {
370
      if (isset($widget_context[$key]) && isset($this->configuration[$key])) {
371
        $this->configuration[$key] = $widget_context[$key];
372
      }
373
    }
374
  }
375
376
  /**
377
   * {@inheritdoc}
378
   */
379
  public function access() {
380
    return AccessResult::allowed();
381
  }
382
383
}
384