Skip to content

Commit

Permalink
Fix Role::withCount if belongsToMany declared (#2280)
Browse files Browse the repository at this point in the history
* Fix Role::withCount if belongsToMany declared

fixes #2277
  • Loading branch information
xenaio-daniil authored Feb 8, 2023
1 parent 3859d92 commit b881a07
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 5 deletions.
6 changes: 1 addition & 5 deletions src/Models/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ public function __construct(array $attributes = [])
parent::__construct($attributes);

$this->guarded[] = $this->primaryKey;
}

public function getTable()
{
return config('permission.table_names.roles', parent::getTable());
$this->table = config('permission.table_names.roles', parent::getTable());
}

public static function create(array $attributes = [])
Expand Down
39 changes: 39 additions & 0 deletions tests/RoleWithNesting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Spatie\Permission\Test;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

/**
* @property Collection $parents
* @property Collection $children
*/
class RoleWithNesting extends \Spatie\Permission\Models\Role
{
const HIERARCHY_TABLE = 'roles_hierarchy';

/**
* @return BelongsToMany
*/
public function parents()
{
return $this->belongsToMany(
static::class,
static::HIERARCHY_TABLE,
'child_id',
'parent_id');
}

/**
* @return BelongsToMany
*/
public function children(): BelongsToMany
{
return $this->belongsToMany(
static::class,
static::HIERARCHY_TABLE,
'parent_id',
'child_id');
}
}
90 changes: 90 additions & 0 deletions tests/RoleWithNestingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Spatie\Permission\Test;

class RoleWithNestingTest extends TestCase
{
private static $old_migration;
/**
* @var RoleWithNesting[]
*/
protected $parent_roles=[];
/**
* @var RoleWithNesting[]
*/
protected $child_roles=[];

public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
self::$old_migration = self::$migration;
self::$migration = self::getMigration();
}

public function setUp(): void
{
parent::setUp();
$this->parent_roles = [];
$this->child_roles = [];
$this->parent_roles["has_no_children"] = RoleWithNesting::create(["name"=>"has_no_children"]);
$this->parent_roles["has_1_child"] = RoleWithNesting::create(["name"=>"has_1_child"]);
$this->parent_roles["has_3_children"] = RoleWithNesting::create(["name"=>"has_3_children"]);

$this->child_roles["has_no_parents"] = RoleWithNesting::create(["name"=>"has_no_parents"]);
$this->child_roles["has_1_parent"] = RoleWithNesting::create(["name"=>"has_1_parent"]);
$this->child_roles["has_2_parents"] = RoleWithNesting::create(["name"=>"has_2_parents"]);
$this->child_roles["third_child"] = RoleWithNesting::create(["name"=>"third_child"]);

$this->parent_roles["has_1_child"]->children()->attach($this->child_roles["has_2_parents"]);
$this->parent_roles["has_3_children"]->children()->attach($this->child_roles["has_2_parents"]);
$this->parent_roles["has_3_children"]->children()->attach($this->child_roles["has_1_parent"]);
$this->parent_roles["has_3_children"]->children()->attach($this->child_roles["third_child"]);
}

public static function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
self::$migration = self::$old_migration;
}

protected function getEnvironmentSetUp($app)
{
parent::getEnvironmentSetUp($app);
$app['config']->set('permission.models.role', RoleWithNesting::class);
$app['config']->set('permission.table_names.roles', "nesting_role");
}

protected static function getMigration()
{
require_once __DIR__."/customMigrations/roles_with_nesting_migration.php.stub";
return new \CreatePermissionTablesWithNested();
}

/** @test
* @dataProvider roles_list
*/
public function it_returns_correct_withCount_of_nested_roles($role_group,$index,$relation,$expectedCount)
{
$role = $this->$role_group[$index];
$count_field_name = sprintf("%s_count", $relation);

$actualCount = intval(RoleWithNesting::query()->withCount($relation)->find($role->id)->$count_field_name);

$this->assertSame(
$expectedCount,
$actualCount,
sprintf("%s expects %d %s, %d found",$role->name,$expectedCount,$relation,$actualCount)
);
}

public function roles_list(){
return [
["parent_roles","has_no_children","children",0],
["parent_roles","has_1_child","children",1],
["parent_roles","has_3_children","children",3],
["child_roles","has_no_parents","parents",0],
["child_roles","has_1_parent","parents",1],
["child_roles","has_2_parents","parents",2],
];
}
}
40 changes: 40 additions & 0 deletions tests/customMigrations/roles_with_nesting_migration.php.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\PermissionRegistrar;

require_once __DIR__."/../../database/migrations/create_permission_tables.php.stub";
class CreatePermissionTablesWithNested extends CreatePermissionTables
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
parent::up();
$tableNames = config('permission.table_names');

Schema::create(\Spatie\Permission\Test\RoleWithNesting::HIERARCHY_TABLE,function(Blueprint $table) use ($tableNames){
$table->id();
$table->bigInteger("parent_id", false, true);
$table->bigInteger("child_id", false, true);
$table->foreign("parent_id")->references("id")->on($tableNames['roles']);
$table->foreign("child_id")->references("id")->on($tableNames['roles']);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
parent::down();
Schema::drop(\Spatie\Permission\Test\RoleWithNesting::HIERARCHY_TABLE);
}
}

0 comments on commit b881a07

Please sign in to comment.