Skip to content

Commit

Permalink
Allow creation of entities of any type with base field value parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisolof committed Mar 6, 2024
1 parent 22d69d8 commit 7c6168b
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 32 deletions.
17 changes: 17 additions & 0 deletions src/Drupal/DrupalExtension/Context/DrupalContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,23 @@ public function assertEditNodeOfType($type)
$this->assertSession()->statusCodeEquals('200');
}

/**
* Creates entities of a given type provided in a table.
*
* Example:
* | title | author | status | created |
* | My title | Joe Editor | 1 | 2014-10-17 8:00am |
* | ... | ... | ... | ... |
*
* @Given :type entities:
*/
public function createEntities($type, TableNode $entitiesTable)
{
foreach ($entitiesTable->getHash() as $entityHash) {
$entity = (object) $entityHash;
$this->entityCreate($type, $entity);
}
}

/**
* Creates a term on an existing vocabulary.
Expand Down
102 changes: 70 additions & 32 deletions src/Drupal/DrupalExtension/Context/RawDrupalContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ class RawDrupalContext extends RawMinkContext implements DrupalAwareInterface
*/
protected $terms = [];

/**
* Keep track of created entities so they can be cleaned up.
*
* Each entry is expected to have the following keys:
* - type: The entity type.
* - entity: The saved entity object.
*
* @var array
*/
protected $entities = [];

/**
* Keep track of any roles that are created so they can easily be removed.
*
Expand Down Expand Up @@ -288,6 +299,19 @@ public function cleanTerms()
$this->terms = [];
}

/**
* Remove any created entities.
*
* @AfterScenario
*/
public function cleanEntities()
{
foreach (array_reverse($this->entities) as [$type, $entity]) {
$this->getDriver()->entityDelete($type, $entity);
}
$this->entities = [];
}

/**
* Remove any created roles.
*
Expand Down Expand Up @@ -419,40 +443,38 @@ public function parseEntityFields($entity_type, \stdClass $entity)

$is_multicolumn = $multicolumn_field && $multicolumn_column;
$field_name = $multicolumn_field ?: $field;
if ($this->getDriver()->isField($entity_type, $field_name)) {
// Split up multiple values in multi-value fields.
$values = [];
foreach (str_getcsv($field_value) as $key => $value) {
$value = trim((string) $value);
$columns = $value;
// Split up field columns if the ' - ' separator is present.
if (strstr($value, ' - ') !== false) {
$columns = [];
foreach (explode(' - ', $value) as $column) {
// Check if it is an inline named column.
if (!$is_multicolumn && strpos($column, ': ', 1) !== false) {
list ($key, $column) = explode(': ', $column);
$columns[$key] = $column;
} else {
$columns[] = $column;
}
// Split up multiple values in multi-value fields.
$values = [];
foreach (str_getcsv($field_value) as $key => $value) {
$value = trim((string) $value);
$columns = $value;
// Split up field columns if the ' - ' separator is present.
if (strstr($value, ' - ') !== false) {
$columns = [];
foreach (explode(' - ', $value) as $column) {
// Check if it is an inline named column.
if (!$is_multicolumn && strpos($column, ': ', 1) !== false) {
list ($key, $column) = explode(': ', $column);
$columns[$key] = $column;
} else {
$columns[] = $column;
}
}
// Use the column name if we are tracking a multicolumn field.
if ($is_multicolumn) {
$multicolumn_fields[$multicolumn_field][$key][$multicolumn_column] = $columns;
unset($entity->$field);
} else {
$values[] = $columns;
}
}
// Replace regular fields inline in the entity after parsing.
if (!$is_multicolumn) {
$entity->$field_name = $values;
// Don't specify any value if the step author has left it blank.
if ($field_value === '') {
unset($entity->$field_name);
}
// Use the column name if we are tracking a multicolumn field.
if ($is_multicolumn) {
$multicolumn_fields[$multicolumn_field][$key][$multicolumn_column] = $columns;
unset($entity->$field);
} else {
$values[] = $columns;
}
}
// Replace regular fields inline in the entity after parsing.
if (!$is_multicolumn) {
$entity->$field_name = count($values) > 1 ? $values : reset($values);
// Don't specify any value if the step author has left it blank.
if ($field_value === '') {
unset($entity->$field_name);
}
}
}
Expand All @@ -463,7 +485,7 @@ public function parseEntityFields($entity_type, \stdClass $entity)
if (count(array_filter($columns, function ($var) {
return ($var !== '');
})) > 0) {
$entity->$field_name = $columns;
$entity->$field_name = count($columns) > 1 ? $columns : reset($columns);
}
}
}
Expand Down Expand Up @@ -500,6 +522,22 @@ public function termCreate($term)
return $saved;
}

/**
* Create an entity.
*
* @return object
* The created entity.
*/
public function entityCreate($type, $entity)
{
$this->dispatchHooks('BeforeEntityCreateScope', $entity);
$this->parseEntityFields($type, $entity);
$saved = $this->getDriver()->createEntity($type, $entity);
$this->dispatchHooks('AfterEntityCreateScope', $saved);
$this->entities[] = [$type, $saved];
return $saved;
}

/**
* Creates a language.
*
Expand Down
25 changes: 25 additions & 0 deletions src/Drupal/DrupalExtension/Hook/Scope/AfterEntityCreateScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* @file
* After entity create scope.
*/
namespace Drupal\DrupalExtension\Hook\Scope;

use Behat\Testwork\Hook\Scope\HookScope;

/**
* Represents an Entity hook scope.
*/
final class AfterEntityCreateScope extends BaseEntityScope
{

/**
* Return the scope name.
*
* @return string
*/
public function getName()
{
return self::AFTER;
}
}
25 changes: 25 additions & 0 deletions src/Drupal/DrupalExtension/Hook/Scope/BeforeEntityCreateScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* @file
* Before entity create scope.
*/
namespace Drupal\DrupalExtension\Hook\Scope;

use Behat\Testwork\Hook\Scope\HookScope;

/**
* Represents an Entity hook scope.
*/
final class BeforeEntityCreateScope extends BaseEntityScope
{

/**
* Return the scope name.
*
* @return string
*/
public function getName()
{
return self::BEFORE;
}
}

0 comments on commit 7c6168b

Please sign in to comment.