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

Drupal6   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 524
Duplicated Lines 20.23 %

Coupling/Cohesion

Components 4
Dependencies 3

Importance

Changes 11
Bugs 4 Features 5
Metric Value
wmc 78
c 11
b 4
f 5
lcom 4
cbo 3
dl 106
loc 524
rs 2.1126

31 Methods

Rating   Name   Duplication   Size   Complexity  
A bootstrap() 5 18 3
A clearCache() 0 7 1
A nodeDelete() 0 6 2
B nodeCreate() 3 32 5
A nodeDeleteMultiple() 0 5 2
A runCron() 0 3 1
B userCreate() 0 22 4
A userDelete() 6 6 1
A userDeleteMultiple() 8 8 2
A processBatch() 0 2 1
A userAddRole() 0 8 2
A userRoleLoadByName() 0 4 1
B checkPermissions() 0 14 5
A roleCreate() 0 17 3
A roleDelete() 0 8 2
C validateDrupalSite() 51 51 7
B expandEntityProperties() 0 16 5
A taxonomyVocabularyLoadMultiple() 0 7 2
C termCreate() 15 52 9
A termDelete() 0 8 2
A getAllPermissions() 7 7 2
A getModuleList() 0 3 1
A getExtensionPathList() 11 11 2
A expandEntityFields() 0 3 1
A getEntityFieldTypes() 0 17 4
A isField() 0 10 3
A languageCreate() 0 3 1
A languageDelete() 0 3 1
A configGet() 0 3 1
A configSet() 0 3 1
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 Drupal6 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 Drupal6, 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 6 core.
9
 */
10
class Drupal6 extends AbstractCore {
11
12
  /**
13
   * The available permissions.
14
   *
15
   * @var array
16
   */
17
  protected $availablePermissons;
18
19
  /**
20
   * {@inheritdoc}
21
   */
22
  public function bootstrap() {
23
    // Validate, and prepare environment for Drupal bootstrap.
24 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...
25
      define('DRUPAL_ROOT', $this->drupalRoot);
26
      require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
27
      $this->validateDrupalSite();
28
    }
29
30
    // Bootstrap Drupal.
31
    $current_path = getcwd();
32
    chdir(DRUPAL_ROOT);
33
    drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
34
    if (empty($GLOBALS['db_url'])) {
35
      throw new BootstrapException('Missing database setting, verify the database configuration in settings.php.');
36
    }
37
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
38
    chdir($current_path);
39
  }
40
41
  /**
42
   * {@inheritdoc}
43
   */
44
  public function clearCache() {
45
    // Need to change into the Drupal root directory or the registry explodes.
46
    $current_path = getcwd();
47
    chdir(DRUPAL_ROOT);
48
    drupal_flush_all_caches();
49
    chdir($current_path);
50
  }
51
52
  /**
53
   * {@inheritdoc}
54
   */
55
  public function nodeCreate($node) {
56
    $current_path = getcwd();
57
    chdir(DRUPAL_ROOT);
58
59
    // Set original if not set.
60
    if (!isset($node->original)) {
61
      $node->original = clone $node;
62
    }
63
64
    // Assign authorship if none exists and `author` is passed.
65 View Code Duplication
    if (!isset($node->uid) && !empty($node->author) && ($user = user_load(array('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...
66
      $node->uid = $user->uid;
67
    }
68
69
    // Convert properties to expected structure.
70
    $this->expandEntityProperties($node);
71
72
    // Attempt to decipher any fields that may be specified.
73
    $this->expandEntityFields('node', $node);
74
75
    // Set defaults that haven't already been set.
76
    $defaults = clone $node;
77
    module_load_include('inc', 'node', 'node.pages');
78
    node_object_prepare($defaults);
79
    $node = (object) array_merge((array) $defaults, (array) $node);
80
81
    node_save($node);
82
83
    chdir($current_path);
84
    return $node;
85
86
  }
87
88
  /**
89
   * {@inheritdoc}
90
   */
91
  public function nodeDelete($node) {
92
    if (is_numeric($node)) {
93
      return node_delete($node);
94
    }
95
    return node_delete($node->nid);
96
  }
97
98
  /**
99
   * {@inheritdoc}
100
   */
101
  public function nodeDeleteMultiple(array $nids) {
102
    foreach ($nids as $nid) {
103
      node_delete($nid);
104
    }
105
  }
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
123
    // Clone user object, otherwise user_save() changes the password to the
124
    // hashed password.
125
    $account = clone $user;
126
    // Convert role array to a keyed array.
127
    if (isset($user->roles)) {
128
      $roles = array();
129
      foreach ($user->roles as $rid) {
130
        $roles[$rid] = $rid;
131
      }
132
      $user->roles = $roles;
133
    }
134
    $account = user_save((array) $account, (array) $account);
135
    // Store the UID.
136
    $user->uid = $account->uid;
137
    return $user;
138
  }
139
140
  /**
141
   * {@inheritdoc}
142
   */
143 View Code Duplication
  public function userDelete(\stdClass $user) {
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...
144
    $current_path = getcwd();
145
    chdir(DRUPAL_ROOT);
146
    user_delete(array(), $user->uid);
147
    chdir($current_path);
148
  }
149
150
  /**
151
   * {@inheritdoc}
152
   */
153 View Code Duplication
  public function userDeleteMultiple(array $uids) {
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...
154
    $current_path = getcwd();
155
    chdir(DRUPAL_ROOT);
156
    foreach ($uids as $uid) {
157
      user_delete(array(), $uid);
158
    }
159
    chdir($current_path);
160
  }
161
162
  /**
163
   * {@inheritdoc}
164
   */
165
  public function processBatch() {
166
  }
167
168
  /**
169
   * {@inheritdoc}
170
   */
171
  public function userAddRole(\stdClass $user, $role_name) {
172
    $roles = array_flip(user_roles());
173
    $role = $roles[$role_name];
174
    if (!$role) {
175
      throw new \RuntimeException(sprintf('No role "%s" exists.', $role_name));
176
    }
177
    user_multiple_role_edit(array($user->uid), 'add_role', $role);
178
  }
179
180
  /**
181
   * Fetches a user role by role name.
182
   *
183
   * @param string $role_name
184
   *   A string representing the role name.
185
   *
186
   * @return object
187
   *   A fully-loaded role object if a role with the given name exists, or FALSE
188
   *   otherwise.
189
   *
190
   * @see user_role_load()
191
   */
192
  protected function userRoleLoadByName($role_name) {
193
    $result = db_query('SELECT * FROM {role} WHERE name = "%s"', $role_name);
194
    return db_fetch_object($result);
195
  }
196
197
  /**
198
   * Check to make sure that the array of permissions are valid.
199
   *
200
   * @param array $permissions
201
   *   Permissions to check.
202
   * @param bool $reset
203
   *   Reset cached available permissions.
204
   *
205
   * @return bool
206
   *   TRUE or FALSE depending on whether the permissions are valid.
207
   */
208
  protected function checkPermissions(array $permissions, $reset = FALSE) {
209
210
    if (!isset($this->availablePermissons) || $reset) {
211
      $this->availablePermissons = array_keys(module_invoke_all('permission'));
212
    }
213
214
    $valid = TRUE;
215
    foreach ($permissions as $permission) {
216
      if (!in_array($permission, $this->availablePermissons)) {
217
        $valid = FALSE;
218
      }
219
    }
220
    return $valid;
221
  }
222
223
  /**
224
   * {@inheritdoc}
225
   */
226
  public function roleCreate(array $permissions) {
227
    // Verify permissions exist.
228
    $all_permissions = module_invoke_all('perm');
229
    foreach ($permissions as $name) {
230
      $search = array_search($name, $all_permissions);
231
      if (!$search) {
232
        throw new \RuntimeException(sprintf("No permission '%s' exists.", $name));
233
      }
234
    }
235
    // Create new role.
236
    $name = $this->random->name(8);
237
    db_query("INSERT INTO {role} SET name = '%s'", $name);
238
    // Add permissions to role.
239
    $rid = db_last_insert_id('role', 'rid');
240
    db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $rid, implode(', ', $permissions));
241
    return $name;
242
  }
243
244
  /**
245
   * {@inheritdoc}
246
   */
247
  public function roleDelete($role_name) {
248
    $roles = array_flip(user_roles());
249
    $rid = $roles[$role_name];
250
    db_query('DELETE FROM {role} WHERE rid = %d', $rid);
251
    if (!db_affected_rows()) {
252
      throw new \RuntimeException(sprintf('No role "%s" exists.', $rid));
253
    }
254
  }
255
256
  /**
257
   * {@inheritdoc}
258
   */
259 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...
260
    if ('default' !== $this->uri) {
261
      // Fake the necessary HTTP headers that Drupal needs:
262
      $drupal_base_url = parse_url($this->uri);
263
      // If there's no url scheme set, add http:// and re-parse the url
264
      // so the host and path values are set accurately.
265
      if (!array_key_exists('scheme', $drupal_base_url)) {
266
        $drupal_base_url = parse_url($this->uri);
267
      }
268
      // Fill in defaults.
269
      $drupal_base_url += array(
270
        'path' => NULL,
271
        'host' => NULL,
272
        'port' => NULL,
273
      );
274
      $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
275
276
      if ($drupal_base_url['port']) {
277
        $_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port'];
278
      }
279
      $_SERVER['SERVER_PORT'] = $drupal_base_url['port'];
280
281
      if (array_key_exists('path', $drupal_base_url)) {
282
        $_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php';
283
      }
284
      else {
285
        $_SERVER['PHP_SELF'] = '/index.php';
286
      }
287
    }
288
    else {
289
      $_SERVER['HTTP_HOST'] = 'default';
290
      $_SERVER['PHP_SELF'] = '/index.php';
291
    }
292
293
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
294
    $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
295
    $_SERVER['REQUEST_METHOD']  = NULL;
296
297
    $_SERVER['SERVER_SOFTWARE'] = NULL;
298
    $_SERVER['HTTP_USER_AGENT'] = NULL;
299
300
    $conf_path = conf_path(TRUE, TRUE);
301
    $conf_file = $this->drupalRoot . "/$conf_path/settings.php";
302
    if (!file_exists($conf_file)) {
303
      throw new BootstrapException(sprintf('Could not find a Drupal settings.php file at "%s"', $conf_file));
304
    }
305
    $drushrc_file = $this->drupalRoot . "/$conf_path/drushrc.php";
306
    if (file_exists($drushrc_file)) {
307
      require_once $drushrc_file;
308
    }
309
  }
310
311
  /**
312
   * Expands properties on the given entity object to the expected structure.
313
   *
314
   * @param \stdClass $entity
315
   *   The entity object.
316
   */
317
  protected function expandEntityProperties(\stdClass $entity) {
318
    // The created field may come in as a readable date, rather than a
319
    // timestamp.
320
    if (isset($entity->created) && !is_numeric($entity->created)) {
321
      $entity->created = strtotime($entity->created);
322
    }
323
324
    // Map human-readable node types to machine node types.
325
    $types = node_get_types();
326
    foreach ($types as $type) {
327
      if ($entity->type == $type->name) {
328
        $entity->type = $type->type;
329
        continue;
330
      }
331
    }
332
  }
333
334
  /**
335
   * Load vocabularies, optional by VIDs.
336
   *
337
   * @param array $vids
338
   *   The vids to load.
339
   *
340
   * @return array
341
   *   An array of vocabulary objects
342
   */
343
  protected function taxonomyVocabularyLoadMultiple($vids = array()) {
344
    $vocabularies = taxonomy_get_vocabularies();
345
    if ($vids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $vids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
346
      return array_intersect_key($vocabularies, array_flip($vids));
347
    }
348
    return $vocabularies;
349
  }
350
351
  /**
352
   * {@inheritdoc}
353
   */
354
  public function termCreate(\stdClass $term) {
355
    // Map vocabulary names to vid, these take precedence over machine names.
356 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...
357
      $vocabularies = \taxonomy_get_vocabularies();
358
      foreach ($vocabularies as $vid => $vocabulary) {
359
        if ($vocabulary->name == $term->vocabulary_machine_name) {
360
          $term->vid = $vocabulary->vid;
361
        }
362
      }
363
    }
364
365
    if (!isset($term->vid)) {
366
367
      // Try to load vocabulary by machine name.
368
      $vocabularies = $this->taxonomyVocabularyLoadMultiple(array($term->vid));
369
      if (!empty($vocabularies)) {
370
        $vids = array_keys($vocabularies);
371
        $term->vid = reset($vids);
372
      }
373
    }
374
375
    // If `parent` is set, look up a term in this vocab with that name.
376 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...
377
      $parent = \taxonomy_get_term_by_name($term->parent);
378
      if (!empty($parent)) {
379
        $parent = reset($parent);
380
        $term->parent = $parent->tid;
381
      }
382
    }
383
384
    if (empty($term->vid)) {
385
      throw new \Exception(sprintf('No "%s" vocabulary found.'));
386
    }
387
388
    // Attempt to decipher any fields that may be specified.
389
    $this->expandEntityFields('taxonomy_term', $term);
390
391
    // Protect against a failure from hook_taxonomy_term_insert() in pathauto.
392
    $current_path = getcwd();
393
    chdir(DRUPAL_ROOT);
394
    $term_array = (array) $term;
395
    \taxonomy_save_term($term_array);
396
    chdir($current_path);
397
398
    // Loading a term by name returns an array of term objects, but there should
399
    // only be one matching term in a testing context, so take the first match
400
    // by reset()'ing $matches.
401
    $matches = \taxonomy_get_term_by_name($term->name);
402
    $saved_term = reset($matches);
403
404
    return $saved_term;
405
  }
406
407
  /**
408
   * {@inheritdoc}
409
   */
410
  public function termDelete(\stdClass $term) {
411
    $status = 0;
412
    if (isset($term->tid)) {
413
      $status = \taxonomy_del_term($term->tid);
414
    }
415
    // Will be SAVED_DELETED (3) on success.
416
    return $status;
417
  }
418
419
  /**
420
   * Helper function to get all permissions.
421
   *
422
   * @return array
423
   *   Array keyed by permission name, with the human-readable title as the
424
   *   value.
425
   */
426 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...
427
    $permissions = array();
428
    foreach (module_invoke_all('permission') as $name => $permission) {
429
      $permissions[$name] = $permission['title'];
430
    }
431
    return $permissions;
432
  }
433
434
  /**
435
   * {@inheritdoc}
436
   */
437
  public function getModuleList() {
438
    return module_list();
439
  }
440
441
  /**
442
   * {@inheritdoc}
443
   */
444 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...
445
    $paths = array();
446
447
    // Get enabled modules.
448
    $modules = $this->getModuleList();
449
    foreach ($modules as $module) {
450
      $paths[] = $this->drupalRoot . DIRECTORY_SEPARATOR . \drupal_get_path('module', $module);
451
    }
452
453
    return $paths;
454
  }
455
456
  /**
457
   * {@inheritdoc}
458
   */
459
  protected function expandEntityFields($entity_type, \stdClass $entity) {
460
    return parent::expandEntityFields($entity_type, $entity);
461
  }
462
463
  /**
464
   * {@inheritdoc}
465
   */
466
  public function getEntityFieldTypes($entity_type) {
467
    $taxonomy_fields = array('taxonomy' => 'taxonomy');
468
    if (!module_exists('content')) {
469
      return $taxonomy_fields;
470
    }
471
    $return = array();
472
    $fields = content_fields();
473
    foreach ($fields as $field_name => $field) {
474
      if ($this->isField($entity_type, $field_name)) {
475
        $return[$field_name] = $field['type'];
476
      }
477
    }
478
479
    $return += $taxonomy_fields;
480
481
    return $return;
482
  }
483
484
  /**
485
   * {@inheritdoc}
486
   */
487
  public function isField($entity_type, $field_name) {
488
    if ($field_name === 'taxonomy') {
489
      return TRUE;
490
    }
491
    if (!module_exists('content')) {
492
      return FALSE;
493
    }
494
    $map = content_fields();
495
    return isset($map[$field_name]);
496
  }
497
498
  /**
499
   * {@inheritdoc}
500
   */
501
  public function languageCreate(\stdClass $language) {
502
    throw new \Exception('Creating languages is not yet implemented for Drupal 6.');
503
  }
504
505
  /**
506
   * {@inheritdoc}
507
   */
508
  public function languageDelete(\stdClass $language) {
509
    throw new \Exception('Deleting languages is not yet implemented for Drupal 6.');
510
  }
511
512
  /**
513
   * {@inheritdoc}
514
   */
515
  public function configGet($name, $key = '') {
516
    throw new \Exception('Getting config is not yet implemented for Drupal 6.');
517
  }
518
519
  /**
520
   * {@inheritdoc}
521
   */
522
  public function configSet($name, $key, $value) {
523
    throw new \Exception('Setting config is not yet implemented for Drupal 6.');
524
  }
525
526
  /**
527
   * {@inheritdoc}
528
   */
529
  public function clearStaticCaches() {
530
    // Drupal 6 doesn't have a way of clearing all static caches.
531
  }
532
533
}
534