Skip to content
This repository has been archived by the owner on Aug 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #420 from Gizra/store-bundle-in-membership
Browse files Browse the repository at this point in the history
Performance: Store the group bundle in the membership entity
  • Loading branch information
pfrenssen authored Aug 7, 2018
2 parents 15182de + 08e4216 commit bb8dc16
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 4 deletions.
60 changes: 60 additions & 0 deletions og.install
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,70 @@
* Install, update, and uninstall functions for the Organic groups module.
*/

use Drupal\Core\Field\BaseFieldDefinition;

/**
* Implements hook_uninstall().
*/
function og_uninstall() {
\Drupal::queue('og_orphaned_group_content')->deleteQueue();
\Drupal::queue('og_orphaned_group_content_cron')->deleteQueue();
}

/**
* Add a base field to store the group bundle in memberships.
*/
function og_update_8001(&$sandbox) {
$storage = \Drupal::entityTypeManager()->getStorage('og_membership');

if (!isset($sandbox['total'])) {
$storage_definition = BaseFieldDefinition::create('string')
->setLabel(t('Group bundle ID'))
->setDescription(t('The bundle ID of the group.'));
\Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('entity_bundle', 'og_membership', 'og', $storage_definition);

$sandbox['#finished'] = 0;
$sandbox['current'] = 0;
$sandbox['total'] = $storage->getQuery()->count()->execute();
$sandbox['batch_size'] = 500;
}

// Update the existing memberships to include the group bundle ID.
$membership_ids = $storage->getQuery()
->range($sandbox['current'], $sandbox['batch_size'])
->sort('id')
->execute();

/** @var \Drupal\og\Entity\OgMembership $membership */
foreach ($storage->loadMultiple($membership_ids) as $membership) {
$group = $membership->getGroup();
if (!empty($group)) {
$membership->set('entity_bundle', $group->bundle());
$membership->save();
}
else {
// The membership is for a group that no longer exists. We cannot no
// longer retrieve the group bundle ID so the membership cannot be
// updated. Delete the membership since it is invalid, and inform the
// user.
\Drupal::logger('og')->warning('Deleted orphaned membership with ID @id since the group it refers to no longer exists.', [
'@id' => $membership->id(),
]);
$membership->delete();
}
}

$sandbox['current'] += $sandbox['batch_size'];
if ($sandbox['current'] >= $sandbox['total']) {
$sandbox['current'] = $sandbox['total'];
}
$sandbox['#finished'] = $sandbox['current'] / $sandbox['total'];

$message = t('Processed @current of @total memberships (@percentage% complete)', [
'@current' => $sandbox['current'],
'@total' => $sandbox['total'],
'@percentage' => number_format($sandbox['#finished'] * 100, 2),
]);

return $message;
}
41 changes: 37 additions & 4 deletions src/Entity/OgMembership.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public function setOwnerId($uid) {
*/
public function setGroup(EntityInterface $group) {
$this->set('entity_type', $group->getEntityTypeId());
$this->set('entity_bundle', $group->bundle());
$this->set('entity_id', $group->id());
return $this;
}
Expand All @@ -137,13 +138,41 @@ public function getGroupEntityType() {
return $this->get('entity_type')->value;
}

/**
* {@inheritdoc}
*/
public function getGroupBundle() {
return $this->get('entity_bundle')->value;
}

/**
* {@inheritdoc}
*/
public function getGroupId() {
return $this->get('entity_id')->value;
}

/**
* Checks if a group has already been populated on the membership.
*
* The group is required for a membership, so it is always present if a
* membership has been saved. This is intended for internal use to verify if
* a group is present when methods are called on a membership that is possibly
* still under construction.
*
* For performance reasons this avoids loading the full group entity just for
* this purpose, and relies only on the fact that the data for the entity is
* populated in the relevant fields. This should give us the same indication,
* but with a lower performance cost, especially for users that are a member
* of a large number of groups.
*
* @return bool
* Whether or not the group is already present.
*/
protected function hasGroup() {
return !empty($this->get('entity_type')->value) && !empty($this->get('entity_bundle')->value) && !empty($this->get('entity_id')->value);
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -223,9 +252,9 @@ public function getRoles() {

// Add the member role. This is only possible if a group has been set on the
// membership.
if ($group = $this->getGroup()) {
if ($this->hasGroup()) {
$roles = [
OgRole::getRole($this->getGroupEntityType(), $group->bundle(), OgRoleInterface::AUTHENTICATED),
OgRole::getRole($this->getGroupEntityType(), $this->getGroupBundle(), OgRoleInterface::AUTHENTICATED),
];
}
$roles = array_merge($roles, $this->get('roles')->referencedEntities());
Expand Down Expand Up @@ -335,9 +364,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setLabel(t('Group entity type'))
->setDescription(t('The entity type of the group.'));

$fields['entity_bundle'] = BaseFieldDefinition::create('string')
->setLabel(t('Group bundle ID'))
->setDescription(t('The bundle ID of the group.'));

$fields['entity_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Group entity id'))
->setDescription(t("The entity ID of the group."));
->setLabel(t('Group entity ID'))
->setDescription(t('The entity ID of the group.'));

$fields['state'] = BaseFieldDefinition::create('string')
->setLabel(t('State'))
Expand Down
8 changes: 8 additions & 0 deletions src/OgMembershipInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ public function getGroup();
*/
public function getGroupEntityType();

/**
* Gets the group entity bundle.
*
* @return string
* The bundle.
*/
public function getGroupBundle();

/**
* Gets the group entity ID.
*
Expand Down
18 changes: 18 additions & 0 deletions tests/src/Kernel/Entity/OgMembershipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,24 @@ public function testGetGroup() {
$this->assertEquals($this->group->id(), $membership->getGroup()->id());
}

/**
* Tests getting the bundle of the group that is associated with a membership.
*
* @covers ::getGroupBundle
*/
public function testGetGroupBundle() {
$membership = OgMembership::create();

// When no group has been set yet, the method should return NULL.
$this->assertNull($membership->getGroupBundle());

// Set a group.
$membership->setGroup($this->group);

// Now the group bundle should be returned.
$this->assertEquals($this->group->bundle(), $membership->getGroupBundle());
}

/**
* Tests that membership has "member" role when roles are retrieved.
*
Expand Down

0 comments on commit bb8dc16

Please sign in to comment.