Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor \Drupal\og_ui\BundleFormAlter #734

Open
wants to merge 15 commits into
base: 8.x-1.x
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ mysql:
services:
- mysql

addons:
chrome: stable

cache:
directories:
- $HOME/.composer/cache/files
Expand Down Expand Up @@ -78,4 +81,7 @@ before_script:
# Export database variable for kernel tests.
- export SIMPLETEST_DB=mysql://root:@127.0.0.1/og

# Start chromedriver for JS tests.
- chromedriver --port=4444 &

script: DRUPAL_DIR=$DRUPAL_DIR MODULE_DIR=$MODULE_DIR $MODULE_DIR/scripts/travis-ci/run-test.sh $TEST_SUITE
3 changes: 1 addition & 2 deletions og_ui/og_ui.module
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\og\Og;
use Drupal\og\OgGroupAudienceHelperInterface;
use Drupal\og_ui\BundleFormAlter;

/**
* Implements hook_form_alter().
Expand All @@ -31,7 +30,7 @@ function og_ui_form_alter(array &$form, FormStateInterface $form_state, $form_id
return;
}

(new BundleFormAlter($entity_type))->formAlter($form, $form_state);
\Drupal::service('og_ui.bundle_entity_form_alter')->formAlter($form, $form_state);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions og_ui/og_ui.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
og_ui.bundle_entity_form_alter:
class: Drupal\og_ui\BundleEntityFormAlter
arguments: ['@entity_type.manager', '@entity_type.bundle.info', '@og.group_type_manager']
136 changes: 72 additions & 64 deletions og_ui/src/BundleFormAlter.php → og_ui/src/BundleEntityFormAlter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,81 @@

namespace Drupal\og_ui;

use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\BundleEntityFormBase;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\RevisionableEntityBundleInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\field\Entity\FieldConfig;
use Drupal\og\Og;
use Drupal\og\GroupTypeManagerInterface;
use Drupal\og\OgGroupAudienceHelperInterface;

/**
* Helper for og_ui_form_alter().
*/
class BundleFormAlter {
class BundleEntityFormAlter {

/**
* Entity type definition.
* The entity type manager.
*
* @var \Drupal\Core\Entity\ContentEntityTypeInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $definition;
protected EntityTypeManagerInterface $entityTypeManager;

/**
* The entity bundle.
* The entity type bundle info service.
*
* @var string
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected $bundle;
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo;

/**
* The bundle label.
* The group type manager.
*
* @var string
* @var \Drupal\og\GroupTypeManagerInterface
*/
protected $bundleLabel;
protected GroupTypeManagerInterface $groupTypeManager;

/**
* The entity type ID.
* Constructs a new BundleEntityFormAlter service.
*
* @var string
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
* The entity type bundle info service.
* @param \Drupal\og\GroupTypeManagerInterface $groupTypeManager
* The group type manager.
*/
protected $entityTypeId;

/**
* The form entity which has been used for populating form element defaults.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;

/**
* Construct a BundleFormAlter object.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
*/
public function __construct(EntityInterface $entity) {
$this->entity = $entity;
public function __construct(EntityTypeManagerInterface $entityTypeManager, EntityTypeBundleInfoInterface $entityTypeBundleInfo, GroupTypeManagerInterface $groupTypeManager) {
$this->entityTypeManager = $entityTypeManager;
$this->entityTypeBundleInfo = $entityTypeBundleInfo;
$this->groupTypeManager = $groupTypeManager;
}

/**
* This is a helper for og_ui_form_alter().
* Alters bundle entity forms.
*
* @param array $form
* The form variable.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*
* @see og_ui_form_alter()
*/
public function formAlter(array &$form, FormStateInterface $form_state) {
$this->prepare($form, $form_state);
public function formAlter(array &$form, FormStateInterface $form_state): void {
if (!$form_state->getFormObject() instanceof BundleEntityFormBase) {
throw new \InvalidArgumentException('Passed in form is not a bundle entity form.');
}
static::prepare($form);
$this->addGroupType($form, $form_state);
$this->addGroupContent($form, $form_state);
}

/**
* AJAX callback displaying the target bundles select box.
*/
public function ajaxCallback(array $form, FormStateInterface $form_state) {
public static function ajaxCallback(array $form, FormStateInterface $form_state): array {
return $form['og']['og_target_bundles'];
}

Expand All @@ -88,18 +87,8 @@ public function ajaxCallback(array $form, FormStateInterface $form_state) {
*
* @param array $form
* The form variable.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*/
protected function prepare(array &$form, FormStateInterface $form_state) {
// Example: article.
$this->bundle = $this->entity->id();
// Example: Article.
$this->bundleLabel = Unicode::lcfirst($this->entity->label());
$this->definition = $this->entity->getEntityType();
// Example: node.
$this->entityTypeId = $this->definition->getBundleOf();

protected static function prepare(array &$form): void {
$form['og'] = [
'#type' => 'details',
'#title' => new TranslatableMarkup('Organic groups'),
Expand All @@ -110,48 +99,54 @@ protected function prepare(array &$form, FormStateInterface $form_state) {
}

/**
* Adds the "is group?" checkbox.
* Adds the section to mark the entity type as a group type.
*/
protected function addGroupType(array &$form, FormStateInterface $form_state) {
if ($this->entity->isNew()) {
protected function addGroupType(array &$form, FormStateInterface $form_state): void {
$bundle = static::getEntityBundle($form_state);
if ($bundle->isNew()) {
$description = new TranslatableMarkup('Every entity in this bundle is a group which can contain entities and can have members.');
$default_value = FALSE;
}
else {
$description = new TranslatableMarkup('Every "%bundle" is a group which can contain entities and can have members.', [
'%bundle' => Unicode::lcfirst($this->bundleLabel),
'%bundle' => $bundle->label(),
]);
$default_value = $this->groupTypeManager->isGroup($bundle->getEntityType()->getBundleOf(), $bundle->id());
}
$form['og']['og_is_group'] = [
'#type' => 'checkbox',
'#title' => new TranslatableMarkup('Group'),
'#default_value' => Og::isGroup($this->entityTypeId, $this->bundle),
'#default_value' => $default_value,
'#description' => $description,
];
}

/**
* Adds the "is group content?" checkbox and target settings elements.
* Adds the section to configure the entity type as group content.
*/
protected function addGroupContent(array &$form, FormStateInterface $form_state) {
protected function addGroupContent(array &$form, FormStateInterface $form_state): void {
$bundle = static::getEntityBundle($form_state);
$entity_type_id = $bundle->getEntityType()->getBundleOf();

// Get the stored config from the default group audience field if it exists.
$field = FieldConfig::loadByName($this->entityTypeId, $this->bundle, OgGroupAudienceHelperInterface::DEFAULT_FIELD);
$field = FieldConfig::loadByName($entity_type_id, $bundle->id(), OgGroupAudienceHelperInterface::DEFAULT_FIELD);
$handler_settings = $field ? $field->getSetting('handler_settings') : [];

// Compile a list of group entity types and bundles.
$target_types = [];
$target_bundles = [];
foreach (Og::groupTypeManager()->getGroupMap() as $entity_type => $bundles) {
$target_types[$entity_type] = \Drupal::entityTypeManager()->getDefinition($entity_type)->getLabel();
$bundle_info = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type);
foreach ($bundles as $bundle) {
$target_bundles[$entity_type][$bundle] = $bundle_info[$bundle]['label'];
foreach ($this->groupTypeManager->getGroupMap() as $entity_type => $bundle_ids) {
$target_types[$entity_type] = $this->entityTypeManager->getDefinition($entity_type)->getLabel();
$bundle_info = $this->entityTypeBundleInfo->getBundleInfo($entity_type);
foreach ($bundle_ids as $bundle_id) {
$target_bundles[$entity_type][$bundle_id] = $bundle_info[$bundle_id]['label'];
}
}

$form['og']['og_group_content_bundle'] = [
'#type' => 'checkbox',
'#title' => new TranslatableMarkup('Group content'),
'#default_value' => $this->bundle ? Og::isGroupContent($this->entityTypeId, $this->bundle) : FALSE,
'#default_value' => !$bundle->isNew() && $this->groupTypeManager->isGroupContent($entity_type_id, $bundle->id()),
'#description' => empty($target_bundles) ? new TranslatableMarkup('There are no group bundles defined.') : '',
];

Expand All @@ -172,7 +167,7 @@ protected function addGroupContent(array &$form, FormStateInterface $form_state)
'#default_value' => $target_type_default,
'#description' => new TranslatableMarkup('The entity type that can be referenced through this field.'),
'#ajax' => [
'callback' => [$this, 'ajaxCallback'],
'callback' => [static::class, 'ajaxCallback'],
'wrapper' => 'og-settings-wrapper',
],
'#states' => [
Expand All @@ -198,7 +193,7 @@ protected function addGroupContent(array &$form, FormStateInterface $form_state)
],
],
];
$form['#validate'][] = [get_class($this), 'validateTargetBundleElement'];
$form['#validate'][] = [static::class, 'validateTargetBundleElement'];
}
else {
// Don't show the settings, as there might be multiple OG audience fields
Expand All @@ -210,7 +205,7 @@ protected function addGroupContent(array &$form, FormStateInterface $form_state)
/**
* Form validate handler.
*/
public static function validateTargetBundleElement(array &$form, FormStateInterface $form_state) {
public static function validateTargetBundleElement(array &$form, FormStateInterface $form_state): void {
// If no checkboxes were checked for 'og_target_bundles', store NULL ("all
// bundles are referenceable") rather than empty array ("no bundle is
// referenceable" - typically happens when all referenceable bundles have
Expand All @@ -220,4 +215,17 @@ public static function validateTargetBundleElement(array &$form, FormStateInterf
}
}

/**
* Retrieves the entity type bundle object from the given form state.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* A bundle entity form.
*
* @return \Drupal\Core\Entity\RevisionableEntityBundleInterface
* The bundle.
*/
protected static function getEntityBundle(FormStateInterface $form_state): RevisionableEntityBundleInterface {
return $form_state->getFormObject()->getEntity();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@

namespace Drupal\Tests\og_ui\Functional;

use Drupal\Core\Form\FormState;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Tests\BrowserTestBase;
use Drupal\node\Entity\NodeType;
use Drupal\og\Og;
use Drupal\og_ui\BundleFormAlter;

/**
* Test making a bundle a group and a group content.
*
* @group og
*/
class BundleFormAlterTest extends BrowserTestBase {
class BundleEntityFormAlterTest extends BrowserTestBase {

/**
* {@inheritdoc}
Expand Down Expand Up @@ -113,29 +109,6 @@ public function testCreate() {
$this->assertSession()->fieldNotExists('og_group_content_bundle');
}

/**
* Tests AJAX behavior for selecting group content entity types and bundles.
*/
public function testGroupContentAjax() {
// Create two group bundles of different entity types.
NodeType::create(['name' => 'group node', 'type' => 'group'])->save();
Og::groupTypeManager()->addGroup('node', 'group');
Og::groupTypeManager()->addGroup('entity_test', 'entity_test');

// BrowserTestBase doesn't support JavaScript yet. Replace the following
// unit test with a functional test once JavaScript support is added.
// @see https://www.drupal.org/node/2469713
$form = [];
$form_state = new FormState();
// Set the form state as if the 'entity_test' option was chosen with AJAX.
$form_state->setValue('og_target_type', 'entity_test');
$entity = $this->entityTypeManager->getStorage('node_type')->create([]);
(new BundleFormAlter($entity))->formAlter($form, $form_state);

// Check that the target bundles are set to the test entity bundle.
$this->assertEquals(['entity_test' => 'Entity Test Bundle'], $form['og']['og_target_bundles']['#options']);
}

/**
* Checks whether the target bundles in the group content are as expected.
*
Expand Down
Loading