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

Drupal7::nodeAlter()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 4
Ratio 20 %

Importance

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