<?php
namespace Croogo\Acl\Model\Behavior;
use Cake\Cache\Cache;
use Cake\Event\Event;
use Cake\ORM\Behavior;
use Cake\ORM\Entity;
use Cake\ORM\Query;
use Cake\Utility\Hash;
use Cake\Utility\Text;
/**
* RoleAro Behavior
*
* @category Behavior
* @package Croogo.Acl.Model.Behavior
* @version 1.0
* @author Fahad Ibnay Heylaal <contact@fahad19.com>
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
* @link http://www.croogo.org
*/
class RoleAroBehavior extends Behavior
{
protected $_defaultConfig = [
'implementedFinders' => [
'roleHierarchy' => 'findRoleHierarchy',
],
];
/**
* parentNode
*
* @param Model $model
* @return $mixed
*/
public function parentNode($model)
{
if (!$model->id && empty($model->data)) {
return null;
} else {
$id = $model->id ? $model->id : $model->data[$model->alias]['id'];
$aro = $model->Aro->node('first', [
'conditions' => [
'model' => $model->alias,
'foreign_key' => $id,
]
]);
if (!empty($aro['Aro']['foreign_key'])) {
$return = [
$aro[0]['Aro']['model'] => [
'id' => $aro['Aro']['foreign_key']
]];
} else {
$return = null;
}
return $return;
}
}
/**
* afterSave
*
* Update the corresponding ACO record alias
*/
public function afterSave(Event $event, Entity $entity)
{
$model = $event->getSubject();
$ref = ['model' => $model->getAlias(), 'foreign_key' => $entity->id];
$aro = $model->node($ref)->firstOrFail();
if (!empty($entity->alias)) {
$aro->alias = sprintf(
'Role-%s',
Text::slug($entity->alias)
);
}
if (!empty($entity->parent_id)) {
$aro->parent_id = $entity->parent_id;
}
$model->Aro->save($aro);
Cache::clearGroup('acl', 'permissions');
}
/**
* findRoleHierarchy
*
* binds Aro model so that it gets retrieved during admin_[edit|add].
*/
public function findRoleHierarchy(Query $query, array $options)
{
$alias = $this->_table->getAlias();
$primaryKey = $this->_table->getPrimaryKey();
$this->_table->hasOne('ParentAro', [
'className' => 'Aros',
'bindingKey' => 'id',
'foreignKey' => 'foreign_key',
'conditions' => [
'model' => $alias,
],
]);
$query
->contain('ParentAro')
->formatResults(function ($resultSet) {
foreach ($resultSet as $result) {
if ($result->parent_aro) {
$result->parent_id = $result->parent_aro->parent_id;
$result->lft = $result->parent_aro->lft;
$result->rght = $result->parent_aro->rght;
$result->setDirty('parent_id', false);
$result->setDirty('lft', false);
$result->setDirty('rght', false);
$result->unsetProperty('parent_aro');
}
}
return $resultSet;
});
return $query;
}
/**
* afterFind
*
* When 'parent_id' is present, copy its value from Aro to Role data.
*/
public function afterFind(Model $model, $results, $primary = false)
{
if (!empty($results[0]['Aro']['parent_id'])) {
$results[0][$model->alias]['parent_id'] = $results[0]['Aro']['parent_id'];
return $results;
}
}
/**
* Retrieve a list of allowed parent roles
*
* @paraam integer $roleId
* @param int $id Role id
* @return array list of allowable parent roles in 'list' format
*/
public function allowedParents($id = null)
{
if (!$this->_table->behaviors()->has('Croogo/Core.Aliasable')) {
$this->_table->addBehavior('Croogo/Core.Aliasable');
}
if ($id == $this->_table->byAlias('public')) {
return [];
}
$adminRoleId = $this->_table->byAlias('superadmin');
$excludes = Hash::filter(array_values([$adminRoleId, $id]));
$conditions = [
'NOT' => [$this->_table->aliasField('id') . ' IN' => $excludes],
];
return $this->_table->find('list')
->where($conditions)
->toArray();
}
/**
* afterDelete
*/
public function afterDelete(Event $event)
{
Cache::clearGroup('acl', 'permissions');
}
}