Completed
Pull Request — master (#157)
by
unknown
01:57
created

Drupal8::convertPermissions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
3
namespace Drupal\Driver\Cores;
4
5
use Drupal\Core\DrupalKernel;
6
use Drupal\Core\Field\BaseFieldDefinition;
7
use Drupal\Driver\Exception\BootstrapException;
8
use Drupal\field\Entity\FieldStorageConfig;
9
use Drupal\language\Entity\ConfigurableLanguage;
10
use Drupal\mailsystem\MailsystemManager;
11
use Drupal\node\NodeInterface;
12
use Drupal\Core\Entity\EntityInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
use Drupal\Driver\Wrapper\Field\DriverFieldDrupal8;
15
use Drupal\Driver\Wrapper\Entity\DriverEntityDrupal8;
16
17
/**
18
 * Drupal 8 core.
19
 */
20
class Drupal8 extends AbstractCore {
21
22
  /**
23
   * Tracks original configuration values.
24
   *
25
   * This is necessary since configurations modified here are actually saved so
26
   * that they persist values across bootstraps.
27
   *
28
   * @var array
29
   *   An array of data, keyed by configuration name.
30
   */
31
  protected $originalConfiguration = [];
32
33
  /**
34
   * {@inheritdoc}
35
   */
36
  public function bootstrap() {
37
    // Validate, and prepare environment for Drupal bootstrap.
38
    if (!defined('DRUPAL_ROOT')) {
39
      define('DRUPAL_ROOT', $this->drupalRoot);
40
    }
41
42
    // Bootstrap Drupal.
43
    chdir(DRUPAL_ROOT);
44
    $autoloader = require DRUPAL_ROOT . '/autoload.php';
45
    require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
46
    $this->validateDrupalSite();
47
48
    $request = Request::createFromGlobals();
49
    $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
50
    $kernel->boot();
51
    $kernel->prepareLegacyRequest($request);
52
53
    // Initialise an anonymous session. required for the bootstrap.
54
    \Drupal::service('session_manager')->start();
55
  }
56
57
  /**
58
   * {@inheritdoc}
59
   */
60
  public function clearCache() {
61
    // Need to change into the Drupal root directory or the registry explodes.
62
    drupal_flush_all_caches();
63
  }
64
65
  /**
66
   * {@inheritdoc}
67
   */
68
  public function nodeCreate($node) {
69
    $entity = $this->getNewEntity('node');
70
    $entity->setFields((array) $node);
71
    $entity->save();
72
    $node->nid = $entity->id();
73
    return $node;
74
  }
75
76
  /**
77
   * {@inheritdoc}
78
   */
79
  public function nodeDelete($node) {
80
    $nid = $node instanceof NodeInterface ? $node->id() : $node->nid;
0 ignored issues
show
Bug introduced by
The class Drupal\node\NodeInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
81
    $entity = $this->getNewEntity('node');
82
    $entity->load($nid);
83
    $entity->delete();
84
  }
85
86
  /**
87
   * {@inheritdoc}
88
   */
89
  public function runCron() {
90
    return \Drupal::service('cron')->run();
91
  }
92
93
  /**
94
   * {@inheritdoc}
95
   */
96
  public function userCreate(\stdClass $user) {
97
    // @todo determine if this needs to be here. It disrupts the new kernel
98
    // tests.
99
    $this->validateDrupalSite();
100
101
    $entity = $this->getNewEntity('user');
102
    $entity->setFields((array) $user);
103
    $entity->save();
104
    $user->uid = $entity->id();
105
    return $user;
106
  }
107
108
  /**
109
   * {@inheritdoc}
110
   */
111
  public function roleCreate(array $permissions) {
112
    // Generate a random machine name & label.
113
    $id = strtolower($this->random->name(8, TRUE));
114
    $label = trim($this->random->name(8, TRUE));
115
116
    $entity = $this->getNewEntity('role');
117
    $entity->set('id', $id);
118
    $entity->set('label', $label);
119
    $entity->grantPermissions($permissions);
0 ignored issues
show
Bug introduced by
The method grantPermissions() does not seem to exist on object<Drupal\Driver\Wra...EntityWrapperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
120
    $entity->save();
121
    return $entity->id();
122
  }
123
124
  /**
125
   * {@inheritdoc}
126
   */
127
  public function roleDelete($role_name) {
128
    $role = $this->getNewEntity('role');
129
    $role->load($role_name);
130
    $role->delete();
131
  }
132
133
  /**
134
   * {@inheritdoc}
135
   */
136
  public function processBatch() {
137
    $this->validateDrupalSite();
138
    $batch =& batch_get();
139
    $batch['progressive'] = FALSE;
140
    batch_process();
141
  }
142
143
  /**
144
   * {@inheritdoc}
145
   */
146
  public function userDelete(\stdClass $user) {
147
    // Not using user_cancel here leads to an error when batch_process()
148
    // is subsequently called.
149
    user_cancel(array(), $user->uid, 'user_cancel_delete');
150
    // $entity = $this->getNewEntity('user');
151
    // $entity->load($user->uid);
152
    // $entity->delete();
153
  }
154
155
  /**
156
   * {@inheritdoc}
157
   */
158
  public function userAddRole(\stdClass $user, $role_name) {
159
    $uid = $user->uid;
160
    $user = $this->getNewEntity('user');
161
    $user->load($uid);
162
    $user->addRole($role_name);
0 ignored issues
show
Bug introduced by
The method addRole() does not seem to exist on object<Drupal\Driver\Wra...EntityWrapperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
    $user->save();
164
  }
165
166
  /**
167
   * {@inheritdoc}
168
   */
169
  public function validateDrupalSite() {
170
    if ('default' !== $this->uri) {
171
      // Fake the necessary HTTP headers that Drupal needs:
172
      $drupal_base_url = parse_url($this->uri);
173
      // If there's no url scheme set, add http:// and re-parse the url
174
      // so the host and path values are set accurately.
175
      if (!array_key_exists('scheme', $drupal_base_url)) {
176
        $drupal_base_url = parse_url($this->uri);
177
      }
178
      // Fill in defaults.
179
      $drupal_base_url += array(
180
        'path' => NULL,
181
        'host' => NULL,
182
        'port' => NULL,
183
      );
184
      $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
185
186
      if ($drupal_base_url['port']) {
187
        $_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port'];
188
      }
189
      $_SERVER['SERVER_PORT'] = $drupal_base_url['port'];
190
191
      if (array_key_exists('path', $drupal_base_url)) {
192
        $_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php';
193
      }
194
      else {
195
        $_SERVER['PHP_SELF'] = '/index.php';
196
      }
197
    }
198
    else {
199
      $_SERVER['HTTP_HOST'] = 'default';
200
      $_SERVER['PHP_SELF'] = '/index.php';
201
    }
202
203
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
204
    $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
205
    $_SERVER['REQUEST_METHOD'] = NULL;
206
207
    $_SERVER['SERVER_SOFTWARE'] = NULL;
208
    $_SERVER['HTTP_USER_AGENT'] = NULL;
209
210
    $conf_path = DrupalKernel::findSitePath(Request::createFromGlobals());
211
    $conf_file = $this->drupalRoot . "/$conf_path/settings.php";
212
    if (!file_exists($conf_file)) {
213
      throw new BootstrapException(sprintf('Could not find a Drupal settings.php file at "%s"', $conf_file));
214
    }
215
    $drushrc_file = $this->drupalRoot . "/$conf_path/drushrc.php";
216
    if (file_exists($drushrc_file)) {
217
      require_once $drushrc_file;
218
    }
219
  }
220
221
  /**
222
   * {@inheritdoc}
223
   */
224
  public function termCreate(\stdClass $term) {
225
    $entity = $this->getNewEntity('taxonomy_term');
226
    $entity->setFields((array) $term);
227
    $entity->save();
228
    $term->tid = $entity->id();
229
    return $term;
230
  }
231
232
  /**
233
   * {@inheritdoc}
234
   */
235
  public function termDelete(\stdClass $term) {
236
    $entity = $this->getNewEntity('taxonomy_term');
237
    $entity->load($term->tid);
238
    $entity->delete();
239
  }
240
241
  /**
242
   * {@inheritdoc}
243
   */
244
  public function getModuleList() {
245
    return array_keys(\Drupal::moduleHandler()->getModuleList());
246
  }
247
248
  /**
249
   * {@inheritdoc}
250
   */
251
  public function getExtensionPathList() {
252
    $paths = array();
253
254
    // Get enabled modules.
255
    foreach (\Drupal::moduleHandler()->getModuleList() as $module) {
256
      $paths[] = $this->drupalRoot . DIRECTORY_SEPARATOR . $module->getPath();
257
    }
258
259
    return $paths;
260
  }
261
262
  /**
263
   * {@inheritdoc}
264
   */
265
  protected function expandEntityFields($entity_type, \stdClass $entity, array $base_fields = array()) {
266
    $field_types = $this->getEntityFieldTypes($entity_type, $base_fields);
267
    $bundle_key = \Drupal::entityManager()->getDefinition($entity_type)->getKey('bundle');
268
    if (isset($entity->$bundle_key) && ($entity->$bundle_key !== NULL)) {
269
      $bundle = $entity->$bundle_key;
270
    }
271
    else {
272
      $bundle = $entity_type;
273
    }
274
275
    foreach ($field_types as $field_name => $type) {
276
      if (isset($entity->$field_name)) {
277
        // @todo find a bettter way of standardising single/multi value fields
278
        if (is_array($entity->$field_name)) {
279
          $fieldValues = $entity->$field_name;
280
        }
281
        else {
282
          $fieldValues = [$entity->$field_name];
283
        }
284
        $field = new DriverFieldDrupal8(
285
          $fieldValues,
286
          $field_name,
287
          $entity_type,
288
          $bundle
289
        );
290
        $entity->$field_name = $field->getProcessedValues();
291
      }
292
    }
293
  }
294
295
  /**
296
   * Expands specified base fields on the entity object.
297
   *
298
   * @param string $entity_type
299
   *   The entity type for which to return the field types.
300
   * @param \stdClass $entity
301
   *   Entity object.
302
   * @param array $base_fields
303
   *   Base fields to be expanded in addition to user defined fields.
304
   */
305
  public function expandEntityBaseFields($entity_type, \stdClass $entity, array $base_fields) {
306
    $this->expandEntityFields($entity_type, $entity, $base_fields);
307
  }
308
309
  /**
310
   * {@inheritdoc}
311
   */
312
  public function getEntityFieldTypes($entity_type, array $base_fields = array()) {
313
    $return = array();
314
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
315
    foreach ($fields as $field_name => $field) {
316
      if ($this->isField($entity_type, $field_name)
317
        || (in_array($field_name, $base_fields) && $this->isBaseField($entity_type, $field_name))) {
318
        $return[$field_name] = $field->getType();
319
      }
320
    }
321
    return $return;
322
  }
323
324
  /**
325
   * Get a new driver entity wrapper.
326
   *
327
   * @return \Drupal\Driver\Wrapper\Entity\DriverEntityWrapperInterface
328
   *   A new driver entity wrapper.
329
   */
330
  public function getNewEntity($type, $bundle = NULL) {
331
    $entity = new DriverEntityDrupal8($type, $bundle);
332
    return $entity;
333
  }
334
335
  /**
336
   * {@inheritdoc}
337
   */
338
  public function isField($entity_type, $field_name) {
339
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
340
    return (isset($fields[$field_name]) && $fields[$field_name] instanceof FieldStorageConfig);
0 ignored issues
show
Bug introduced by
The class Drupal\field\Entity\FieldStorageConfig does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
341
  }
342
343
  /**
344
   * {@inheritdoc}
345
   */
346
  public function isBaseField($entity_type, $field_name) {
347
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
348
    return (isset($fields[$field_name]) && $fields[$field_name] instanceof BaseFieldDefinition);
0 ignored issues
show
Bug introduced by
The class Drupal\Core\Field\BaseFieldDefinition does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
349
  }
350
351
  /**
352
   * {@inheritdoc}
353
   */
354
  public function languageCreate(\stdClass $language) {
355
    $langcode = $language->langcode;
356
357
    // Enable a language only if it has not been enabled already.
358
    if (!ConfigurableLanguage::load($langcode)) {
359
      $entity = $this->getNewEntity('configurable_language');
360
      $entity->set('id', $langcode);
361
      $entity->set('label', $langcode);
362
      $entity->save();
363
      return $language;
364
    }
365
366
    return FALSE;
367
  }
368
369
  /**
370
   * {@inheritdoc}
371
   */
372
  public function languageDelete(\stdClass $language) {
373
    $configurable_language = ConfigurableLanguage::load($language->langcode);
374
    $configurable_language->delete();
375
  }
376
377
  /**
378
   * {@inheritdoc}
379
   */
380
  public function clearStaticCaches() {
381
    drupal_static_reset();
382
    \Drupal::service('cache_tags.invalidator')->resetChecksums();
383
  }
384
385
  /**
386
   * {@inheritdoc}
387
   */
388
  public function configGet($name, $key = '') {
389
    return \Drupal::config($name)->get($key);
390
  }
391
392
  /**
393
   * {@inheritdoc}
394
   */
395
  public function configSet($name, $key, $value) {
396
    \Drupal::configFactory()->getEditable($name)
397
      ->set($key, $value)
398
      ->save();
399
  }
400
401
  /**
402
   * {@inheritdoc}
403
   */
404
  public function entityCreate($entity_type, $entity) {
405
    $entityWrapped = $this->getNewEntity($entity_type);
406
    $entityWrapped->setFields((array) $entity);
407
    $entityWrapped->save();
408
    $entity->id = $entityWrapped->id();
409
    return $entity;
410
  }
411
412
  /**
413
   * {@inheritdoc}
414
   */
415
  public function entityDelete($entity_type, $entity) {
416
    $eid = $entity instanceof EntityInterface ? $entity->id() : $entity->id;
0 ignored issues
show
Bug introduced by
The class Drupal\Core\Entity\EntityInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
417
    $entity = $this->getNewEntity($entity_type);
418
    $entity->load($eid);
419
    $entity->delete();
420
  }
421
422
  /**
423
   * {@inheritdoc}
424
   */
425
  public function startCollectingMail() {
426
    $config = \Drupal::configFactory()->getEditable('system.mail');
427
    $data = $config->getRawData();
428
429
    // Save the original values for restoration after.
430
    $this->originalConfiguration['system.mail'] = $data;
431
432
    // @todo Use a collector that supports html after D#2223967 lands.
433
    $data['interface'] = ['default' => 'test_mail_collector'];
434
    $config->setData($data)->save();
435
    // Disable the mail system module's mail if enabled.
436
    $this->startCollectingMailSystemMail();
437
  }
438
439
  /**
440
   * {@inheritdoc}
441
   */
442
  public function stopCollectingMail() {
443
    $config = \Drupal::configFactory()->getEditable('system.mail');
444
    $config->setData($this->originalConfiguration['system.mail'])->save();
445
    // Re-enable the mailsystem module's mail if enabled.
446
    $this->stopCollectingMailSystemMail();
447
  }
448
449
  /**
450
   * {@inheritdoc}
451
   */
452
  public function getMail() {
453
    \Drupal::state()->resetCache();
454
    $mail = \Drupal::state()->get('system.test_mail_collector') ?: [];
455
    // Discard cancelled mail.
456
    $mail = array_values(array_filter($mail, function ($mailItem) {
457
      return ($mailItem['send'] == TRUE);
458
    }));
459
    return $mail;
460
  }
461
462
  /**
463
   * {@inheritdoc}
464
   */
465
  public function clearMail() {
466
    \Drupal::state()->set('system.test_mail_collector', []);
467
  }
468
469
  /**
470
   * {@inheritdoc}
471
   */
472
  public function sendMail($body = '', $subject = '', $to = '', $langcode = '') {
473
    // Send the mail, via the system module's hook_mail.
474
    $params['context']['message'] = $body;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
475
    $params['context']['subject'] = $subject;
476
    $mailManager = \Drupal::service('plugin.manager.mail');
477
    $result = $mailManager->mail('system', '', $to, $langcode, $params, NULL, TRUE);
478
    return $result;
479
  }
480
481
  /**
482
   * If the Mail System module is enabled, collect that mail too.
483
   *
484
   * @see MailsystemManager::getPluginInstance()
485
   */
486
  protected function startCollectingMailSystemMail() {
487
    if (\Drupal::moduleHandler()->moduleExists('mailsystem')) {
488
      $config = \Drupal::configFactory()->getEditable('mailsystem.settings');
489
      $data = $config->getRawData();
490
491
      // Track original data for restoration.
492
      $this->originalConfiguration['mailsystem.settings'] = $data;
493
494
      // Convert all of the 'senders' to the test collector.
495
      $data = $this->findMailSystemSenders($data);
496
      $config->setData($data)->save();
497
    }
498
  }
499
500
  /**
501
   * Find and replace all the mail system sender plugins with the test plugin.
502
   *
503
   * This method calls itself recursively.
504
   */
505
  protected function findMailSystemSenders(array $data) {
506
    foreach ($data as $key => $values) {
507
      if (is_array($values)) {
508
        if (isset($values[MailsystemManager::MAILSYSTEM_TYPE_SENDING])) {
509
          $data[$key][MailsystemManager::MAILSYSTEM_TYPE_SENDING] = 'test_mail_collector';
510
        }
511
        else {
512
          $data[$key] = $this->findMailSystemSenders($values);
513
        }
514
      }
515
    }
516
    return $data;
517
  }
518
519
  /**
520
   * If the Mail System module is enabled, stop collecting those mails.
521
   */
522
  protected function stopCollectingMailSystemMail() {
523
    if (\Drupal::moduleHandler()->moduleExists('mailsystem')) {
524
      \Drupal::configFactory()->getEditable('mailsystem.settings')->setData($this->originalConfiguration['mailsystem.settings'])->save();
525
    }
526
  }
527
528
}
529