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

Drupal7::expandEntityProperties()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 16
Code Lines 8

Duplication

Lines 16
Ratio 100 %

Importance

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