Skip to content

Commit

Permalink
Add events to the attaching/detaching methods.
Browse files Browse the repository at this point in the history
- Fix #151
  • Loading branch information
santigarcor committed Sep 24, 2017
1 parent d4c0242 commit 6342410
Show file tree
Hide file tree
Showing 6 changed files with 423 additions and 7 deletions.
107 changes: 107 additions & 0 deletions src/Traits/LaratrustHasEvents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Laratrust\Traits;

trait LaratrustHasEvents
{
/**
* Fire the given event for the model.
*
* @param string $event
* @param array $payload
* @return mixed
*/
protected function fireLaratrustEvent($event, array $payload)
{
if (! isset(static::$dispatcher)) {
return true;
}

return static::$dispatcher->fire(
"laratrust.{$event}: ".static::class,
$payload
);
}

/**
* Register a laratrust event with the dispatcher.
*
* @param string $event
* @param \Closure|string $callback
* @return void
*/
public static function registerLaratrustEvent($event, $callback)
{
if (isset(static::$dispatcher)) {
$name = static::class;

static::$dispatcher->listen("laratrust.{$event}: {$name}", $callback);
}
}

/**
* Register a role attached laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function roleAttached($callback)
{
static::registerLaratrustEvent('role.attached', $callback);
}

/**
* Register a role detached laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function roleDetached($callback)
{
static::registerLaratrustEvent('role.detached', $callback);
}

/**
* Register a permission attached laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function permissionAttached($callback)
{
static::registerLaratrustEvent('permission.attached', $callback);
}

/**
* Register a permission detached laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function permissionDetached($callback)
{
static::registerLaratrustEvent('permission.detached', $callback);
}

/**
* Register a role synced laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function roleSynced($callback)
{
static::registerLaratrustEvent('role.synced', $callback);
}

/**
* Register a permission synced laratrust event with the dispatcher.
*
* @param \Closure|string $callback
* @return void
*/
public static function permissionSynced($callback)
{
static::registerLaratrustEvent('permission.synced', $callback);
}
}
19 changes: 16 additions & 3 deletions src/Traits/LaratrustRoleTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
trait LaratrustRoleTrait
{
use LaratrustDynamicUserRelationsCalls;
use LaratrustHasEvents;

/**
* Tries to return all the cached permissions of the role.
Expand Down Expand Up @@ -147,9 +148,15 @@ public function hasPermission($permission, $requireAll = false)
*/
public function syncPermissions($permissions)
{
// If the permissions is empty it will delete all associations.
$mappedPermissions = [];

foreach ($permissions as $permission) {
$mappedPermissions[] = Helper::getIdFor($permission, $permission);
}

$changes = $this->permissions()->sync($permissions);
$this->flushCache();
$this->fireLaratrustEvent("permission.synced", [$this, $changes]);

return $this;
}
Expand All @@ -162,8 +169,11 @@ public function syncPermissions($permissions)
*/
public function attachPermission($permission)
{
$this->permissions()->attach(Helper::getIdFor($permission, 'permission'));
$permission = Helper::getIdFor($permission, 'permission');

$this->permissions()->attach($permission);
$this->flushCache();
$this->fireLaratrustEvent("permission.attached", [$this, $permission]);

return $this;
}
Expand All @@ -176,8 +186,11 @@ public function attachPermission($permission)
*/
public function detachPermission($permission)
{
$this->permissions()->detach(Helper::getIdFor($permission, 'permission'));
$permission = Helper::getIdFor($permission, 'permission');

$this->permissions()->detach($permission);
$this->flushCache();
$this->fireLaratrustEvent("permission.detached", [$this, $permission]);

return $this;
}
Expand Down
12 changes: 8 additions & 4 deletions src/Traits/LaratrustUserTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

trait LaratrustUserTrait
{
use LaratrustHasEvents;

/**
* Tries to return all the cached roles of the user.
* If it can't bring the roles from the cache,
Expand Down Expand Up @@ -365,6 +367,7 @@ private function attachModel($relationship, $objectType, $object, $team)
$attributes
);
$this->flushCache();
$this->fireLaratrustEvent("{$objectType}.attached", [$this, $object, $team]);

return $this;
}
Expand Down Expand Up @@ -393,11 +396,11 @@ private function detachModel($relationship, $objectType, $object, $team)
);
}

$relationshipQuery->detach(
Helper::getIdFor($object, $objectType)
);
$object = Helper::getIdFor($object, $objectType);
$relationshipQuery->detach($object);

$this->flushCache();
$this->fireLaratrustEvent("{$objectType}.detached", [$this, $object, $team]);

return $this;
}
Expand All @@ -422,9 +425,10 @@ private function syncModels($relationship, $objectType, $objects, $team, $detach
$relationshipToSync->wherePivot(Helper::teamForeignKey(), $team);
}

$relationshipToSync->sync($mappedObjects, $detaching);
$result = $relationshipToSync->sync($mappedObjects, $detaching);

$this->flushCache();
$this->fireLaratrustEvent("{$objectType}.synced", [$this, $result, $team]);

return $this;
}
Expand Down
69 changes: 69 additions & 0 deletions tests/LaratrustEventsTestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Laratrust\Tests;

use Mockery as m;

class LaratrustEventsTestCase extends LaratrustTestCase
{
protected $dispatcher;

public function setUp()
{
parent::setUp();

$this->migrate();
$this->dispatcher = m::mock('\Illuminate\Events\Dispatcher')->makePartial();
$this->app['config']->set('laratrust.use_teams', true);
}

/**
* Listen to a Laratrust event.
*
* @param string $event
* @return void
*/
protected function listenTo($event, $modelClass)
{
$method = \Illuminate\Support\Str::camel(str_replace('.', ' ', $event));

$modelClass::{$method}(function ($user, $roleId) {
return 'test';
});
}

/**
* Assert that the dispatcher has listeners for the given event.
*
* @param string $event
* @return void
*/
protected function assertHasListenersFor($event, $modelClass)
{
$eventName = "laratrust.{$event}: {$modelClass}";
$dispatcher = $modelClass::getEventDispatcher();

$this->assertTrue($dispatcher->hasListeners($eventName));
$this->assertCount(1, $dispatcher->getListeners($eventName));
$this->assertEquals('test', $dispatcher->fire($eventName, ['user', 'an_id', null])[0]);
}

/**
* Assert the dispatcher fires the fire event with the given data.
*
* @param string $event
* @param array $payload
* @param string $model
* @return void
*/
protected function dispatcherShouldFire($event, array $payload, $modelClass)
{
$this->dispatcher->shouldReceive('fire')
->with(
"laratrust.{$event}: {$modelClass}",
$payload
)
->andReturn(null)
->once()->ordered();
}
}
82 changes: 82 additions & 0 deletions tests/LaratrustRoleEventsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Laratrust\Tests;

use Mockery as m;
use Laratrust\Tests\Models\Role;
use Laratrust\Tests\Models\User;
use Laratrust\Tests\LaratrustTestCase;
use Laratrust\Tests\Models\Permission;

class LaratrustRoleEventsTest extends LaratrustEventsTestCase
{
protected $role;

public function setUp()
{
parent::setUp();
$this->role = Role::create(['name' => 'role']);

}

public function testCanListenToThePermissionAttachedEvent()
{
$this->listenTo('permission.attached', Role::class);

$this->assertHasListenersFor('permission.attached', Role::class);
}

public function testCanListenToThePermissionDetachedEvent()
{
$this->listenTo('permission.detached', Role::class);

$this->assertHasListenersFor('permission.detached', Role::class);
}

public function testCanListenToThePermissionSyncedEvent()
{
$this->listenTo('permission.synced', Role::class);

$this->assertHasListenersFor('permission.synced', Role::class);
}

public function testAnEventIsFiredWhenPermissionIsAttachedToRole()
{
$permission = Permission::create(['name' => 'permission']);

Role::setEventDispatcher($this->dispatcher);

$this->dispatcherShouldFire('permission.attached', [$this->role, $permission->id], Role::class);

$this->role->attachPermission($permission);
}

public function testAnEventIsFiredWhenPermissionIsDetachedFromRole()
{
$permission = Permission::create(['name' => 'permission']);
$this->role->attachPermission($permission);

Role::setEventDispatcher($this->dispatcher);

$this->dispatcherShouldFire('permission.detached', [$this->role, $permission->id], Role::class);

$this->role->detachPermission($permission);
}

public function testAnEventIsFiredWhenPermissionsAreSynced()
{
$permission = Permission::create(['name' => 'permission']);
$this->role->attachPermission($permission);

Role::setEventDispatcher($this->dispatcher);

$this->dispatcherShouldFire('permission.synced', [
$this->role,
[
'attached' => [], 'detached' => [$permission->id], 'updated' => [],
]
], Role::class);

$this->role->syncPermissions([]);
}
}

0 comments on commit 6342410

Please sign in to comment.