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

Fun: UserPermissions facade #7491

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
Draft
19 changes: 19 additions & 0 deletions src/Framework/Permissions/Contracts/UserPermissionsInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Give\Framework\Permissions\Contracts;

/**
* @unreleased
*/
interface UserPermissionsInterface
{
/**
* @return string
*/
public static function getType(): string;

/**
* @unreleased
*/
public function can(string $capability): bool;
}
16 changes: 16 additions & 0 deletions src/Framework/Permissions/DonationFormPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Give\Framework\Permissions;
/**
* @unreleased
*/
class DonationFormPermissions extends UserPermission
{
/**
* @unreleased
*/
public static function getType(): string
{
return 'give_form';
}
}
17 changes: 17 additions & 0 deletions src/Framework/Permissions/DonationPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Give\Framework\Permissions;

/**
* @unreleased
*/
class DonationPermissions extends UserPermission
{
/**
* @unreleased
*/
public static function getType(): string
{
return 'give_payment';
}
}
17 changes: 17 additions & 0 deletions src/Framework/Permissions/DonorPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Give\Framework\Permissions;

/**
* @unreleased
*/
class DonorPermissions extends UserPermission
{
/**
* @unreleased
*/
public static function getType(): string
{
return 'give_payment';
}
}
23 changes: 23 additions & 0 deletions src/Framework/Permissions/Facades/UserPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Give\Framework\Permissions\Facades;

use Give\Framework\Permissions\DonationFormPermissions;
use Give\Framework\Permissions\DonationPermissions;
use Give\Framework\Permissions\DonorPermissions;
use Give\Framework\Support\Facades\Facade;

/**
* @unreleased
*
* @method static DonationFormPermissions donationForms()
* @method static DonationPermissions donations()
* @method static DonorPermissions donors()
*/
class UserPermissions extends Facade
{
protected function getFacadeAccessor(): string
{
return UserPermissionsFacade::class;
}
}
41 changes: 41 additions & 0 deletions src/Framework/Permissions/Facades/UserPermissionsFacade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Give\Framework\Permissions\Facades;

use Give\Framework\Permissions\DonationFormPermissions;
use Give\Framework\Permissions\DonationPermissions;
use Give\Framework\Permissions\DonorPermissions;

/**
* This is a facade for interacting with WP and GiveWP permissions.
*
* @see https://wordpress.org/documentation/article/roles-and-capabilities/
*
* @unreleased
*/
class UserPermissionsFacade
{
/**
* @unreleased
*/
public function donationForms(): DonationFormPermissions
{
return new DonationFormPermissions();
}

/**
* @unreleased
*/
public function donations(): DonationPermissions
{
return new DonationPermissions();
}

/**
* @unreleased
*/
public function donors(): DonorPermissions
{
return new DonorPermissions();
}
}
15 changes: 15 additions & 0 deletions src/Framework/Permissions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Permissions Facade

The Permissions Facade is a class that allows you to check if a user has a specific capability or role. It is a wrapper around the WordPress `current_user_can()` function.

Example:

```php
use Give\Framework\Permissions\Permissions;

if (!UserPermissions::donationForms()->can('edit')) {
throw new Exception('You do not have permission to edit donation forms.');
}
```
};
```
67 changes: 67 additions & 0 deletions src/Framework/Permissions/UserPermission.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Give\Framework\Permissions;

abstract class UserPermission implements Contracts\UserPermissionsInterface
{
/**
* @unreleased
*/
public function can(string $capability): bool
{
switch ($capability) {
case 'delete':
$capability = $this->getCapability('delete');
break;
case 'read':
case 'view':
case 'create':
case 'update':
case 'edit':
$capability = $this->getCapability('edit');
break;
}

return current_user_can($capability);
}

/**
* @unreleased
*/
protected function getCapability(string $cap): string
{
$caps = $this->getCapabilities($this::getType());

return $caps[$cap];
}

/**
* @unreleased
*/
protected function getCapabilities(string $type): array
{
return [
// Post type.
"edit" => "edit_{$type}s",
"edit_others" => "edit_others_{$type}s",
"publish" => "publish_{$type}s",
"read_private" => "read_private_{$type}s",
"delete" => "delete_{$type}s",
"delete_private" => "delete_private_{$type}s",
"delete_published" => "delete_published_{$type}s",
"delete_others" => "delete_others_{$type}s",
"edit_private" => "edit_private_{$type}s",
"edit_published" => "edit_published_{$type}s",

// Terms / taxonomies.
"manage_terms" => "manage_{$type}_terms",
"edit_terms" => "edit_{$type}_terms",
"delete_terms" => "delete_{$type}_terms",
"assign_terms" => "assign_{$type}_terms",

// Custom capabilities.
"view_stats" => "view_{$type}_stats",
"import" => "import_{$type}s"
];
}
}
28 changes: 28 additions & 0 deletions tests/Unit/Framework/Permissions/Facades/TestUserPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Give\Tests\Unit\Framework\Permissions\Facades;

use Give\Framework\Permissions\DonationFormPermissions;
use Give\Framework\Permissions\Facades\UserPermissions;
use Give\Tests\TestCase;
use Give\Tests\TestTraits\RefreshDatabase;

/**
* @unreleased
*/
final class TestUserPermissions extends TestCase
{
use RefreshDatabase;

/**
* @unreleased
*/
public function testDonationForms(): void
{
$this->assertInstanceOf(
DonationFormPermissions::class,
UserPermissions::donationForms()
);
}

}
111 changes: 111 additions & 0 deletions tests/Unit/Framework/Permissions/TestDonationFormsPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

namespace Give\Tests\Unit\Framework\Permissions;

use Give\Framework\Permissions\DonationFormPermissions;
use Give\Tests\TestCase;
use Give\Tests\TestTraits\RefreshDatabase;

/**
* @unreleased
*/
final class TestDonationFormsPermissions extends TestCase
{
use RefreshDatabase;

/**
* @unreleased
* @dataProvider canTrueProvider
*/
public function testCanShouldBeTrue(string $role, string $capability): void
{
$user = self::factory()->user->create_and_get();
$user->set_role($role);

wp_set_current_user($user->ID);

$this->assertTrue(
(new DonationFormPermissions())->can($capability)
);
}

/**
* @unreleased
* @dataProvider canFalseProvider
*/
public function testCanShouldBeFalse(string $role, string $capability): void
{
$user = self::factory()->user->create_and_get();
$user->set_role($role);

wp_set_current_user($user->ID);

$this->assertFalse(
(new DonationFormPermissions())->can($capability)
);
}


/**
* @unreleased
*
* @return array<int, array<mixed, bool>>
*/
public function canTrueProvider(): array
{
return [
// true
['give_worker', 'create'],
['give_worker', 'read'],
['give_worker', 'update'],
['give_worker', 'edit'],

['give_manager', 'create'],
['give_manager', 'read'],
['give_manager', 'update'],
['give_manager', 'edit'],
['give_manager', 'delete'],

['give_accountant', 'create'],
['give_accountant', 'read'],
['give_accountant', 'update'],
['give_accountant', 'edit'],
['give_accountant', 'read_private_give_forms'],

['administrator', 'create'],
['administrator', 'read'],
['administrator', 'update'],
['administrator', 'edit'],
['administrator', 'delete'],
];
}

/**
* @unreleased
*/
public function canFalseProvider(): array
{
return [
// false
['give_accountant', 'delete'],

['give_donor', 'create'],
['give_donor', 'read'],
['give_donor', 'update'],
['give_donor', 'edit'],
['give_donor', 'delete'],

['give_subscriber', 'create'],
['give_subscriber', 'read'],
['give_subscriber', 'update'],
['give_subscriber', 'edit'],
['give_subscriber', 'delete'],

['subscriber', 'create'],
['subscriber', 'read'],
['subscriber', 'update'],
['subscriber', 'edit'],
['subscriber', 'delete'],
];
}
}
Loading