Completed
Pull Request — master (#69)
by Pieter
02:08
created

Drupal7::installModules()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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