Completed
Pull Request — master (#171)
by Jonathan
02:55 queued 01:32
created

DrupalDriver::getCore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Drupal\Driver;
4
5
use Drupal\Driver\Exception\BootstrapException;
6
7
use Behat\Behat\Tester\Exception\PendingException;
8
9
/**
10
 * Fully bootstraps Drupal and uses native API calls.
11
 */
12
class DrupalDriver implements DriverInterface, SubDriverFinderInterface {
13
14
  /**
15
   * Track whether Drupal has been bootstrapped.
16
   *
17
   * @var bool
18
   */
19
  private $bootstrapped = FALSE;
20
21
  /**
22
   * Drupal core object.
23
   *
24
   * @var \Drupal\Driver\Cores\CoreInterface
25
   */
26
  public $core;
27
28
  /**
29
   * System path to the Drupal installation.
30
   *
31
   * @var string
32
   */
33
  private $drupalRoot;
34
35
  /**
36
   * URI for the Drupal installation.
37
   *
38
   * @var string
39
   */
40
  private $uri;
41
42
  /**
43
   * Drupal core version.
44
   *
45
   * @var int
46
   */
47
  public $version;
48
49
  /**
50
   * Set Drupal root and URI.
51
   *
52
   * @param string $drupal_root
53
   *   The Drupal root path.
54
   * @param string $uri
55
   *   The URI for the Drupal installation.
56
   *
57
   * @throws BootstrapException
58
   *   Thrown when the Drupal installation is not found in the given root path.
59
   */
60
  public function __construct($drupal_root, $uri) {
61
    $this->drupalRoot = realpath($drupal_root);
62
    if (!$this->drupalRoot) {
63
      throw new BootstrapException(sprintf('No Drupal installation found at %s', $drupal_root));
64
    }
65
    $this->uri = $uri;
66
    $this->version = $this->getDrupalVersion();
67
  }
68
69
  /**
70
   * {@inheritdoc}
71
   */
72
  public function getRandom() {
73
    return $this->getCore()->getRandom();
74
  }
75
76
  /**
77
   * {@inheritdoc}
78
   */
79
  public function bootstrap() {
80
    $this->getCore()->bootstrap();
81
    $this->bootstrapped = TRUE;
82
  }
83
84
  /**
85
   * {@inheritdoc}
86
   */
87
  public function isBootstrapped() {
88
    // Assume the blackbox is always bootstrapped.
89
    return $this->bootstrapped;
90
  }
91
92
  /**
93
   * {@inheritdoc}
94
   */
95
  public function userCreate(\stdClass $user) {
96
    $this->getCore()->userCreate($user);
97
  }
98
99
  /**
100
   * {@inheritdoc}
101
   */
102
  public function userDelete(\stdClass $user) {
103
    $this->getCore()->userDelete($user);
104
  }
105
106
  /**
107
   * {@inheritdoc}
108
   */
109
  public function processBatch() {
110
    $this->getCore()->processBatch();
111
  }
112
113
  /**
114
   * {@inheritdoc}
115
   */
116
  public function userAddRole(\stdClass $user, $role_name) {
117
    $this->getCore()->userAddRole($user, $role_name);
118
  }
119
120
  /**
121
   * {@inheritdoc}
122
   */
123
  public function fetchWatchdog($count = 10, $type = NULL, $severity = NULL) {
124
    throw new PendingException(sprintf('Currently no ability to access watchdog entries in %s', $this));
125
  }
126
127
  /**
128
   * {@inheritdoc}
129
   */
130
  public function clearCache($type = NULL) {
131
    $this->getCore()->clearCache();
132
  }
133
134
  /**
135
   * {@inheritdoc}
136
   */
137
  public function getSubDriverPaths() {
138
    // Ensure system is bootstrapped.
139
    if (!$this->isBootstrapped()) {
140
      $this->bootstrap();
141
    }
142
143
    return $this->getCore()->getExtensionPathList();
144
  }
145
146
  /**
147
   * Determine major Drupal version.
148
   *
149
   * @return int
150
   *   The major Drupal version.
151
   *
152
   * @throws \Drupal\Driver\Exception\BootstrapException
153
   *   Thrown when the Drupal version could not be determined.
154
   *
155
   * @see drush_drupal_version()
156
   */
157
  public function getDrupalVersion() {
158
    if (!isset($this->version)) {
159
      // Support 6, 7 and 8.
160
      $version_constant_paths = array(
161
        // Drupal 6.
162
        '/modules/system/system.module',
163
        // Drupal 7.
164
        '/includes/bootstrap.inc',
165
        // Drupal 8.
166
        '/autoload.php',
167
        '/core/includes/bootstrap.inc',
168
      );
169
170
      if ($this->drupalRoot === FALSE) {
171
        throw new BootstrapException('`drupal_root` parameter must be defined.');
172
      }
173
174
      foreach ($version_constant_paths as $path) {
175
        if (file_exists($this->drupalRoot . $path)) {
176
          require_once $this->drupalRoot . $path;
177
        }
178
      }
179
      if (defined('VERSION')) {
180
        $version = VERSION;
181
      }
182
      elseif (defined('\Drupal::VERSION')) {
183
        $version = \Drupal::VERSION;
184
      }
185
      else {
186
        throw new BootstrapException('Unable to determine Drupal core version. Supported versions are 6, 7, and 8.');
187
      }
188
189
      // Extract the major version from VERSION.
190
      $version_parts = explode('.', $version);
191
      if (is_numeric($version_parts[0])) {
192
        $this->version = (integer) $version_parts[0];
193
      }
194
      else {
195
        throw new BootstrapException(sprintf('Unable to extract major Drupal core version from version string %s.', $version));
196
      }
197
    }
198
    return $this->version;
199
  }
200
201
  /**
202
   * Instantiate and set Drupal core class.
203
   *
204
   * @param array $available_cores
205
   *   A major-version-keyed array of available core controllers.
206
   */
207
  public function setCore(array $available_cores) {
208
    if (!isset($available_cores[$this->version])) {
209
      throw new BootstrapException(sprintf('There is no available Drupal core controller for Drupal version %s.', $this->version));
210
    }
211
    $this->core = $available_cores[$this->version];
212
  }
213
214
  /**
215
   * Automatically set the core from the current version.
216
   */
217
  public function setCoreFromVersion() {
218
    $core = '\Drupal\Driver\Cores\Drupal' . $this->getDrupalVersion();
219
    $this->core = new $core($this->drupalRoot, $this->uri);
220
  }
221
222
  /**
223
   * Return current core.
224
   */
225
  public function getCore() {
226
    return $this->core;
227
  }
228
229
  /**
230
   * {@inheritdoc}
231
   */
232
  public function createNode($node) {
233
    return $this->getCore()->nodeCreate($node);
234
  }
235
236
  /**
237
   * {@inheritdoc}
238
   */
239
  public function nodeDelete($node) {
240
    return $this->getCore()->nodeDelete($node);
241
  }
242
243
  /**
244
   * {@inheritdoc}
245
   */
246
  public function runCron() {
247
    if (!$this->getCore()->runCron()) {
248
      throw new \Exception('Failed to run cron.');
249
    }
250
  }
251
252
  /**
253
   * {@inheritdoc}
254
   */
255
  public function createTerm(\stdClass $term) {
256
    return $this->getCore()->termCreate($term);
257
  }
258
259
  /**
260
   * {@inheritdoc}
261
   */
262
  public function termDelete(\stdClass $term) {
263
    return $this->getCore()->termDelete($term);
264
  }
265
266
  /**
267
   * {@inheritdoc}
268
   */
269
  public function roleCreate(array $permissions) {
270
    return $this->getCore()->roleCreate($permissions);
271
  }
272
273
  /**
274
   * {@inheritdoc}
275
   */
276
  public function roleDelete($rid) {
277
    $this->getCore()->roleDelete($rid);
278
  }
279
280
  /**
281
   * {@inheritdoc}
282
   */
283
  public function isField($entity_type, $field_name) {
284
    return $this->getCore()->isField($entity_type, $field_name);
285
  }
286
287
  /**
288
   * {@inheritdoc}
289
   */
290
  public function languageCreate($language) {
291
    return $this->getCore()->languageCreate($language);
292
  }
293
294
  /**
295
   * {@inheritdoc}
296
   */
297
  public function languageDelete($language) {
298
    $this->getCore()->languageDelete($language);
299
  }
300
301
  /**
302
   * {@inheritdoc}
303
   */
304
  public function configGet($name, $key) {
305
    return $this->getCore()->configGet($name, $key);
306
  }
307
308
  /**
309
   * {@inheritdoc}
310
   */
311
  public function configSet($name, $key, $value) {
312
    $this->getCore()->configSet($name, $key, $value);
313
  }
314
315
  /**
316
   * {@inheritdoc}
317
   */
318
  public function clearStaticCaches() {
319
    $this->getCore()->clearStaticCaches();
320
  }
321
322
  /**
323
   * {@inheritdoc}
324
   */
325
  public function createEntity($entity_type, \stdClass $entity) {
326
    return $this->getCore()->entityCreate($entity_type, $entity);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getCore()-...$entity_type, $entity); (Drupal\Core\Entity\EntityInterface) is incompatible with the return type declared by the interface Drupal\Driver\DriverInterface::createEntity of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
327
  }
328
329
  /**
330
   * {@inheritdoc}
331
   */
332
  public function entityDelete($entity_type, \stdClass $entity) {
333
    return $this->getCore()->entityDelete($entity_type, $entity);
334
  }
335
336
  /**
337
   * {@inheritdoc}
338
   */
339
  public function startCollectingMail() {
340
    return $this->getCore()->startCollectingMail();
341
  }
342
343
  /**
344
   * {@inheritdoc}
345
   */
346
  public function stopCollectingMail() {
347
    return $this->getCore()->stopCollectingMail();
348
  }
349
350
  /**
351
   * {@inheritdoc}
352
   */
353
  public function getMail() {
354
    return $this->getCore()->getMail();
355
  }
356
357
  /**
358
   * {@inheritdoc}
359
   */
360
  public function clearMail() {
361
    return $this->getCore()->clearMail();
362
  }
363
364
  /**
365
   * {@inheritdoc}
366
   */
367
  public function sendMail($body, $subject, $to, $langcode) {
368
    return $this->getCore()->sendMail($body, $subject, $to, $langcode);
369
  }
370
371
}
372