|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Drupal\Driver\Cores; |
|
4
|
|
|
|
|
5
|
|
|
use Drupal\Core\DrupalKernel; |
|
6
|
|
|
use Drupal\Core\Field\BaseFieldDefinition; |
|
7
|
|
|
use Drupal\Driver\Exception\BootstrapException; |
|
8
|
|
|
use Drupal\Driver\Wrapper\Entity\DriverEntityWrapperInterface; |
|
9
|
|
|
use Drupal\field\Entity\FieldStorageConfig; |
|
10
|
|
|
use Drupal\language\Entity\ConfigurableLanguage; |
|
11
|
|
|
use Drupal\mailsystem\MailsystemManager; |
|
12
|
|
|
use Drupal\node\Entity\Node; |
|
13
|
|
|
use Drupal\node\NodeInterface; |
|
14
|
|
|
use Drupal\Core\Entity\EntityInterface; |
|
15
|
|
|
use Drupal\taxonomy\Entity\Term; |
|
16
|
|
|
use Drupal\taxonomy\TermInterface; |
|
17
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
18
|
|
|
use Drupal\Driver\Plugin\DriverFieldPluginManager; |
|
19
|
|
|
use Drupal\Driver\Wrapper\Field\DriverFieldDrupal8; |
|
20
|
|
|
use Drupal\Driver\Wrapper\Entity\DriverEntityDrupal8; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Drupal 8 core. |
|
24
|
|
|
*/ |
|
25
|
|
|
class Drupal8 extends AbstractCore { |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* Tracks original configuration values. |
|
29
|
|
|
* |
|
30
|
|
|
* This is necessary since configurations modified here are actually saved so |
|
31
|
|
|
* that they persist values across bootstraps. |
|
32
|
|
|
* |
|
33
|
|
|
* @var array |
|
34
|
|
|
* An array of data, keyed by configuration name. |
|
35
|
|
|
*/ |
|
36
|
|
|
protected $originalConfiguration = []; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* {@inheritdoc} |
|
40
|
|
|
*/ |
|
41
|
|
|
public function bootstrap() { |
|
42
|
|
|
// Validate, and prepare environment for Drupal bootstrap. |
|
43
|
|
|
if (!defined('DRUPAL_ROOT')) { |
|
44
|
|
|
define('DRUPAL_ROOT', $this->drupalRoot); |
|
45
|
|
|
} |
|
46
|
|
|
|
|
47
|
|
|
// Bootstrap Drupal. |
|
48
|
|
|
chdir(DRUPAL_ROOT); |
|
49
|
|
|
$autoloader = require DRUPAL_ROOT . '/autoload.php'; |
|
50
|
|
|
require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc'; |
|
51
|
|
|
$this->validateDrupalSite(); |
|
52
|
|
|
|
|
53
|
|
|
$request = Request::createFromGlobals(); |
|
54
|
|
|
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); |
|
55
|
|
|
$kernel->boot(); |
|
56
|
|
|
$kernel->prepareLegacyRequest($request); |
|
57
|
|
|
|
|
58
|
|
|
// Initialise an anonymous session. required for the bootstrap. |
|
59
|
|
|
\Drupal::service('session_manager')->start(); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* {@inheritdoc} |
|
64
|
|
|
*/ |
|
65
|
|
|
public function clearCache() { |
|
66
|
|
|
// Need to change into the Drupal root directory or the registry explodes. |
|
67
|
|
|
drupal_flush_all_caches(); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* {@inheritdoc} |
|
72
|
|
|
*/ |
|
73
|
|
|
public function nodeCreate($node) { |
|
74
|
|
|
$entity = $this->getNewEntity('node'); |
|
75
|
|
|
$entity->setFields((array) $node); |
|
76
|
|
|
$entity->save(); |
|
77
|
|
|
$node->nid = $entity->id(); |
|
78
|
|
|
return $node; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* {@inheritdoc} |
|
83
|
|
|
*/ |
|
84
|
|
|
public function nodeDelete($node) { |
|
85
|
|
|
$nid = $node instanceof NodeInterface ? $node->id() : $node->nid; |
|
|
|
|
|
|
86
|
|
|
$entity = $this->getNewEntity('node'); |
|
87
|
|
|
$entity->load($nid); |
|
88
|
|
|
$entity->delete(); |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* {@inheritdoc} |
|
93
|
|
|
*/ |
|
94
|
|
|
public function runCron() { |
|
95
|
|
|
return \Drupal::service('cron')->run(); |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* {@inheritdoc} |
|
100
|
|
|
*/ |
|
101
|
|
|
public function userCreate(\stdClass $user) { |
|
102
|
|
|
// @todo determine if this needs to be here. It disrupts the new kernel |
|
103
|
|
|
// tests. |
|
104
|
|
|
$this->validateDrupalSite(); |
|
105
|
|
|
|
|
106
|
|
|
$entity = $this->getNewEntity('user'); |
|
107
|
|
|
$entity->setFields((array) $user); |
|
108
|
|
|
$entity->save(); |
|
109
|
|
|
$user->uid = $entity->id(); |
|
110
|
|
|
return $user; |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* {@inheritdoc} |
|
115
|
|
|
*/ |
|
116
|
|
|
public function roleCreate(array $permissions) { |
|
117
|
|
|
// Generate a random machine name & label. |
|
118
|
|
|
$id = strtolower($this->random->name(8, TRUE)); |
|
119
|
|
|
$label = trim($this->random->name(8, TRUE)); |
|
120
|
|
|
|
|
121
|
|
|
$entity = $this->getNewEntity('role'); |
|
122
|
|
|
$entity->set('id', $id); |
|
123
|
|
|
$entity->set('label', $label); |
|
124
|
|
|
$entity->grantPermissions($permissions); |
|
|
|
|
|
|
125
|
|
|
$entity->save(); |
|
126
|
|
|
return $entity->id(); |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* {@inheritdoc} |
|
131
|
|
|
*/ |
|
132
|
|
|
public function roleDelete($role_name) { |
|
133
|
|
|
$role = $this->getNewEntity('role'); |
|
134
|
|
|
$role->load($role_name); |
|
135
|
|
|
$role->delete(); |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
/** |
|
139
|
|
|
* {@inheritdoc} |
|
140
|
|
|
*/ |
|
141
|
|
|
public function processBatch() { |
|
142
|
|
|
$this->validateDrupalSite(); |
|
143
|
|
|
$batch =& batch_get(); |
|
144
|
|
|
$batch['progressive'] = FALSE; |
|
145
|
|
|
batch_process(); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* {@inheritdoc} |
|
150
|
|
|
*/ |
|
151
|
|
|
public function userDelete(\stdClass $user) { |
|
152
|
|
|
// Not using user_cancel here leads to an error when batch_process() |
|
153
|
|
|
// is subsequently called. |
|
154
|
|
|
user_cancel(array(), $user->uid, 'user_cancel_delete'); |
|
155
|
|
|
//$entity = $this->getNewEntity('user'); |
|
156
|
|
|
//$entity->load($user->uid); |
|
157
|
|
|
//$entity->delete(); |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
/** |
|
161
|
|
|
* {@inheritdoc} |
|
162
|
|
|
*/ |
|
163
|
|
|
public function userAddRole(\stdClass $user, $role_name) { |
|
164
|
|
|
$uid = $user->uid; |
|
165
|
|
|
$user = $this->getNewEntity('user'); |
|
166
|
|
|
$user->load($uid); |
|
167
|
|
|
$user->addRole($role_name); |
|
|
|
|
|
|
168
|
|
|
$user->save(); |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* {@inheritdoc} |
|
173
|
|
|
*/ |
|
174
|
|
|
public function validateDrupalSite() { |
|
175
|
|
|
if ('default' !== $this->uri) { |
|
176
|
|
|
// Fake the necessary HTTP headers that Drupal needs: |
|
177
|
|
|
$drupal_base_url = parse_url($this->uri); |
|
178
|
|
|
// If there's no url scheme set, add http:// and re-parse the url |
|
179
|
|
|
// so the host and path values are set accurately. |
|
180
|
|
|
if (!array_key_exists('scheme', $drupal_base_url)) { |
|
181
|
|
|
$drupal_base_url = parse_url($this->uri); |
|
182
|
|
|
} |
|
183
|
|
|
// Fill in defaults. |
|
184
|
|
|
$drupal_base_url += array( |
|
185
|
|
|
'path' => NULL, |
|
186
|
|
|
'host' => NULL, |
|
187
|
|
|
'port' => NULL, |
|
188
|
|
|
); |
|
189
|
|
|
$_SERVER['HTTP_HOST'] = $drupal_base_url['host']; |
|
190
|
|
|
|
|
191
|
|
|
if ($drupal_base_url['port']) { |
|
192
|
|
|
$_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port']; |
|
193
|
|
|
} |
|
194
|
|
|
$_SERVER['SERVER_PORT'] = $drupal_base_url['port']; |
|
195
|
|
|
|
|
196
|
|
|
if (array_key_exists('path', $drupal_base_url)) { |
|
197
|
|
|
$_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php'; |
|
198
|
|
|
} |
|
199
|
|
|
else { |
|
200
|
|
|
$_SERVER['PHP_SELF'] = '/index.php'; |
|
201
|
|
|
} |
|
202
|
|
|
} |
|
203
|
|
|
else { |
|
204
|
|
|
$_SERVER['HTTP_HOST'] = 'default'; |
|
205
|
|
|
$_SERVER['PHP_SELF'] = '/index.php'; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF']; |
|
209
|
|
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; |
|
210
|
|
|
$_SERVER['REQUEST_METHOD'] = NULL; |
|
211
|
|
|
|
|
212
|
|
|
$_SERVER['SERVER_SOFTWARE'] = NULL; |
|
213
|
|
|
$_SERVER['HTTP_USER_AGENT'] = NULL; |
|
214
|
|
|
|
|
215
|
|
|
$conf_path = DrupalKernel::findSitePath(Request::createFromGlobals()); |
|
216
|
|
|
$conf_file = $this->drupalRoot . "/$conf_path/settings.php"; |
|
217
|
|
|
if (!file_exists($conf_file)) { |
|
218
|
|
|
throw new BootstrapException(sprintf('Could not find a Drupal settings.php file at "%s"', $conf_file)); |
|
219
|
|
|
} |
|
220
|
|
|
$drushrc_file = $this->drupalRoot . "/$conf_path/drushrc.php"; |
|
221
|
|
|
if (file_exists($drushrc_file)) { |
|
222
|
|
|
require_once $drushrc_file; |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
/** |
|
227
|
|
|
* {@inheritdoc} |
|
228
|
|
|
*/ |
|
229
|
|
|
public function termCreate(\stdClass $term) { |
|
230
|
|
|
$entity = $this->getNewEntity('taxonomy_term'); |
|
231
|
|
|
$entity->setFields((array) $term); |
|
232
|
|
|
$entity->save(); |
|
233
|
|
|
$term->tid = $entity->id(); |
|
234
|
|
|
return $term; |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
/** |
|
238
|
|
|
* {@inheritdoc} |
|
239
|
|
|
*/ |
|
240
|
|
|
public function termDelete(\stdClass $term) { |
|
241
|
|
|
$entity = $this->getNewEntity('taxonomy_term'); |
|
242
|
|
|
$entity->load($term->tid); |
|
243
|
|
|
$entity->delete(); |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* {@inheritdoc} |
|
248
|
|
|
*/ |
|
249
|
|
|
public function getModuleList() { |
|
250
|
|
|
return array_keys(\Drupal::moduleHandler()->getModuleList()); |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
/** |
|
254
|
|
|
* {@inheritdoc} |
|
255
|
|
|
*/ |
|
256
|
|
|
public function getExtensionPathList() { |
|
257
|
|
|
$paths = array(); |
|
258
|
|
|
|
|
259
|
|
|
// Get enabled modules. |
|
260
|
|
|
foreach (\Drupal::moduleHandler()->getModuleList() as $module) { |
|
261
|
|
|
$paths[] = $this->drupalRoot . DIRECTORY_SEPARATOR . $module->getPath(); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
return $paths; |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
/** |
|
268
|
|
|
* {@inheritdoc} |
|
269
|
|
|
*/ |
|
270
|
|
|
protected function expandEntityFields($entity_type, \stdClass $entity, array $base_fields = array()) { |
|
271
|
|
|
$field_types = $this->getEntityFieldTypes($entity_type, $base_fields); |
|
272
|
|
|
$bundle_key = \Drupal::entityManager()->getDefinition($entity_type)->getKey('bundle'); |
|
273
|
|
|
if (isset($entity->$bundle_key) && ($entity->$bundle_key !== NULL)) { |
|
274
|
|
|
$bundle = $entity->$bundle_key; |
|
275
|
|
|
} |
|
276
|
|
|
else { |
|
277
|
|
|
$bundle = $entity_type; |
|
278
|
|
|
} |
|
279
|
|
|
|
|
280
|
|
|
foreach ($field_types as $field_name => $type) { |
|
281
|
|
|
if (isset($entity->$field_name)) { |
|
282
|
|
|
// @todo find a bettter way of standardising single/multi value fields |
|
283
|
|
|
if (is_array($entity->$field_name)) { |
|
284
|
|
|
$fieldValues = $entity->$field_name; |
|
285
|
|
|
} |
|
286
|
|
|
else { |
|
287
|
|
|
$fieldValues = [$entity->$field_name]; |
|
288
|
|
|
} |
|
289
|
|
|
$field = New DriverFieldDrupal8( |
|
290
|
|
|
$fieldValues, |
|
291
|
|
|
$field_name, |
|
292
|
|
|
$entity_type, |
|
293
|
|
|
$bundle |
|
294
|
|
|
); |
|
295
|
|
|
$entity->$field_name = $field->getProcessedValues(); |
|
296
|
|
|
} |
|
297
|
|
|
} |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
/** |
|
301
|
|
|
* Expands specified base fields on the entity object. |
|
302
|
|
|
* |
|
303
|
|
|
* @param string $entity_type |
|
304
|
|
|
* The entity type for which to return the field types. |
|
305
|
|
|
* @param \stdClass $entity |
|
306
|
|
|
* Entity object. |
|
307
|
|
|
* @param array $base_fields |
|
308
|
|
|
* Base fields to be expanded in addition to user defined fields. |
|
309
|
|
|
*/ |
|
310
|
|
|
public function expandEntityBaseFields($entity_type, \stdClass $entity, array $base_fields) { |
|
311
|
|
|
$this->expandEntityFields($entity_type, $entity, $base_fields); |
|
312
|
|
|
} |
|
313
|
|
|
|
|
314
|
|
|
/** |
|
315
|
|
|
* {@inheritdoc} |
|
316
|
|
|
*/ |
|
317
|
|
|
public function getEntityFieldTypes($entity_type, array $base_fields = array()) { |
|
318
|
|
|
$return = array(); |
|
319
|
|
|
$fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type); |
|
320
|
|
|
foreach ($fields as $field_name => $field) { |
|
321
|
|
|
if ($this->isField($entity_type, $field_name) |
|
322
|
|
|
|| (in_array($field_name, $base_fields) && $this->isBaseField($entity_type, $field_name))) { |
|
323
|
|
|
$return[$field_name] = $field->getType(); |
|
324
|
|
|
} |
|
325
|
|
|
} |
|
326
|
|
|
return $return; |
|
327
|
|
|
} |
|
328
|
|
|
|
|
329
|
|
|
/** |
|
330
|
|
|
* Get a new driver entity wrapper. |
|
331
|
|
|
* |
|
332
|
|
|
* @return \Drupal\Driver\Wrapper\Entity\DriverEntityWrapperInterface; |
|
|
|
|
|
|
333
|
|
|
*/ |
|
334
|
|
|
public function getNewEntity($type, $bundle = NULL) { |
|
335
|
|
|
$entity = new DriverEntityDrupal8($type, $bundle); |
|
336
|
|
|
return $entity; |
|
337
|
|
|
} |
|
338
|
|
|
|
|
339
|
|
|
/** |
|
340
|
|
|
* {@inheritdoc} |
|
341
|
|
|
*/ |
|
342
|
|
|
public function isField($entity_type, $field_name) { |
|
343
|
|
|
$fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type); |
|
344
|
|
|
return (isset($fields[$field_name]) && $fields[$field_name] instanceof FieldStorageConfig); |
|
|
|
|
|
|
345
|
|
|
} |
|
346
|
|
|
|
|
347
|
|
|
/** |
|
348
|
|
|
* {@inheritdoc} |
|
349
|
|
|
*/ |
|
350
|
|
|
public function isBaseField($entity_type, $field_name) { |
|
351
|
|
|
$fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type); |
|
352
|
|
|
return (isset($fields[$field_name]) && $fields[$field_name] instanceof BaseFieldDefinition); |
|
|
|
|
|
|
353
|
|
|
} |
|
354
|
|
|
|
|
355
|
|
|
/** |
|
356
|
|
|
* {@inheritdoc} |
|
357
|
|
|
*/ |
|
358
|
|
|
public function languageCreate(\stdClass $language) { |
|
359
|
|
|
$langcode = $language->langcode; |
|
360
|
|
|
|
|
361
|
|
|
// Enable a language only if it has not been enabled already. |
|
362
|
|
|
if (!ConfigurableLanguage::load($langcode)) { |
|
363
|
|
|
$entity = $this->getNewEntity('configurable_language'); |
|
364
|
|
|
$entity->set('id', $langcode); |
|
365
|
|
|
$entity->set('label', $langcode); |
|
366
|
|
|
$entity->save(); |
|
367
|
|
|
return $language; |
|
368
|
|
|
} |
|
369
|
|
|
|
|
370
|
|
|
return FALSE; |
|
371
|
|
|
} |
|
372
|
|
|
|
|
373
|
|
|
/** |
|
374
|
|
|
* {@inheritdoc} |
|
375
|
|
|
*/ |
|
376
|
|
|
public function languageDelete(\stdClass $language) { |
|
377
|
|
|
$configurable_language = ConfigurableLanguage::load($language->langcode); |
|
378
|
|
|
$configurable_language->delete(); |
|
379
|
|
|
} |
|
380
|
|
|
|
|
381
|
|
|
/** |
|
382
|
|
|
* {@inheritdoc} |
|
383
|
|
|
*/ |
|
384
|
|
|
public function clearStaticCaches() { |
|
385
|
|
|
drupal_static_reset(); |
|
386
|
|
|
\Drupal::service('cache_tags.invalidator')->resetChecksums(); |
|
387
|
|
|
} |
|
388
|
|
|
|
|
389
|
|
|
/** |
|
390
|
|
|
* {@inheritdoc} |
|
391
|
|
|
*/ |
|
392
|
|
|
public function configGet($name, $key = '') { |
|
393
|
|
|
return \Drupal::config($name)->get($key); |
|
394
|
|
|
} |
|
395
|
|
|
|
|
396
|
|
|
/** |
|
397
|
|
|
* {@inheritdoc} |
|
398
|
|
|
*/ |
|
399
|
|
|
public function configSet($name, $key, $value) { |
|
400
|
|
|
\Drupal::configFactory()->getEditable($name) |
|
401
|
|
|
->set($key, $value) |
|
402
|
|
|
->save(); |
|
403
|
|
|
} |
|
404
|
|
|
|
|
405
|
|
|
/** |
|
406
|
|
|
* {@inheritdoc} |
|
407
|
|
|
*/ |
|
408
|
|
|
public function entityCreate($entity_type, $entity) { |
|
409
|
|
|
$entityWrapped = $this->getNewEntity($entity_type); |
|
410
|
|
|
$entityWrapped->setFields((array) $entity); |
|
411
|
|
|
$entityWrapped->save(); |
|
412
|
|
|
$entity->id = $entityWrapped->id(); |
|
413
|
|
|
return $entity; |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
/** |
|
417
|
|
|
* {@inheritdoc} |
|
418
|
|
|
*/ |
|
419
|
|
|
public function entityDelete($entity_type, $entity) { |
|
420
|
|
|
$eid = $entity instanceof EntityInterface ? $entity->id() : $entity->id; |
|
|
|
|
|
|
421
|
|
|
$entity = $this->getNewEntity($entity_type); |
|
422
|
|
|
$entity->load($eid); |
|
423
|
|
|
$entity->delete(); |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
/** |
|
427
|
|
|
* {@inheritdoc} |
|
428
|
|
|
*/ |
|
429
|
|
|
public function startCollectingMail() { |
|
430
|
|
|
$config = \Drupal::configFactory()->getEditable('system.mail'); |
|
431
|
|
|
$data = $config->getRawData(); |
|
432
|
|
|
|
|
433
|
|
|
// Save the original values for restoration after. |
|
434
|
|
|
$this->originalConfiguration['system.mail'] = $data; |
|
435
|
|
|
|
|
436
|
|
|
// @todo Use a collector that supports html after D#2223967 lands. |
|
437
|
|
|
$data['interface'] = ['default' => 'test_mail_collector']; |
|
438
|
|
|
$config->setData($data)->save(); |
|
439
|
|
|
// Disable the mail system module's mail if enabled. |
|
440
|
|
|
$this->startCollectingMailSystemMail(); |
|
441
|
|
|
} |
|
442
|
|
|
|
|
443
|
|
|
/** |
|
444
|
|
|
* {@inheritdoc} |
|
445
|
|
|
*/ |
|
446
|
|
|
public function stopCollectingMail() { |
|
447
|
|
|
$config = \Drupal::configFactory()->getEditable('system.mail'); |
|
448
|
|
|
$config->setData($this->originalConfiguration['system.mail'])->save(); |
|
449
|
|
|
// Re-enable the mailsystem module's mail if enabled. |
|
450
|
|
|
$this->stopCollectingMailSystemMail(); |
|
451
|
|
|
} |
|
452
|
|
|
|
|
453
|
|
|
/** |
|
454
|
|
|
* {@inheritdoc} |
|
455
|
|
|
*/ |
|
456
|
|
|
public function getMail() { |
|
457
|
|
|
\Drupal::state()->resetCache(); |
|
458
|
|
|
$mail = \Drupal::state()->get('system.test_mail_collector') ?: []; |
|
459
|
|
|
// Discard cancelled mail. |
|
460
|
|
|
$mail = array_values(array_filter($mail, function ($mailItem) { |
|
461
|
|
|
return ($mailItem['send'] == TRUE); |
|
462
|
|
|
})); |
|
463
|
|
|
return $mail; |
|
464
|
|
|
} |
|
465
|
|
|
|
|
466
|
|
|
/** |
|
467
|
|
|
* {@inheritdoc} |
|
468
|
|
|
*/ |
|
469
|
|
|
public function clearMail() { |
|
470
|
|
|
\Drupal::state()->set('system.test_mail_collector', []); |
|
471
|
|
|
} |
|
472
|
|
|
|
|
473
|
|
|
/** |
|
474
|
|
|
* {@inheritdoc} |
|
475
|
|
|
*/ |
|
476
|
|
|
public function sendMail($body = '', $subject = '', $to = '', $langcode = '') { |
|
477
|
|
|
// Send the mail, via the system module's hook_mail. |
|
478
|
|
|
$params['context']['message'] = $body; |
|
|
|
|
|
|
479
|
|
|
$params['context']['subject'] = $subject; |
|
480
|
|
|
$mailManager = \Drupal::service('plugin.manager.mail'); |
|
481
|
|
|
$result = $mailManager->mail('system', '', $to, $langcode, $params, NULL, TRUE); |
|
482
|
|
|
return $result; |
|
483
|
|
|
} |
|
484
|
|
|
|
|
485
|
|
|
/** |
|
486
|
|
|
* If the Mail System module is enabled, collect that mail too. |
|
487
|
|
|
* |
|
488
|
|
|
* @see MailsystemManager::getPluginInstance() |
|
489
|
|
|
*/ |
|
490
|
|
|
protected function startCollectingMailSystemMail() { |
|
491
|
|
|
if (\Drupal::moduleHandler()->moduleExists('mailsystem')) { |
|
492
|
|
|
$config = \Drupal::configFactory()->getEditable('mailsystem.settings'); |
|
493
|
|
|
$data = $config->getRawData(); |
|
494
|
|
|
|
|
495
|
|
|
// Track original data for restoration. |
|
496
|
|
|
$this->originalConfiguration['mailsystem.settings'] = $data; |
|
497
|
|
|
|
|
498
|
|
|
// Convert all of the 'senders' to the test collector. |
|
499
|
|
|
$data = $this->findMailSystemSenders($data); |
|
500
|
|
|
$config->setData($data)->save(); |
|
501
|
|
|
} |
|
502
|
|
|
} |
|
503
|
|
|
|
|
504
|
|
|
/** |
|
505
|
|
|
* Find and replace all the mail system sender plugins with the test plugin. |
|
506
|
|
|
* |
|
507
|
|
|
* This method calls itself recursively. |
|
508
|
|
|
*/ |
|
509
|
|
|
protected function findMailSystemSenders(array $data) { |
|
510
|
|
|
foreach ($data as $key => $values) { |
|
511
|
|
|
if (is_array($values)) { |
|
512
|
|
|
if (isset($values[MailsystemManager::MAILSYSTEM_TYPE_SENDING])) { |
|
513
|
|
|
$data[$key][MailsystemManager::MAILSYSTEM_TYPE_SENDING] = 'test_mail_collector'; |
|
514
|
|
|
} |
|
515
|
|
|
else { |
|
516
|
|
|
$data[$key] = $this->findMailSystemSenders($values); |
|
517
|
|
|
} |
|
518
|
|
|
} |
|
519
|
|
|
} |
|
520
|
|
|
return $data; |
|
521
|
|
|
} |
|
522
|
|
|
|
|
523
|
|
|
/** |
|
524
|
|
|
* If the Mail System module is enabled, stop collecting those mails. |
|
525
|
|
|
*/ |
|
526
|
|
|
protected function stopCollectingMailSystemMail() { |
|
527
|
|
|
if (\Drupal::moduleHandler()->moduleExists('mailsystem')) { |
|
528
|
|
|
\Drupal::configFactory()->getEditable('mailsystem.settings')->setData($this->originalConfiguration['mailsystem.settings'])->save(); |
|
529
|
|
|
} |
|
530
|
|
|
} |
|
531
|
|
|
|
|
532
|
|
|
} |
|
533
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.jsonfile (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.jsonto be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
requireorrequire-devsection?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceofchecks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.