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

Drupal7   D

Complexity

Total Complexity 83

Size/Duplication

Total Lines 532
Duplicated Lines 21.8 %

Coupling/Cohesion

Components 3
Dependencies 3

Importance

Changes 16
Bugs 5 Features 6
Metric Value
wmc 83
c 16
b 5
f 6
lcom 3
cbo 3
dl 116
loc 532
rs 4.8717

28 Methods

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