Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c3aaed4
Prove the bug
claudiu-cristea Sep 5, 2022
a805f97
Fix spelling error
claudiu-cristea Sep 5, 2022
20092d7
Properly merge permission arrays
claudiu-cristea Sep 5, 2022
0d53e71
Fix phpcs issues
MPParsley Sep 5, 2022
a808daa
Merge pull request #748 from claudiu-cristea/array_merge-permissions
MPParsley Sep 5, 2022
c8c303b
fix machine name mismatch in link template vs route
jludwig Oct 13, 2022
912b5c7
Run Rector + metadata update.
claudiu-cristea Nov 19, 2022
c94dea3
Run PHP CS only once
claudiu-cristea Nov 19, 2022
f021a99
Be nice with Travis
claudiu-cristea Nov 19, 2022
5550aa8
Add back code sniffer test
claudiu-cristea Nov 19, 2022
ce8b578
Fix tests
claudiu-cristea Nov 19, 2022
801f3f0
Use the 'use' statement
claudiu-cristea Nov 19, 2022
3c7946e
Expectation come first
claudiu-cristea Nov 19, 2022
8c3feb9
Testing modules
claudiu-cristea Nov 19, 2022
c5aa0d0
Follow the parent
claudiu-cristea Nov 19, 2022
6adea6e
Testing modules should be protected
claudiu-cristea Nov 19, 2022
cbcf77c
Fix og_ui metadata
claudiu-cristea Nov 19, 2022
2d138df
Compatibility with parent
claudiu-cristea Nov 19, 2022
81229f4
More D10 conversions
claudiu-cristea Nov 19, 2022
c5c3d2f
Typo
claudiu-cristea Nov 19, 2022
7744526
Entity query access
claudiu-cristea Nov 19, 2022
77f0ac0
PHP CS
claudiu-cristea Nov 19, 2022
62a4613
Provide the block label
claudiu-cristea Nov 19, 2022
404391a
Site is installed in a subdirectory
claudiu-cristea Nov 20, 2022
95f3f41
EntityTest's label is 'name'
claudiu-cristea Nov 20, 2022
37234a2
Fix base path issue
claudiu-cristea Nov 20, 2022
4303a9b
Cast NULL to empty string
claudiu-cristea Nov 20, 2022
213a9c1
Merge pull request #754 from claudiu-cristea/d10
MPParsley Nov 21, 2022
f7418a2
Merge pull request #751 from jludwig/8.x-1.x
MPParsley Nov 21, 2022
a4997b4
Add support for Drupal 9.5
MPParsley Apr 3, 2023
e319e0b
Merge pull request #757 from Gizra/feature/drupal9.5
MPParsley Apr 3, 2023
2782f4c
Prevent fatal error in membersip create access check
pwolanin Apr 7, 2023
1734f0f
Merge pull request #759 from pwolanin/issue-758-access-controller
amitaibu Sep 27, 2023
556227a
PHPCS fixes (#763)
dipakmdhrm Sep 27, 2023
7e069fd
MembershipManager::getMembership() performance improvement (#762)
lozeone Sep 27, 2023
eb70175
Merge remote-tracking branch 'do/8.x-1.x' into 196-redux-rebased
damienmckenna Apr 30, 2024
a6ebd5b
Missing accessCheck() calls on entity queries.
damienmckenna Apr 30, 2024
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
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,27 @@ language: php
php:
- '7.4'
- '8.0'
- nightly
- '8.1'

env:
global:
- COMPOSER_MEMORY_LIMIT=2G
matrix:
- TEST_SUITE=9.3.x
- TEST_SUITE=9.4.x
- TEST_SUITE=9.5.x
- TEST_SUITE=10.0.x
- TEST_SUITE=PHP_CodeSniffer

# Only run the coding standards check once.
matrix:
exclude:
- php: 7.4
env: TEST_SUITE=PHP_CodeSniffer
- php: 7.4
env: TEST_SUITE=10.0.x
- php: 8.0
env: TEST_SUITE=PHP_CodeSniffer
- php: 8.0
env: TEST_SUITE=10.0.x

mysql:
database: og
Expand Down Expand Up @@ -65,7 +69,7 @@ before_script:

# Install Composer dependencies for core. Skip this for the coding standards test.
- test ${TEST_SUITE} == "PHP_CodeSniffer" || composer install --working-dir=$DRUPAL_DIR

# Start a web server on port 8888 in the background.
- test ${TEST_SUITE} == "PHP_CodeSniffer" || nohup php -S localhost:8888 --docroot $DRUPAL_DIR > /dev/null 2>&1 &

Expand Down
6 changes: 1 addition & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,9 @@
"homepage": "https://www.drupal.org/u/pfrenssen"
}
],
"require": {
"php": "^7.4 || ^8",
"drupal/core": "^9.3"
},
"require-dev": {
"drupal/coder": "^8.3.16",
"phpunit/phpunit": "^7 || ^8"
"phpunit/phpunit": "^7 || ^8 || ^9"
},
"minimum-stability": "RC",
"config": {
Expand Down
2 changes: 1 addition & 1 deletion docs/access.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ members:

```php
<?php

// phpcs:ignoreFile
namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\StringTranslation\StringTranslationTrait;
Expand Down
3 changes: 1 addition & 2 deletions og.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ name: Organic Groups
description: API to allow associating content with groups.
package: Organic Groups

core_version_requirement: ^9
core_version_requirement: ^9 || ^10
type: module
php: 7.1

dependencies:
- drupal:options
Expand Down
3 changes: 2 additions & 1 deletion og.install
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function og_update_8001(&$sandbox) {
$sandbox['#finished'] = 0;
$sandbox['batch_size'] = 500;
$sandbox['current'] = 0;
$sandbox['total'] = $storage->getQuery()->count()->execute();
$sandbox['total'] = $storage->getQuery()->accessCheck()->count()->execute();

if (!$sandbox['total']) {
$sandbox['#finished'] = 1;
Expand All @@ -43,6 +43,7 @@ function og_update_8001(&$sandbox) {

// Update the existing memberships to include the group bundle ID.
$membership_ids = $storage->getQuery()
->accessCheck()
->range($sandbox['current'], $sandbox['batch_size'])
->sort('id')
->execute();
Expand Down
4 changes: 2 additions & 2 deletions og_ui/og_ui.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ description: User interface for Organic Groups.
package: Organic Groups

type: module
core_version_requirement: ^9
core_version_requirement: ^9 || ^10

dependencies:
- og
- og:og

configure: og_ui.admin_index
2 changes: 1 addition & 1 deletion og_ui/src/BundleFormAlter.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ 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->bundleLabel = Unicode::lcfirst((string) $this->entity->label());
$this->definition = $this->entity->getEntityType();
// Example: node.
$this->entityTypeId = $this->definition->getBundleOf();
Expand Down
4 changes: 2 additions & 2 deletions og_ui/tests/src/Functional/BundleFormAlterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

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;
use Drupal\Tests\BrowserTestBase;

/**
* Test making a bundle a group and a group content.
Expand All @@ -21,7 +21,7 @@ class BundleFormAlterTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['block_content', 'entity_test', 'node', 'og_ui'];
protected static $modules = ['block_content', 'entity_test', 'node', 'og_ui'];

/**
* {@inheritdoc}
Expand Down
2 changes: 1 addition & 1 deletion src/Controller/OgAdminRoutesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function overview(RouteMatchInterface $route_match) {
$content = [];

$event = new OgAdminRoutesEvent();
$event = $this->eventDispatcher->dispatch(OgAdminRoutesEventInterface::EVENT_NAME, $event);
$event = $this->eventDispatcher->dispatch($event, OgAdminRoutesEventInterface::EVENT_NAME);

foreach ($event->getRoutes($entity_type_id) as $name => $info) {
$route_name = "entity.$entity_type_id.og_admin_routes.$name";
Expand Down
2 changes: 1 addition & 1 deletion src/Controller/OgAutocompleteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityAutocompleteMatcher;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
use Drupal\Core\PrivateKey;
use Drupal\Core\Site\Settings;
Expand Down
4 changes: 2 additions & 2 deletions src/Entity/OgMembership.php
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,8 @@ public function preSave(EntityStorageInterface $storage) {
}

// Check for an existing membership.
$query = \Drupal::entityQuery('og_membership');
$query
$query = \Drupal::entityQuery('og_membership')
->accessCheck()
->condition('uid', $uid)
->condition('entity_id', $entity_id)
->condition('entity_type', $this->get('entity_type')->value);
Expand Down
4 changes: 2 additions & 2 deletions src/Entity/OgMembershipType.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
* "description"
* },
* links = {
* "edit-form" = "/admin/structure/membership-types/manage/{membership_type}",
* "delete-form" = "/admin/structure/membership-types/manage/{membership_type}/delete",
* "edit-form" = "/admin/structure/membership-types/manage/{og_membership_type}",
* "delete-form" = "/admin/structure/membership-types/manage/{og_membership_type}/delete",
* "collection" = "/admin/structure/membership-types",
* }
* )
Expand Down
9 changes: 9 additions & 0 deletions src/Entity/OgRole.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,16 @@ protected function ogAccess() {
* {@inheritdoc}
*/
public function calculateDependencies() {
// The parent method is checking for the existence of each role-assigned
// permission. But in OG this isn't mandatory. Backup the permissions before
// calling the parent method and avoid performing the check.
// @see https://www.drupal.org/node/3193348
// @todo Consider decoupling 'og_role' from 'role' entity config and
// implementing the missing methods in 'og_role'.
$permissions = $this->permissions;
$this->permissions = [];
parent::calculateDependencies();
$this->permissions = $permissions;

// Create a dependency on the group bundle.
$bundle_config_dependency = \Drupal::entityTypeManager()->getDefinition($this->getGroupType())->getBundleConfigDependency($this->getGroupBundle());
Expand Down
4 changes: 3 additions & 1 deletion src/Entity/OgRoleListBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ public function __construct(EntityTypeInterface $entity_type, EntityStorageInter
* {@inheritdoc}
*/
protected function getEntityIds() {
$query = $this->getStorage()->getQuery()
$query = $this->getStorage()
->getQuery()
->accessCheck()
->condition('group_type', $this->groupType, '=')
->condition('group_bundle', $this->groupBundle, '=')
->sort($this->entityType->getKey('weight'));
Expand Down
2 changes: 1 addition & 1 deletion src/Event/AccessEventBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\Event;

/**
* Base class for OG access events.
Expand Down
11 changes: 6 additions & 5 deletions src/Event/DefaultRoleEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Drupal\og\Event;

use Drupal\og\Entity\OgRole;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\Event;

/**
* Event that is fired when default roles are compiled.
Expand Down Expand Up @@ -97,14 +97,15 @@ public function hasRole($name) {
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetGet($key) {
return $this->getRole($key);
}

/**
* {@inheritdoc}
*/
public function offsetSet($key, $role) {
public function offsetSet($key, $role): void {
$this->validate($role);
if ($role->getName() !== $key) {
throw new \InvalidArgumentException('The key and the "name" property of the role should be identical.');
Expand All @@ -115,21 +116,21 @@ public function offsetSet($key, $role) {
/**
* {@inheritdoc}
*/
public function offsetUnset($key) {
public function offsetUnset($key): void {
$this->deleteRole($key);
}

/**
* {@inheritdoc}
*/
public function offsetExists($key) {
public function offsetExists($key): bool {
return $this->hasRole($key);
}

/**
* {@inheritdoc}
*/
public function getIterator() {
public function getIterator(): \Traversable {
return new \ArrayIterator($this->roles);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Event/GroupCreationEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Drupal\og\Event;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\Event;

/**
* The group creation event.
Expand Down
2 changes: 1 addition & 1 deletion src/Event/OgAdminRoutesEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Drupal\Component\Utility\NestedArray;
use Drupal\og\OgAccess;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\Event;

/**
* Event that is fired when OG admin routes are being compiled.
Expand Down
2 changes: 1 addition & 1 deletion src/Event/PermissionEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Drupal\og\GroupContentOperationPermission;
use Drupal\og\PermissionInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\Event;

/**
* Event that is fired when OG permissions are compiled.
Expand Down
2 changes: 1 addition & 1 deletion src/EventSubscriber/OgEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ protected function getDefaultEntityOperationPermissions(array $group_content_bun

foreach ($group_content_bundle_ids as $group_content_entity_type_id => $bundle_ids) {
foreach ($bundle_ids as $bundle_id) {
$permissions += $this->generateEntityOperationPermissionList($group_content_entity_type_id, $bundle_id);
$permissions = array_merge($permissions, $this->generateEntityOperationPermissionList($group_content_entity_type_id, $bundle_id));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/GroupTypeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ public function addGroup($entity_type_id, $bundle_id) {

// Trigger an event upon the new group creation.
$event = new GroupCreationEvent($entity_type_id, $bundle_id);
$this->eventDispatcher->dispatch(GroupCreationEventInterface::EVENT_NAME, $event);
$this->eventDispatcher->dispatch($event, GroupCreationEventInterface::EVENT_NAME);

$this->ogRoleManager->createPerBundleRoles($entity_type_id, $bundle_id);
$this->refreshGroupMap();
Expand Down
39 changes: 35 additions & 4 deletions src/MembershipManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public function getMemberships($user_id, array $states = [OgMembershipInterface:
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->accessCheck()
->condition('uid', $user_id)
->condition('state', $states, 'IN');

Expand All @@ -132,10 +133,36 @@ public function getMembership(EntityInterface $group, $user_id, array $states =
$user_id = $user_id->id();
}

foreach ($this->getMemberships($user_id, $states) as $membership) {
if ($membership->getGroupEntityType() === $group->getEntityTypeId() && $membership->getGroupId() === $group->id()) {
return $membership;
}
// When an empty array is passed, retrieve memberships with all possible
// states.
$states = $this->prepareConditionArray($states, OgMembership::ALL_STATES);

$cid = [
__METHOD__,
$group->getEntityTypeId(),
$group->id(),
$user_id,
implode('|', $states),
];
$cid = implode(':', $cid);

// Use cached result if it exists.
$membership_ids = $this->staticCache->get($cid)->data ?? [];
if (!$membership_ids) {
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->accessCheck()
->condition('entity_type', $group->getEntityTypeId())
->condition('entity_id', $group->id())
->condition('uid', $user_id)
->condition('state', $states, 'IN');

$membership_ids = $query->execute();
$this->cacheMembershipIds($cid, $membership_ids);
}
if ($memberships = $this->loadMemberships($membership_ids)) {
return reset($memberships);
}

// No membership matches the request.
Expand Down Expand Up @@ -185,6 +212,7 @@ public function getGroupMembershipCount(EntityInterface $group, array $states =
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->accessCheck()
->condition('entity_id', $group->id());

if ($states) {
Expand Down Expand Up @@ -231,6 +259,7 @@ public function getGroupMembershipIdsByRoleNames(EntityInterface $group, array $
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->accessCheck()
->condition('entity_type', $entity_type_id)
->condition('entity_id', $group->id())
->condition('state', $states, 'IN');
Expand Down Expand Up @@ -389,6 +418,7 @@ public function getGroupContentIds(EntityInterface $entity, array $entity_types
$query = $this->entityTypeManager
->getStorage('field_storage_config')
->getQuery()
->accessCheck()
->condition('type', OgGroupAudienceHelperInterface::GROUP_REFERENCE);

// Optionally filter group content entity types.
Expand Down Expand Up @@ -418,6 +448,7 @@ public function getGroupContentIds(EntityInterface $entity, array $entity_types
$results = $this->entityTypeManager
->getStorage($group_content_entity_type)
->getQuery()
->accessCheck()
->condition($field->getName() . '.target_id', $entity->id())
->execute();

Expand Down
2 changes: 1 addition & 1 deletion src/OgAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public function userAccessGroupContentEntityOperation(string $operation, EntityI
$event->addCacheContexts(['user']);
}

$this->dispatcher->dispatch(GroupContentEntityOperationAccessEvent::EVENT_NAME, $event);
$this->dispatcher->dispatch($event, GroupContentEntityOperationAccessEvent::EVENT_NAME);

return $event->getAccessResult();
}
Expand Down
Loading