Completed
Pull Request — master (#157)
by
unknown
01:46
created

Drupal8::entityDelete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
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;
0 ignored issues
show
Bug introduced by
The class Drupal\node\NodeInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to 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 require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
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);
0 ignored issues
show
Documentation Bug introduced by
The method grantPermissions does not exist on object<Drupal\Driver\Wra...ty\DriverEntityDrupal8>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
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);
0 ignored issues
show
Documentation Bug introduced by
The method addRole does not exist on object<Drupal\Driver\Wra...ty\DriverEntityDrupal8>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
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
   * Expands specified base fields on the entity object.
269
   *
270
   * @param string $entity_type
271
   *   The entity type for which to return the field types.
272
   * @param \stdClass $entity
273
   *   Entity object.
274
   * @param array $base_fields
275
   *   Base fields to be expanded in addition to user defined fields.
276
   */
277
  public function expandEntityBaseFields($entity_type, \stdClass $entity, array $base_fields) {
278
    $this->expandEntityFields($entity_type, $entity, $base_fields);
0 ignored issues
show
Unused Code introduced by
The call to Drupal8::expandEntityFields() has too many arguments starting with $base_fields.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
279
  }
280
281
  /**
282
   * {@inheritdoc}
283
   */
284
  public function getEntityFieldTypes($entity_type, array $base_fields = array()) {
285
    $return = array();
286
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
287
    foreach ($fields as $field_name => $field) {
288
      if ($this->isField($entity_type, $field_name)
289
        || (in_array($field_name, $base_fields) && $this->isBaseField($entity_type, $field_name))) {
290
        $return[$field_name] = $field->getType();
291
      }
292
    }
293
    return $return;
294
  }
295
296
  /**
297
   * Get a new driver entity wrapper.
298
   *
299
   * @return \Drupal\Driver\Wrapper\Entity\DriverEntityWrapperInterface;
0 ignored issues
show
Documentation introduced by
The doc-type \Drupal\Driver\Wrapper\E...EntityWrapperInterface; could not be parsed: Expected "|" or "end of type", but got ";" at position 58. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
300
   */
301
  public function getNewEntity($type, $bundle = NULL) {
302
    $entity = new DriverEntityDrupal8($type, $bundle);
303
    return $entity;
304
  }
305
306
  /**
307
   * {@inheritdoc}
308
   */
309
  public function isField($entity_type, $field_name) {
310
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
311
    return (isset($fields[$field_name]) && $fields[$field_name] instanceof FieldStorageConfig);
0 ignored issues
show
Bug introduced by
The class Drupal\field\Entity\FieldStorageConfig does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to 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 require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
312
  }
313
314
  /**
315
   * {@inheritdoc}
316
   */
317
  public function isBaseField($entity_type, $field_name) {
318
    $fields = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type);
319
    return (isset($fields[$field_name]) && $fields[$field_name] instanceof BaseFieldDefinition);
0 ignored issues
show
Bug introduced by
The class Drupal\Core\Field\BaseFieldDefinition does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to 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 require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
320
  }
321
322
  /**
323
   * {@inheritdoc}
324
   */
325
  public function languageCreate(\stdClass $language) {
326
    $langcode = $language->langcode;
327
328
    // Enable a language only if it has not been enabled already.
329
    if (!ConfigurableLanguage::load($langcode)) {
330
      $entity = $this->getNewEntity('configurable_language');
331
      $entity->set('id', $langcode);
332
      $entity->set('label', $langcode);
333
      $entity->save();
334
      return $language;
335
    }
336
337
    return FALSE;
338
  }
339
340
  /**
341
   * {@inheritdoc}
342
   */
343
  public function languageDelete(\stdClass $language) {
344
    $configurable_language = ConfigurableLanguage::load($language->langcode);
345
    $configurable_language->delete();
346
  }
347
348
  /**
349
   * {@inheritdoc}
350
   */
351
  public function clearStaticCaches() {
352
    drupal_static_reset();
353
    \Drupal::service('cache_tags.invalidator')->resetChecksums();
354
  }
355
356
  /**
357
   * {@inheritdoc}
358
   */
359
  public function configGet($name, $key = '') {
360
    return \Drupal::config($name)->get($key);
361
  }
362
363
  /**
364
   * {@inheritdoc}
365
   */
366
  public function configSet($name, $key, $value) {
367
    \Drupal::configFactory()->getEditable($name)
368
      ->set($key, $value)
369
      ->save();
370
  }
371
372
  /**
373
   * {@inheritdoc}
374
   */
375
  public function entityCreate($entity_type, $entity) {
376
    $entityWrapped = $this->getNewEntity($entity_type);
377
    $entityWrapped->setFields((array) $entity);
378
    $entityWrapped->save();
379
    $entity->id = $entityWrapped->id();
380
    return $entity;
381
  }
382
383
  /**
384
   * {@inheritdoc}
385
   */
386
  public function entityDelete($entity_type, $entity) {
387
    $eid = $entity instanceof EntityInterface ? $entity->id() : $entity->id;
0 ignored issues
show
Bug introduced by
The class Drupal\Core\Entity\EntityInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to 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 require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
388
    $entity = $this->getNewEntity($entity_type);
389
    $entity->load($eid);
390
    $entity->delete();
391
  }
392
393
  /**
394
   * {@inheritdoc}
395
   */
396
  public function startCollectingMail() {
397
    $config = \Drupal::configFactory()->getEditable('system.mail');
398
    $data = $config->getRawData();
399
400
    // Save the original values for restoration after.
401
    $this->originalConfiguration['system.mail'] = $data;
402
403
    // @todo Use a collector that supports html after D#2223967 lands.
404
    $data['interface'] = ['default' => 'test_mail_collector'];
405
    $config->setData($data)->save();
406
    // Disable the mail system module's mail if enabled.
407
    $this->startCollectingMailSystemMail();
408
  }
409
410
  /**
411
   * {@inheritdoc}
412
   */
413
  public function stopCollectingMail() {
414
    $config = \Drupal::configFactory()->getEditable('system.mail');
415
    $config->setData($this->originalConfiguration['system.mail'])->save();
416
    // Re-enable the mailsystem module's mail if enabled.
417
    $this->stopCollectingMailSystemMail();
418
  }
419
420
  /**
421
   * {@inheritdoc}
422
   */
423
  public function getMail() {
424
    \Drupal::state()->resetCache();
425
    $mail = \Drupal::state()->get('system.test_mail_collector') ?: [];
426
    // Discard cancelled mail.
427
    $mail = array_values(array_filter($mail, function ($mailItem) {
428
      return ($mailItem['send'] == TRUE);
429
    }));
430
    return $mail;
431
  }
432
433
  /**
434
   * {@inheritdoc}
435
   */
436
  public function clearMail() {
437
    \Drupal::state()->set('system.test_mail_collector', []);
438
  }
439
440
  /**
441
   * {@inheritdoc}
442
   */
443
  public function sendMail($body = '', $subject = '', $to = '', $langcode = '') {
444
    // Send the mail, via the system module's hook_mail.
445
    $params['context']['message'] = $body;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
446
    $params['context']['subject'] = $subject;
447
    $mailManager = \Drupal::service('plugin.manager.mail');
448
    $result = $mailManager->mail('system', '', $to, $langcode, $params, NULL, TRUE);
449
    return $result;
450
  }
451
452
  /**
453
   * If the Mail System module is enabled, collect that mail too.
454
   *
455
   * @see MailsystemManager::getPluginInstance()
456
   */
457
  protected function startCollectingMailSystemMail() {
458
    if (\Drupal::moduleHandler()->moduleExists('mailsystem')) {
459
      $config = \Drupal::configFactory()->getEditable('mailsystem.settings');
460
      $data = $config->getRawData();
461
462
      // Track original data for restoration.
463
      $this->originalConfiguration['mailsystem.settings'] = $data;
464
465
      // Convert all of the 'senders' to the test collector.
466
      $data = $this->findMailSystemSenders($data);
467
      $config->setData($data)->save();
468
    }
469
  }
470
471
  /**
472
   * Find and replace all the mail system sender plugins with the test plugin.
473
   *
474
   * This method calls itself recursively.
475
   */
476
  protected function findMailSystemSenders(array $data) {
477
    foreach ($data as $key => $values) {
478
      if (is_array($values)) {
479
        if (isset($values[MailsystemManager::MAILSYSTEM_TYPE_SENDING])) {
480
          $data[$key][MailsystemManager::MAILSYSTEM_TYPE_SENDING] = 'test_mail_collector';
481
        }
482
        else {
483
          $data[$key] = $this->findMailSystemSenders($values);
484
        }
485
      }
486
    }
487
    return $data;
488
  }
489
490
  /**
491
   * If the Mail System module is enabled, stop collecting those mails.
492
   */
493
  protected function stopCollectingMailSystemMail() {
494
    if (\Drupal::moduleHandler()->moduleExists('mailsystem')) {
495
      \Drupal::configFactory()->getEditable('mailsystem.settings')->setData($this->originalConfiguration['mailsystem.settings'])->save();
496
    }
497
  }
498
499
  /**
500
   * Expands properties on the given entity object to the expected structure.
501
   *
502
   * @param string $entity_type
503
   *   The entity type ID.
504
   * @param \stdClass $entity
505
   *   Entity object.
506
   */
507
  protected function expandEntityFields($entity_type, \stdClass $entity) {
508
    $field_types = $this->getEntityFieldTypes($entity_type);
509
    $bundle_key = \Drupal::entityManager()->getDefinition($entity_type)->getKey('bundle');
510
    if (isset($entity->$bundle_key) && ($entity->$bundle_key !== NULL)) {
511
      $bundle = $entity->$bundle_key;
512
    }
513
    else {
514
      $bundle = $entity_type;
515
    }
516
517
    foreach ($field_types as $field_name => $type) {
518
      if (isset($entity->$field_name)) {
519
        // @todo find a bettter way of standardising single/multi value fields
520
        if (is_array($entity->$field_name)) {
521
          $fieldValues = $entity->$field_name;
522
        }
523
        else {
524
          $fieldValues = [$entity->$field_name];
525
        }
526
        $field = New DriverFieldDrupal8(
527
          $fieldValues,
528
          $field_name,
529
          $entity_type,
530
          $bundle
531
        );
532
        $entity->$field_name = $field->getProcessedValues();
533
      }
534
    }
535
  }
536
537
}
538