Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/schema/og.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,17 @@ og.og_role.*:
sequence:
type: string
label: 'Permission'

field.widget.settings.og_complex:
type: mapping
label: 'OG Group Audience field widget'
mapping:
match_operator:
type: string
label: 'Autocomplete matching'
size:
type: integer
label: 'Size of textfield'
placeholder:
type: label
label: 'Placeholder'
32 changes: 30 additions & 2 deletions src/Og.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
Expand Down Expand Up @@ -59,7 +60,7 @@ public static function createField($plugin_id, $entity_type, $bundle, array $set

// Get the field definition and add the entity info to it. By doing so
// we validate the the field can be attached to the entity. For example,
// the OG accesss module's field can be attached only to node entities, so
// the OG access module's field can be attached only to node entities, so
// any other entity will throw an exception.
/** @var \Drupal\og\OgFieldBase $og_field */
$og_field = static::getFieldBaseDefinition($plugin_id)
Expand All @@ -72,7 +73,6 @@ public static function createField($plugin_id, $entity_type, $bundle, array $set
FieldStorageConfig::create($field_storage_config)->save();
}


if (!$field_definition = FieldConfig::loadByName($entity_type, $bundle, $field_name)) {
$field_config = NestedArray::mergeDeep($og_field->getFieldConfigBaseDefinition(), $settings['field_config']);

Expand All @@ -83,6 +83,34 @@ public static function createField($plugin_id, $entity_type, $bundle, array $set
static::invalidateCache();
}

// Make the field visible in the default form display.
/** @var EntityFormDisplayInterface $form_display */
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load("$entity_type.$bundle.default");

// If not found, create a fresh form display object. This is by design,
// configuration entries are only created when an entity form display is
// explicitly configured and saved.
// @see entity_get_form_display()
if (!$form_display) {
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->create([
'targetEntityType' => $entity_type,
'bundle' => $bundle,
'mode' => 'default',
'status' => TRUE,
]);
}

$widget = $form_display->getComponent($plugin_id);
$widget['type'] = 'og_complex';
$widget['settings'] = [
'match_operator' => 'CONTAINS',
'size' => 60,
'placeholder' => '',
];

$form_display->setComponent($plugin_id, $widget);
$form_display->save();

return $field_definition;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Plugin/Field/FieldType/OgStandardReferenceItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* default_widget = "og_complex",
* default_formatter = "og_complex",
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* constraints = {"ValidReference" = {}, "ValidOgMembershipReference" = {}}
* constraints = {"ValidOgMembershipReference" = {}}
* )
*/
class OgStandardReferenceItem extends EntityReferenceItem {
Expand Down
23 changes: 12 additions & 11 deletions src/Plugin/Field/FieldWidget/OgComplex.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,13 @@ public function otherGroupsSingle($delta, EntityInterface $entity = NULL, $weigh
* {@inheritdoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
$parent_values = $values;
// Remove empty values. The form fields may be empty.
$values = array_filter($values, function ($item) {
return !empty($item['target_id']);
});

// Get the groups from the other groups widget.
foreach ($form['other_groups'] as $key => $value) {
foreach ($form[$this->fieldDefinition->getName()]['other_groups'] as $key => $value) {
if (!is_int($key)) {
continue;
}
Expand All @@ -319,18 +322,16 @@ public function massageFormValues(array $values, array $form, FormStateInterface
// be captured in it's own group, with the key 'id'.
preg_match("|.+\((?<id>[\w.]+)\)|", $value['target_id']['#value'], $matches);

if (empty($matches['id'])) {
continue;
if (!empty($matches['id'])) {
$values[] = [
'target_id' => $matches['id'],
'_weight' => $value['_weight']['#value'],
'_original_delta' => $value['_weight']['#delta'],
];
}

$parent_values[] = [
'target_id' => $matches['id'],
'_weight' => $value['_weight']['#value'],
'_original_delta' => $value['_weight']['#delta'],
];
}

return $parent_values;
return $values;
}

/**
Expand Down
98 changes: 98 additions & 0 deletions tests/src/Functional/OgComplexWidgetTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

/**
* @file
* Contains \Drupal\Tests\og\Functional\OgComplexWidgetTest.
*/

namespace Drupal\Tests\og\Functional;

use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\og\Og;
use Drupal\og\OgGroupAudienceHelper;
use Drupal\og\Plugin\Field\FieldType\OgMembershipReferenceItemList;
use Drupal\simpletest\BrowserTestBase;
use Drupal\simpletest\ContentTypeCreationTrait;
use Drupal\simpletest\NodeCreationTrait;

/**
* Tests the complex widget.
*
* @group og
*/
class OgComplexWidgetTest extends BrowserTestBase {

use ContentTypeCreationTrait;
use NodeCreationTrait;

/**
* {@inheritdoc}
*/
public static $modules = ['node', 'og'];

/**
* {@inheritdoc}
*/
function setUp() {
parent::setUp();

// Create a "group" node type and turn it into a group type.
$this->createContentType(['type' => 'group']);
Og::groupManager()->addGroup('node', 'group');

// Add a group audience field to the "post" node type, turning it into a
// group content type.
$this->createContentType(['type' => 'post']);
Og::createField(OgGroupAudienceHelper::DEFAULT_FIELD, 'node', 'post');
}

/**
* Tests the "Other Groups" field.
*/
function testOtherGroups() {
$admin_user = $this->drupalCreateUser(['administer group', 'access content', 'create post content']);
$group_owner = $this->drupalCreateUser(['access content', 'create post content']);

// Create a group content type owned by the group owner.
$settings = [
'type' => 'group',
'uid' => $group_owner->id(),
];
$group = $this->createNode($settings);

// Log in as administrator.
$this->drupalLogin($admin_user);

// Create a new post in the group by using the "Other Groups" field in the
// UI.
$edit = [
'title[0][value]' => "Group owner's post.",
'other_groups[0][target_id]' => "group ({$group->id()})",
];
$this->drupalGet('node/add/post');
$this->submitForm($edit, 'Save');
$this->assertSession()->statusCodeEquals(200);

// Retrieve the post that was created from the database.
/** @var QueryInterface $query */
$query = $this->container->get('entity.query')->get('node');
$result = $query
->condition('type', 'post')
->range(0, 1)
->sort('nid', 'DESC')
->execute();
$post_nid = reset($result);

/** @var NodeInterface $post */
$post = Node::load($post_nid);

// Check that the post references the group correctly.
/** @var OgMembershipReferenceItemList $reference_list */
$reference_list = $post->get(OgGroupAudienceHelper::DEFAULT_FIELD);
$this->assertEquals(1, $reference_list->count(), 'There is 1 reference after adding a group to the "Other Groups" field.');
$this->assertEquals($group->id(), $reference_list->first()->getValue()['target_id'], 'The "Other Groups" field references the correct group.');
}

}