Completed
Pull Request — master (#85)
by
unknown
03:00
created

Drupal7::userAlter()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 10
Ratio 55.56 %

Importance

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