Completed
Pull Request — master (#85)
by
unknown
02:49
created

Drupal7   D

Complexity

Total Complexity 90

Size/Duplication

Total Lines 566
Duplicated Lines 17.67 %

Coupling/Cohesion

Components 3
Dependencies 3

Importance

Changes 20
Bugs 5 Features 10
Metric Value
wmc 90
c 20
b 5
f 10
lcom 3
cbo 3
dl 100
loc 566
rs 4.8717

33 Methods

Rating   Name   Duplication   Size   Complexity  
A bootstrap() 5 16 3
A clearCache() 0 3 1
A nodeLoad() 0 3 1
B nodeCreate() 3 25 5
A nodeDelete() 0 3 1
A nodeDeleteMultiple() 0 3 1
B nodeAlter() 4 20 5
A runCron() 0 3 1
A userLoad() 0 3 1
A userCreate() 0 20 4
A userAlter() 4 12 4
A userDelete() 0 3 1
A userDeleteMultiple() 0 3 1
A processBatch() 0 5 1
A userAddRole() 0 12 2
B checkPermissions() 0 15 5
B roleCreate() 0 27 6
A roleDelete() 0 4 1
C validateDrupalSite() 51 51 7
B expandEntityProperties() 0 19 6
A termLoad() 0 6 2
D termCreate() 15 43 9
A termDelete() 0 8 2
A languageCreate() 0 21 3
B languageDelete() 0 34 4
A configGet() 0 3 1
A configSet() 0 3 1
A getAllPermissions() 7 7 2
A getModuleList() 0 3 1
A getExtensionPathList() 11 11 2
A getEntityFieldTypes() 0 10 3
A isField() 0 4 2
A clearStaticCaches() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Drupal7 often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Drupal7, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Drupal\Driver\Cores;
4
5
use Drupal\Driver\Exception\BootstrapException;
6
7
/**
8
 * Drupal 7 core.
9
 */
10
class Drupal7 extends AbstractCore {
11
12
  /**
13
   * {@inheritdoc}
14
   */
15
  public function bootstrap() {
16
    // Validate, and prepare environment for Drupal bootstrap.
17 View Code Duplication
    if (!defined('DRUPAL_ROOT')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
18
      define('DRUPAL_ROOT', $this->drupalRoot);
19
      require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
20
      $this->validateDrupalSite();
21
    }
22
23
    // Bootstrap Drupal.
24
    chdir(DRUPAL_ROOT);
25
    drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
26
    if (empty($GLOBALS['databases'])) {
27
      throw new BootstrapException('Missing database setting, verify the database configuration in settings.php.');
28
    }
29
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
30
  }
31
32
  /**
33
   * {@inheritdoc}
34
   */
35
  public function clearCache() {
36
    drupal_flush_all_caches();
37
  }
38
39
  /**
40
   * {@inheritdoc}
41
   */
42
  public function nodeLoad($nid) {
43
    return node_load($nid);
44
  }
45
46
  /**
47
   * {@inheritdoc}
48
   */
49
  public function nodeCreate($node) {
50
    // Set original if not set.
51
    if (!isset($node->original)) {
52
      $node->original = clone $node;
53
    }
54
55
    // Assign authorship if none exists and `author` is passed.
56 View Code Duplication
    if (!isset($node->uid) && !empty($node->author) && ($user = user_load_by_name($node->author))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
57
      $node->uid = $user->uid;
58
    }
59
60
    // Convert properties to expected structure.
61
    $this->expandEntityProperties($node);
62
63
    // Attempt to decipher any fields that may be specified.
64
    $this->expandEntityFields('node', $node);
65
66
    // Set defaults that haven't already been set.
67
    $defaults = clone $node;
68
    node_object_prepare($defaults);
69
    $node = (object) array_merge((array) $defaults, (array) $node);
70
71
    node_save($node);
72
    return $node;
73
  }
74
75
  /**
76
   * {@inheritdoc}
77
   */
78
  public function nodeDelete($node) {
79
    return node_delete($node->nid);
80
  }
81
82
  /**
83
   * {@inheritdoc}
84
   */
85
  public function nodeDeleteMultiple(array $nids) {
86
    return node_delete_multiple($nids);
87
  }
88
89
  /**
90
   * {@inheritdoc}
91
   *
92
   * @param object $node
93
   *   A drupal node object.
94
   * @param object $values
95
   *   An object with field/value parameters.
96
   */
97
  public function nodeAlter($node, $values) {
98 View Code Duplication
    if (empty($node) || !isset($node->nid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
99
      var_dump(array_keys(get_object_vars($node)));
0 ignored issues
show
Security Debugging Code introduced by
var_dump(array_keys(get_object_vars($node))); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
100
      throw new \Exception(sprintf("%s::%s: Node was empty or had no id", get_class($this), __FUNCTION__));
101
    }
102
    // Assign type (really, bundle) to values so that expansion functions will
103
    // work properly.
104
    $values->type = $node->type;
105
    $this->expandEntityProperties($values);
106
107
    // Attempt to decipher any fields that may be specified.
108
    $this->expandEntityFields('node', $values);
109
    foreach ($values as $k => $v) {
110
      if (!property_exists($node, $k)) {
111
        throw new \Exception(sprintf("%s::%s line %s: Attempt to modify an invalid field: %s", get_class($this), __LINE__, __FUNCTION__, $k));
112
      }
113
      $node->{$k} = $v;
114
    }
115
    node_save($node);
116
  }
117
118
  /**
119
   * Implements CoreInterface::runCron().
120
   */
121
  public function runCron() {
122
    return drupal_cron_run();
123
  }
124
125
  /**
126
   * {@inheritdoc}
127
   */
128
  public function userLoad($uid) {
129
    return user_load($uid);
130
  }
131
132
  /**
133
   * {@inheritdoc}
134
   */
135
  public function userCreate(\stdClass $user) {
136
    // Default status to TRUE if not explicitly creating a blocked user.
137
    if (!isset($user->status)) {
138
      $user->status = 1;
139
    }
140
    if (isset($user->roles) && is_string($user->roles)) {
141
      $user->roles = array_map('trim', explode(',', $user->roles));
142
    }
143
    // Clone user object, otherwise user_save() changes the password to the
144
    // hashed password.
145
    $account = clone $user;
146
147
    // Attempt to decipher any fields that may be specified.
148
    $this->expandEntityFields('user', $account);
149
150
    user_save($account, (array) $account);
151
152
    // Store UID.
153
    $user->uid = $account->uid;
154
  }
155
156
  /**
157
   * {@inheritdoc}
158
   *
159
   * @param object $user
160
   *   A drupal user object.
161
   * @param object $values
162
   *   An object with field/value parameters.
163
   */
164
  public function userAlter($user, $values) {
165 View Code Duplication
    if (empty($user) || !isset($user->uid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
166
      var_dump(array_keys(get_object_vars($user)));
0 ignored issues
show
Security Debugging Code introduced by
var_dump(array_keys(get_object_vars($user))); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
167
      throw new \Exception(sprintf("%s::%s: User was empty or had no id", get_class($this), __FUNCTION__));
168
    }
169
    // Attempt to decipher any fields that may be specified.
170
    $this->expandEntityFields('user', $values);
171
    foreach ($values as $k => $v) {
172
      $user->{$k} = $v;
173
    }
174
    user_save($user);
175
  }
176
177
  /**
178
   * {@inheritdoc}
179
   */
180
  public function userDelete(\stdClass $user) {
181
    user_cancel(array(), $user->uid, 'user_cancel_delete');
182
  }
183
184
  /**
185
   * {@inheritdoc}
186
   */
187
  public function userDeleteMultiple(array $uids) {
188
    return user_delete_multiple($uids);
189
  }
190
191
  /**
192
   * {@inheritdoc}
193
   */
194
  public function processBatch() {
195
    $batch =& batch_get();
196
    $batch['progressive'] = FALSE;
197
    batch_process();
198
  }
199
200
  /**
201
   * {@inheritdoc}
202
   */
203
  public function userAddRole(\stdClass $user, $role_name) {
204
    $role = user_role_load_by_name($role_name);
205
206
    if (!$role) {
207
      throw new \RuntimeException(sprintf('No role "%s" exists.', $role_name));
208
    }
209
210
    user_multiple_role_edit(array($user->uid), 'add_role', $role->rid);
211
    $account = user_load($user->uid);
212
    $user->roles = $account->roles;
213
214
  }
215
216
  /**
217
   * Check to make sure that the array of permissions are valid.
218
   *
219
   * @param array $permissions
220
   *   Permissions to check.
221
   * @param bool $reset
222
   *   Reset cached available permissions.
223
   *
224
   * @return bool
225
   *   TRUE or FALSE depending on whether the permissions are valid.
226
   */
227
  protected function checkPermissions(array $permissions, $reset = FALSE) {
228
    $available = &drupal_static(__FUNCTION__);
229
230
    if (!isset($available) || $reset) {
231
      $available = array_keys(module_invoke_all('permission'));
232
    }
233
234
    $valid = TRUE;
235
    foreach ($permissions as $permission) {
236
      if (!in_array($permission, $available)) {
237
        $valid = FALSE;
238
      }
239
    }
240
    return $valid;
241
  }
242
243
  /**
244
   * {@inheritdoc}
245
   */
246
  public function roleCreate(array $permissions) {
247
248
    // Both machine name and permission title are allowed.
249
    $all_permissions = $this->getAllPermissions();
250
251
    foreach ($permissions as $key => $name) {
252
      if (!isset($all_permissions[$name])) {
253
        $search = array_search($name, $all_permissions);
254
        if (!$search) {
255
          throw new \RuntimeException(sprintf("No permission '%s' exists.", $name));
256
        }
257
        $permissions[$key] = $search;
258
      }
259
    }
260
261
    // Create new role.
262
    $role = new \stdClass();
263
    $role->name = $this->random->name(8);
264
    user_role_save($role);
265
    user_role_grant_permissions($role->rid, $permissions);
266
267
    if ($role && !empty($role->rid)) {
268
      return $role->name;
269
    }
270
271
    throw new \RuntimeException(sprintf('Failed to create a role with "" permission(s).', implode(', ', $permissions)));
272
  }
273
274
  /**
275
   * {@inheritdoc}
276
   */
277
  public function roleDelete($role_name) {
278
    $role = user_role_load_by_name($role_name);
279
    user_role_delete((int) $role->rid);
280
  }
281
282
  /**
283
   * {@inheritdoc}
284
   */
285 View Code Duplication
  public function validateDrupalSite() {
0 ignored issues
show
Duplication introduced by
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...
286
    if ('default' !== $this->uri) {
287
      // Fake the necessary HTTP headers that Drupal needs:
288
      $drupal_base_url = parse_url($this->uri);
289
      // If there's no url scheme set, add http:// and re-parse the url
290
      // so the host and path values are set accurately.
291
      if (!array_key_exists('scheme', $drupal_base_url)) {
292
        $drupal_base_url = parse_url($this->uri);
293
      }
294
      // Fill in defaults.
295
      $drupal_base_url += array(
296
        'path' => NULL,
297
        'host' => NULL,
298
        'port' => NULL,
299
      );
300
      $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
301
302
      if ($drupal_base_url['port']) {
303
        $_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port'];
304
      }
305
      $_SERVER['SERVER_PORT'] = $drupal_base_url['port'];
306
307
      if (array_key_exists('path', $drupal_base_url)) {
308
        $_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php';
309
      }
310
      else {
311
        $_SERVER['PHP_SELF'] = '/index.php';
312
      }
313
    }
314
    else {
315
      $_SERVER['HTTP_HOST'] = 'default';
316
      $_SERVER['PHP_SELF'] = '/index.php';
317
    }
318
319
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
320
    $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
321
    $_SERVER['REQUEST_METHOD']  = NULL;
322
323
    $_SERVER['SERVER_SOFTWARE'] = NULL;
324
    $_SERVER['HTTP_USER_AGENT'] = NULL;
325
326
    $conf_path = conf_path(TRUE, TRUE);
327
    $conf_file = $this->drupalRoot . "/$conf_path/settings.php";
328
    if (!file_exists($conf_file)) {
329
      throw new BootstrapException(sprintf('Could not find a Drupal settings.php file at "%s"', $conf_file));
330
    }
331
    $drushrc_file = $this->drupalRoot . "/$conf_path/drushrc.php";
332
    if (file_exists($drushrc_file)) {
333
      require_once $drushrc_file;
334
    }
335
  }
336
337
  /**
338
   * Expands properties on the given entity object to the expected structure.
339
   *
340
   * @param \stdClass $entity
341
   *   The entity object.
342
   */
343
  protected function expandEntityProperties(\stdClass $entity) {
344
    if (!isset($entity->type)) {
345
      throw new \Exception(sprintf("%s::%s line %s: Entity argument is missing a value for the key 'type'", get_class($this), __FUNCTION__, __LINE__));
346
    }
347
    // The created field may come in as a readable date, rather than a
348
    // timestamp.
349
    if (isset($entity->created) && !is_numeric($entity->created)) {
350
      $entity->created = strtotime($entity->created);
351
    }
352
353
    // Map human-readable node types to machine node types.
354
    $types = \node_type_get_types();
355
    foreach ($types as $type) {
356
      if ($entity->type == $type->name) {
357
        $entity->type = $type->type;
358
        continue;
359
      }
360
    }
361
  }
362
363
  /**
364
   * {@inheritdoc}
365
   */
366
  public function termLoad($tid, $vocabulary = NULL) {
367
    if (is_numeric($tid)) {
368
      return taxonomy_term_load($tid);
369
    }
370
    return taxonomy_get_term_by_name($tid, $vocabulary);
371
  }
372
373
  /**
374
   * {@inheritdoc}
375
   */
376
  public function termCreate(\stdClass $term) {
377
    // Map vocabulary names to vid, these take precedence over machine names.
378 View Code Duplication
    if (!isset($term->vid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
379
      $vocabularies = \taxonomy_get_vocabularies();
380
      foreach ($vocabularies as $vid => $vocabulary) {
381
        if ($vocabulary->name == $term->vocabulary_machine_name) {
382
          $term->vid = $vocabulary->vid;
383
        }
384
      }
385
    }
386
387
    if (!isset($term->vid)) {
388
389
      // Try to load vocabulary by machine name.
390
      $vocabularies = \taxonomy_vocabulary_load_multiple(FALSE, array(
391
        'machine_name' => $term->vocabulary_machine_name,
392
      ));
393
      if (!empty($vocabularies)) {
394
        $vids = array_keys($vocabularies);
395
        $term->vid = reset($vids);
396
      }
397
    }
398
399
    // If `parent` is set, look up a term in this vocab with that name.
400 View Code Duplication
    if (isset($term->parent)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
401
      $parent = \taxonomy_get_term_by_name($term->parent, $term->vocabulary_machine_name);
402
      if (!empty($parent)) {
403
        $parent = reset($parent);
404
        $term->parent = $parent->tid;
405
      }
406
    }
407
408
    if (empty($term->vid)) {
409
      throw new \Exception(sprintf('%s::%s line %s: Could not load term.', get_class($this), __FUNCTION__, __LINE__));
410
    }
411
412
    // Attempt to decipher any fields that may be specified.
413
    $this->expandEntityFields('taxonomy_term', $term);
414
415
    \taxonomy_term_save($term);
416
417
    return $term;
418
  }
419
420
  /**
421
   * {@inheritdoc}
422
   */
423
  public function termDelete(\stdClass $term) {
424
    $status = 0;
425
    if (isset($term->tid)) {
426
      $status = \taxonomy_term_delete($term->tid);
427
    }
428
    // Will be SAVED_DELETED (3) on success.
429
    return $status;
430
  }
431
432
  /**
433
   * {@inheritdoc}
434
   */
435
  public function languageCreate(\stdClass $language) {
436
    include_once DRUPAL_ROOT . '/includes/iso.inc';
437
    include_once DRUPAL_ROOT . '/includes/locale.inc';
438
439
    // Get all predefined languages, regardless if they are enabled or not.
440
    $predefined_languages = _locale_get_predefined_list();
441
442
    // If the language code is not valid then throw an InvalidArgumentException.
443
    if (!isset($predefined_languages[$language->langcode])) {
444
      throw new InvalidArgumentException("There is no predefined language with langcode '{$language->langcode}'.");
445
    }
446
447
    // Enable a language only if it has not been enabled already.
448
    $enabled_languages = locale_language_list();
449
    if (!isset($enabled_languages[$language->langcode])) {
450
      locale_add_language($language->langcode);
451
      return $language;
452
    }
453
454
    return FALSE;
455
  }
456
457
  /**
458
   * {@inheritdoc}
459
   */
460
  public function languageDelete(\stdClass $language) {
461
    $langcode = $language->langcode;
462
    // Do not remove English or the default language.
463
    if (!in_array($langcode, array(language_default('language'), 'en'))) {
464
      // @see locale_languages_delete_form_submit().
465
      $languages = language_list();
466
      if (isset($languages[$langcode])) {
467
        // Remove translations first.
468
        db_delete('locales_target')
469
          ->condition('language', $langcode)
470
          ->execute();
471
        cache_clear_all('locale:' . $langcode, 'cache');
472
        // With no translations, this removes existing JavaScript translations
473
        // file.
474
        _locale_rebuild_js($langcode);
475
        // Remove the language.
476
        db_delete('languages')
477
          ->condition('language', $langcode)
478
          ->execute();
479
        db_update('node')
480
          ->fields(array('language' => ''))
481
          ->condition('language', $langcode)
482
          ->execute();
483
        if ($languages[$langcode]->enabled) {
484
          variable_set('language_count', variable_get('language_count', 1) - 1);
485
        }
486
        module_invoke_all('multilingual_settings_changed');
487
        drupal_static_reset('language_list');
488
      }
489
490
      // Changing the language settings impacts the interface:
491
      cache_clear_all('*', 'cache_page', TRUE);
492
    }
493
  }
494
495
  /**
496
   * {@inheritdoc}
497
   */
498
  public function configGet($name, $key = '') {
499
    throw new \Exception('Getting config is not yet implemented for Drupal 7.');
500
  }
501
502
  /**
503
   * {@inheritdoc}
504
   */
505
  public function configSet($name, $key, $value) {
506
    throw new \Exception('Setting config is not yet implemented for Drupal 7.');
507
  }
508
509
  /**
510
   * Helper function to get all permissions.
511
   *
512
   * @return array
513
   *   Array keyed by permission name, with the human-readable title as the
514
   *   value.
515
   */
516 View Code Duplication
  protected function getAllPermissions() {
0 ignored issues
show
Duplication introduced by
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...
517
    $permissions = array();
518
    foreach (module_invoke_all('permission') as $name => $permission) {
519
      $permissions[$name] = $permission['title'];
520
    }
521
    return $permissions;
522
  }
523
524
  /**
525
   * {@inheritdoc}
526
   */
527
  public function getModuleList() {
528
    return module_list();
529
  }
530
531
  /**
532
   * {@inheritdoc}
533
   */
534 View Code Duplication
  public function getExtensionPathList() {
0 ignored issues
show
Duplication introduced by
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...
535
    $paths = array();
536
537
    // Get enabled modules.
538
    $modules = $this->getModuleList();
539
    foreach ($modules as $module) {
540
      $paths[] = $this->drupalRoot . DIRECTORY_SEPARATOR . \drupal_get_path('module', $module);
541
    }
542
543
    return $paths;
544
  }
545
546
  /**
547
   * {@inheritdoc}
548
   */
549
  public function getEntityFieldTypes($entity_type) {
550
    $return = array();
551
    $fields = field_info_field_map();
552
    foreach ($fields as $field_name => $field) {
553
      if (array_key_exists($entity_type, $field['bundles'])) {
554
        $return[$field_name] = $field['type'];
555
      }
556
    }
557
    return $return;
558
  }
559
560
  /**
561
   * {@inheritdoc}
562
   */
563
  public function isField($entity_type, $field_name) {
564
    $map = field_info_field_map();
565
    return !empty($map[$field_name]) && array_key_exists($entity_type, $map[$field_name]['bundles']);
566
  }
567
568
  /**
569
   * {@inheritdoc}
570
   */
571
  public function clearStaticCaches() {
572
    drupal_static_reset();
573
  }
574
575
}
576