first commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager;
|
||||
|
||||
/**
|
||||
* Class Dot
|
||||
*
|
||||
* @package SelvinOrtiz\Dot
|
||||
*
|
||||
* https://github.com/selvinortiz/dot
|
||||
*/
|
||||
class Dot
|
||||
{
|
||||
/**
|
||||
* Returns whether or not the $key exists within $arr
|
||||
*
|
||||
* @param array $arr
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($arr, $key)
|
||||
{
|
||||
if (strpos($key, '.') !== false && count(($keys = explode('.', $key)))) {
|
||||
foreach ($keys as $key) {
|
||||
if (!array_key_exists($key, $arr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr = $arr[$key];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return array_key_exists($key, $arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns he value of $key if found in $arr or $default
|
||||
*
|
||||
* @param array $arr
|
||||
* @param string $key
|
||||
* @param null|mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($arr, $key, $default = null)
|
||||
{
|
||||
if (strpos($key, '.') !== false && count(($keys = explode('.', $key)))) {
|
||||
foreach ($keys as $key) {
|
||||
if (!array_key_exists($key, $arr)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$arr = $arr[$key];
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
return array_key_exists($key, $arr) ? $arr[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the $value identified by $key inside $arr
|
||||
*
|
||||
* @param array &$arr
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function set(array &$arr, $key, $value)
|
||||
{
|
||||
if (strpos($key, '.') !== false && ($keys = explode('.', $key)) && count($keys)) {
|
||||
while (count($keys) > 1) {
|
||||
$key = array_shift($keys);
|
||||
|
||||
if (!isset($arr[$key]) || !is_array($arr[$key])) {
|
||||
$arr[$key] = [];
|
||||
}
|
||||
|
||||
$arr = &$arr[$key];
|
||||
}
|
||||
|
||||
$arr[array_shift($keys)] = $value;
|
||||
} else {
|
||||
$arr[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a $key and its value from the $arr
|
||||
*
|
||||
* @param array &$arr
|
||||
* @param string $key
|
||||
*/
|
||||
public static function delete(array &$arr, $key)
|
||||
{
|
||||
if (strpos($key, '.') !== false && ($keys = explode('.', $key)) && count($keys)) {
|
||||
while (count($keys) > 1) {
|
||||
$arr = &$arr[array_shift($keys)];
|
||||
}
|
||||
|
||||
unset($arr[array_shift($keys)]);
|
||||
} else {
|
||||
unset($arr[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
// Copied from Grav source because it has issues which has been fixed here
|
||||
|
||||
namespace AdminAddonUserManager;
|
||||
|
||||
use Grav\Common\Data\Blueprints;
|
||||
use Grav\Common\Data\Data;
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Utils;
|
||||
|
||||
class Group extends Data {
|
||||
|
||||
/**
|
||||
* Get the groups list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function groups() {
|
||||
$groups = Grav::instance()['config']->get('groups', []);
|
||||
|
||||
$blueprints = new Blueprints;
|
||||
$blueprint = $blueprints->get('user/group');
|
||||
foreach ($groups as $groupname => &$content) {
|
||||
if (!isset($content['groupname'])) {
|
||||
$content['groupname'] = $groupname;
|
||||
}
|
||||
$content = new Group($content, $blueprint);
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function groupNames() {
|
||||
$groups = [];
|
||||
|
||||
foreach(Grav::instance()['config']->get('groups', []) as $groupname => $group) {
|
||||
$groups[$groupname] = isset($group['readableName']) ? $group['readableName'] : $groupname;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a group exists
|
||||
*
|
||||
* @param string $groupname
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function groupExists($groupname) {
|
||||
return isset(self::groups()[$groupname]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a group by name
|
||||
*
|
||||
* @param string $groupname
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function load($groupname) {
|
||||
if (self::groupExists($groupname)) {
|
||||
$group = self::groups()[$groupname];
|
||||
} else {
|
||||
$blueprints = new Blueprints;
|
||||
$blueprint = $blueprints->get('user/group');
|
||||
$content = ['groupname' => $groupname];
|
||||
$group = new Group($content, $blueprint);
|
||||
}
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a group
|
||||
*/
|
||||
public function save() {
|
||||
$grav = Grav::instance();
|
||||
$config = $grav['config'];
|
||||
|
||||
$blueprints = new Blueprints;
|
||||
$blueprint = $blueprints->get('user/group');
|
||||
|
||||
$fields = $blueprint->fields();
|
||||
|
||||
$config->set("groups.$this->groupname", []);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ($field['type'] == 'text') {
|
||||
$value = $field['name'];
|
||||
if (isset($this->items[$value])) {
|
||||
$config->set("groups.$this->groupname.$value", $this->items[$value]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($field['type'] == 'array' || $field['type'] == 'permissions') {
|
||||
$value = $field['name'];
|
||||
$arrayValues = Utils::getDotNotation($this->items, $field['name']);
|
||||
|
||||
if ($arrayValues) {
|
||||
foreach ($arrayValues as $arrayIndex => $arrayValue) {
|
||||
$config->set("groups.$this->groupname.$value.$arrayIndex", $arrayValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$type = 'groups';
|
||||
$obj = new Data($config->get($type), $blueprint);
|
||||
$file = CompiledYamlFile::instance($grav['locator']->findResource('config://') . DS . "{$type}.yaml");
|
||||
$obj->file($file);
|
||||
$obj->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a group
|
||||
*
|
||||
* @param string $groupname
|
||||
*
|
||||
* @return bool True if the action was performed
|
||||
*/
|
||||
public static function remove($groupname) {
|
||||
$grav = Grav::instance();
|
||||
$config = $grav['config'];
|
||||
$blueprints = new Blueprints;
|
||||
$blueprint = $blueprints->get('user/group');
|
||||
|
||||
$groups = $config->get('groups', []);
|
||||
if (!isset($groups[$groupname])) {
|
||||
return false;
|
||||
}
|
||||
unset($groups[$groupname]);
|
||||
$config->set('groups', $groups);
|
||||
|
||||
$type = 'groups';
|
||||
$obj = new Data($config->get($type), $blueprint);
|
||||
$file = CompiledYamlFile::instance($grav['locator']->findResource("config://{$type}.yaml"));
|
||||
$obj->file($file);
|
||||
$obj->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function authorize($access) {
|
||||
if (empty($this->items)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($this->items['access'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$val = Utils::getDotNotation($this->items['access'], $access);
|
||||
|
||||
return Utils::isPositive($val) === true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager\Groups;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Plugin\AdminAddonUserManagerPlugin;
|
||||
use Grav\Common\Assets;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use AdminAddonUserManager\Manager as IManager;
|
||||
use AdminAddonUserManager\Pagination\ArrayPagination;
|
||||
use \Grav\Common\Utils;
|
||||
use AdminAddonUserManager\Group;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use \Grav\Common\User\User;
|
||||
use \AdminAddonUserManager\Users\Manager as UsersManager;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
|
||||
|
||||
class Manager implements IManager, EventSubscriberInterface {
|
||||
|
||||
private $grav;
|
||||
private $plugin;
|
||||
private $adminController;
|
||||
|
||||
public function __construct(Grav $grav, AdminAddonUserManagerPlugin $plugin) {
|
||||
$this->grav = $grav;
|
||||
$this->plugin = $plugin;
|
||||
|
||||
$this->grav['events']->addSubscriber($this);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents() {
|
||||
return [
|
||||
'onAdminControllerInit' => ['onAdminControllerInit', 0],
|
||||
'onAdminData' => ['onAdminData', 0]
|
||||
];
|
||||
}
|
||||
|
||||
public function onAdminControllerInit($e) {
|
||||
$controller = $e['controller'];
|
||||
$this->adminController = $controller;
|
||||
}
|
||||
|
||||
public function onAdminData($e) {
|
||||
$type = $e['type'];
|
||||
|
||||
if (preg_match('|group-manager|', $type) && ($group = $this->grav['uri']->param('name', false))) {
|
||||
$obj = Group::load($group);
|
||||
$post = $this->adminController->data;
|
||||
if (isset($post['users'])) {
|
||||
$usersInGroup = $post['users'];
|
||||
unset($post['users']);
|
||||
} else {
|
||||
$usersInGroup = [];
|
||||
}
|
||||
$obj->merge($post);
|
||||
$e['data_type'] = $obj;
|
||||
|
||||
foreach (UsersManager::$instance->users() as $u) {
|
||||
$groups = $u->get('groups', []);
|
||||
if (in_array($u['username'], $usersInGroup)) {
|
||||
if (!in_array($obj['groupname'], $groups)) {
|
||||
$u['groups'] = array_merge($groups, [$obj['groupname']]);
|
||||
$u->save();
|
||||
}
|
||||
} else {
|
||||
if (in_array($obj['groupname'], $groups)) {
|
||||
$u['groups'] = array_diff($groups, [$obj['groupname']]);
|
||||
if (empty($u['groups'])) {
|
||||
unset($u['groups']);
|
||||
}
|
||||
$u->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required permission to access the manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequiredPermission() {
|
||||
return $this->plugin->name . '.groups';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the manager
|
||||
* It will be accessible at this path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocation() {
|
||||
return 'group-manager';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin hooked nav array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNav() {
|
||||
return [
|
||||
'label' => 'PLUGIN_ADMIN_ADDON_USER_MANAGER.GROUP_MANAGER',
|
||||
'location' => $this->getLocation(),
|
||||
'icon' => 'fa-group',
|
||||
'authorize' => $this->getRequiredPermission(),
|
||||
'badge' => [
|
||||
'count' => count($this->groups())
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialiaze required assets
|
||||
*
|
||||
* @param \Grav\Common\Assets $assets
|
||||
* @return void
|
||||
*/
|
||||
public function initializeAssets(Assets $assets) {
|
||||
$this->grav['assets']->addCss('plugin://' . $this->plugin->name . '/assets/groups/style.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle task requests
|
||||
*
|
||||
* @param \RocketTheme\Toolbox\Event\Event $event
|
||||
* @return boolean
|
||||
*/
|
||||
public function handleTask(Event $event) {
|
||||
$method = $event['method'];
|
||||
|
||||
if ($method === 'taskGroupDelete' && ($group = $this->grav['uri']->param('name', false))) {
|
||||
Group::remove($group);
|
||||
$this->grav->redirect($this->grav['uri']->url($this->getLocation()));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic of the manager goes here
|
||||
*
|
||||
* @return array The array to be merged to Twig vars
|
||||
*/
|
||||
public function handleRequest() {
|
||||
$vars = [];
|
||||
|
||||
$twig = $this->grav['twig'];
|
||||
$uri = $this->grav['uri'];
|
||||
|
||||
// Bulk actions
|
||||
if (isset($_POST['selected'])) {
|
||||
$groupnames = $_POST['selected'];
|
||||
|
||||
if (isset($_POST['bulk_delete'])) {
|
||||
// Bulk delete groups
|
||||
foreach ($groupnames as $groupname) {
|
||||
Group::remove($groupname);
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
}
|
||||
}
|
||||
|
||||
$group = $this->grav['uri']->param('name', false);
|
||||
|
||||
if ($group) {
|
||||
$vars['exists'] = Group::groupExists($group);
|
||||
$vars['group'] = $group = Group::load($group);
|
||||
$users = [];
|
||||
foreach (UsersManager::$instance->users() as $u) {
|
||||
if (in_array($group['groupname'], $u->get('groups', []))) {
|
||||
$users[] = $u->username;
|
||||
}
|
||||
}
|
||||
$group['users'] = $users;
|
||||
} else {
|
||||
$vars['fields'] = $this->plugin->getModalsConfiguration()['add_group']['fields'];
|
||||
$vars['bulkFields'] = $this->plugin->getModalsConfiguration()['bulk_group']['fields'];
|
||||
|
||||
$groups = $this->groups();
|
||||
foreach ($groups as &$group) {
|
||||
$group['users'] = 0;
|
||||
|
||||
foreach (UsersManager::$instance->users() as $u) {
|
||||
if (in_array($group['groupname'], $u->get('groups', []))) {
|
||||
$group['users'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering
|
||||
$filterException = false;
|
||||
$filter = (empty($_GET['filter'])) ? '' : $_GET['filter'];
|
||||
$vars['filter'] = $filter;
|
||||
if ($filter) {
|
||||
try {
|
||||
$language = new ExpressionLanguage();
|
||||
$language->addFunction(ExpressionFunction::fromPhp('count'));
|
||||
foreach ($groups as $k => $group) {
|
||||
if (!$language->evaluate($_GET['filter'], ['group' => $group])) {
|
||||
unset($groups[$k]);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$vars['filterException'] = $exception;
|
||||
$filterException = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($filterException) {
|
||||
$groups = [];
|
||||
}
|
||||
|
||||
// Pagination
|
||||
$perPage = $this->plugin->getPluginConfigValue('pagination.per_page', 10);
|
||||
$pagination = new ArrayPagination($groups, $perPage);
|
||||
$pagination->paginate($uri->param('page'));
|
||||
|
||||
$vars['pagination'] = [
|
||||
'current' => $pagination->getCurrentPage(),
|
||||
'count' => $pagination->getPagesCount(),
|
||||
'total' => $pagination->getRowsCount(),
|
||||
'perPage' => $pagination->getRowsPerPage(),
|
||||
'startOffset' => $pagination->getStartOffset(),
|
||||
'endOffset' => $pagination->getEndOffset()
|
||||
];
|
||||
$groups = $pagination->getPaginatedRows();
|
||||
|
||||
$vars['groups'] = $groups;
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function groups() {
|
||||
return Group::groups();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Plugin\AdminAddonUserManagerPlugin;
|
||||
use Grav\Common\Assets;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
interface Manager {
|
||||
|
||||
public function __construct(Grav $grav, AdminAddonUserManagerPlugin $plugin);
|
||||
|
||||
/**
|
||||
* Returns the required permission to access the manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequiredPermission();
|
||||
|
||||
/**
|
||||
* Returns the location of the manager
|
||||
* It will be accessible at this path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocation();
|
||||
|
||||
/**
|
||||
* Returns the plugin hooked nav array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNav();
|
||||
|
||||
/**
|
||||
* Initialiaze required assets
|
||||
*
|
||||
* @param \Grav\Common\Assets $assets
|
||||
* @return void
|
||||
*/
|
||||
public function initializeAssets(Assets $assets);
|
||||
|
||||
/**
|
||||
* Handle task requests
|
||||
*
|
||||
* @param \RocketTheme\Toolbox\Event\Event $event
|
||||
* @return void
|
||||
*/
|
||||
public function handleTask(Event $event);
|
||||
|
||||
/**
|
||||
* Logic of the manager goes here
|
||||
*
|
||||
* @return array The array to be merged to Twig vars
|
||||
*/
|
||||
public function handleRequest();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager\Pagination;
|
||||
|
||||
use AdminAddonUserManager\Pagination\Pagination;
|
||||
|
||||
class ArrayPagination implements Pagination {
|
||||
|
||||
protected $data;
|
||||
protected $rowsPerPage;
|
||||
protected $page;
|
||||
|
||||
private $rowsCount = null;
|
||||
private $slicedData = null;
|
||||
|
||||
public function __construct($data, $rowsPerPage = 10) {
|
||||
$this->data = $data;
|
||||
$this->rowsPerPage = $rowsPerPage;
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
public function paginate($page) {
|
||||
if ($page > $this->getPagesCount()) {
|
||||
$page = $page;
|
||||
}
|
||||
|
||||
if ($page < 1) {
|
||||
$page = 1;
|
||||
}
|
||||
|
||||
$this->page = $page;
|
||||
|
||||
$this->slicedData = null;
|
||||
}
|
||||
|
||||
public function getRowsPerPage() {
|
||||
return $this->rowsPerPage;
|
||||
}
|
||||
|
||||
public function getRowsCount() {
|
||||
if ($this->rowsCount !== null) {
|
||||
return $this->rowsCount;
|
||||
}
|
||||
|
||||
return $this->rowsCount = count($this->data);
|
||||
}
|
||||
|
||||
public function getCurrentPage() {
|
||||
return $this->page;
|
||||
}
|
||||
|
||||
public function getPagesCount() {
|
||||
return ceil($this->getRowsCount() / $this->getRowsPerPage());
|
||||
}
|
||||
|
||||
public function getStartOffset() {
|
||||
return ($this->getCurrentPage() - 1) * $this->getRowsPerPage();
|
||||
}
|
||||
|
||||
public function getEndOffset() {
|
||||
$endOffset = $this->getStartOffset() + $this->getRowsPerPage();
|
||||
|
||||
if ($endOffset > $this->getRowsCount()) {
|
||||
$endOffset = $this->getRowsCount();
|
||||
}
|
||||
|
||||
return $endOffset;
|
||||
}
|
||||
|
||||
public function getPaginatedRowsCount() {
|
||||
return $this->getEndOffset() - $this->getStartOffset();
|
||||
}
|
||||
|
||||
public function getPaginatedRows() {
|
||||
if ($this->slicedData !== null) {
|
||||
return $this->slicedData;
|
||||
}
|
||||
|
||||
return $this->slicedData = array_slice($this->data, $this->getStartOffset(), $this->getRowsPerPage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager\Pagination;
|
||||
|
||||
interface Pagination {
|
||||
|
||||
public function paginate($page);
|
||||
|
||||
public function getRowsPerPage();
|
||||
public function getRowsCount();
|
||||
public function getCurrentPage();
|
||||
public function getPagesCount();
|
||||
public function getStartOffset();
|
||||
public function getEndOffset();
|
||||
public function getPaginatedRowsCount();
|
||||
public function getPaginatedRows();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager\Users;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Plugin\AdminAddonUserManagerPlugin;
|
||||
use Grav\Common\Assets;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use AdminAddonUserManager\Manager as IManager;
|
||||
use Grav\Common\User\User;
|
||||
use Grav\Common\Data\Blueprints;
|
||||
|
||||
class ExpertManager implements IManager {
|
||||
|
||||
private $grav;
|
||||
private $plugin;
|
||||
|
||||
public static $instance;
|
||||
|
||||
public function __construct(Grav $grav, AdminAddonUserManagerPlugin $plugin) {
|
||||
$this->grav = $grav;
|
||||
$this->plugin = $plugin;
|
||||
|
||||
self::$instance = $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required permission to access the manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequiredPermission() {
|
||||
return $this->plugin->name . '.users_expert';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the manager
|
||||
* It will be accessible at this path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocation() {
|
||||
return 'user-expert';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin hooked nav array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNav() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialiaze required assets
|
||||
*
|
||||
* @param \Grav\Common\Assets $assets
|
||||
* @return void
|
||||
*/
|
||||
public function initializeAssets(Assets $assets) {
|
||||
$assets->addCss('plugin://admin/themes/grav/css/codemirror/codemirror.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle task requests
|
||||
*
|
||||
* @param \RocketTheme\Toolbox\Event\Event $event
|
||||
* @return boolean
|
||||
*/
|
||||
public function handleTask(Event $event) {}
|
||||
|
||||
/**
|
||||
* Logic of the manager goes here
|
||||
*
|
||||
* @return array The array to be merged to Twig vars
|
||||
*/
|
||||
public function handleRequest() {
|
||||
$vars = [];
|
||||
|
||||
$twig = $this->grav['twig'];
|
||||
$uri = $this->grav['uri'];
|
||||
|
||||
$username = $uri->paths()[2];
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
|
||||
if (isset($_POST['raw'])) {
|
||||
$user->file()->raw($_POST['raw']);
|
||||
$user->file()->save();
|
||||
}
|
||||
|
||||
$vars['raw'] = $user->file()->raw();
|
||||
$vars['user'] = $user;
|
||||
|
||||
$blueprints = new Blueprints;
|
||||
$vars['blueprint'] = $blueprints->get('user/account-raw');
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
<?php
|
||||
namespace AdminAddonUserManager\Users;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Plugin\AdminAddonUserManagerPlugin;
|
||||
use Grav\Common\Assets;
|
||||
use Grav\Common\Data\Blueprints;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use AdminAddonUserManager\Manager as IManager;
|
||||
use AdminAddonUserManager\Pagination\ArrayPagination;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Common\User\User;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
|
||||
use AdminAddonUserManager\Group;
|
||||
use AdminAddonUserManager\Dot;
|
||||
|
||||
class Manager implements IManager, EventSubscriberInterface {
|
||||
|
||||
private $grav;
|
||||
private $plugin;
|
||||
private $adminController;
|
||||
|
||||
/**
|
||||
* In-memory caching for users
|
||||
*
|
||||
* @var Array<User>
|
||||
*/
|
||||
private $usersCached = null;
|
||||
|
||||
/**
|
||||
* In-memory cache of the account directory
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
private $accountDirCached = null;
|
||||
|
||||
public static $instance;
|
||||
|
||||
public function __construct(Grav $grav, AdminAddonUserManagerPlugin $plugin) {
|
||||
$this->grav = $grav;
|
||||
$this->plugin = $plugin;
|
||||
|
||||
self::$instance = $this;
|
||||
|
||||
$this->grav['events']->addSubscriber($this);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents() {
|
||||
return [
|
||||
'onAdminControllerInit' => ['onAdminControllerInit', 0],
|
||||
'onAdminData' => ['onAdminData', 0]
|
||||
];
|
||||
}
|
||||
|
||||
public function onAdminControllerInit($e) {
|
||||
$controller = $e['controller'];
|
||||
$this->adminController = $controller;
|
||||
}
|
||||
|
||||
public function onAdminData($e) {
|
||||
$type = $e['type'];
|
||||
|
||||
if (preg_match('|user-manager/|', $type)) {
|
||||
$post = $this->adminController->data;
|
||||
|
||||
$obj = $this->grav['accounts']->load(preg_replace('|user-manager/|', '', $type));
|
||||
$obj->merge($post);
|
||||
|
||||
$e['data_type'] = $obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required permission to access the manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequiredPermission() {
|
||||
return $this->plugin->name . '.users';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the manager
|
||||
* It will be accessible at this path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocation() {
|
||||
return 'user-manager';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin hooked nav array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNav() {
|
||||
return [
|
||||
'label' => 'PLUGIN_ADMIN_ADDON_USER_MANAGER.USER_MANAGER',
|
||||
'location' => $this->getLocation(),
|
||||
'icon' => 'fa-user',
|
||||
'authorize' => $this->getRequiredPermission(),
|
||||
'badge' => [
|
||||
'count' => count($this->users())
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialiaze required assets
|
||||
*
|
||||
* @param \Grav\Common\Assets $assets
|
||||
* @return void
|
||||
*/
|
||||
public function initializeAssets(Assets $assets) {
|
||||
$assets->addCss('plugin://' . $this->plugin->name . '/assets/users/style.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle task requests
|
||||
*
|
||||
* @param \RocketTheme\Toolbox\Event\Event $event
|
||||
* @return boolean
|
||||
*/
|
||||
public function handleTask(Event $event) {
|
||||
$method = $event['method'];
|
||||
|
||||
if ($method === 'taskUserDelete') {
|
||||
$username = $this->grav['uri']->paths()[2];
|
||||
if ($this->removeUser($username)) {
|
||||
$this->adminController->setRedirect($this->getLocation());
|
||||
}
|
||||
} elseif ($method === 'taskUserLoginAs') {
|
||||
$username = $this->grav['uri']->paths()[2];
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
$user->authenticated = true;
|
||||
|
||||
$this->grav['session']->user = $user;
|
||||
unset($this->grav['user']);
|
||||
$this->grav['user'] = $user;
|
||||
|
||||
if ($user->authorize('admin.login')) {
|
||||
$this->adminController->setRedirect('/');
|
||||
} else {
|
||||
$this->grav->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic of the manager goes here
|
||||
*
|
||||
* @return array The array to be merged to Twig vars
|
||||
*/
|
||||
public function handleRequest() {
|
||||
$vars = [];
|
||||
|
||||
$twig = $this->grav['twig'];
|
||||
$uri = $this->grav['uri'];
|
||||
|
||||
$user = $this->grav['uri']->paths();
|
||||
if (count($user) == 3) {
|
||||
$user = $user[2];
|
||||
} else {
|
||||
$user = false;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
if (isset($_POST['task']) && $_POST['task'] === 'admin-addon-user-manager-save') {
|
||||
$user = $this->grav['accounts']->load($user);
|
||||
$post = $_POST['data'];
|
||||
|
||||
try {
|
||||
$user->merge($post);
|
||||
$method = new \ReflectionMethod('\Grav\Plugin\Admin\AdminController', 'storeFiles');
|
||||
$method->setAccessible(true);
|
||||
$user = $method->invoke($this->adminController, $user);
|
||||
$user->validate();
|
||||
$user->filter();
|
||||
$user->save();
|
||||
} catch (\Exception $e) {
|
||||
$this->grav['admin']->setMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
} else {
|
||||
$blueprints = new Blueprints;
|
||||
$blueprint = $blueprints->get('user/aaum-account');
|
||||
$vars['blueprints'] = $blueprint;
|
||||
$vars['user'] = $user = $this->grav['accounts']->load($user);
|
||||
$vars['exists'] = $user->exists();
|
||||
}
|
||||
} else {
|
||||
// Bulk actions
|
||||
if (isset($_POST['selected'])) {
|
||||
$usernames = $_POST['selected'];
|
||||
|
||||
if (isset($_POST['bulk_delete'])) {
|
||||
// Bulk delete
|
||||
foreach ($usernames as $username) {
|
||||
$this->removeUser($username);
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
} else if (isset($_POST['bulk_add_to_group']) && isset($_POST['groups'])) {
|
||||
// Bulk add users to groups
|
||||
$groups = $_POST['groups'];
|
||||
|
||||
foreach ($usernames as $username) {
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
if ($user->file()->exists()) {
|
||||
if (!isset($user['groups']) || !is_array($user['groups'])) {
|
||||
$user['groups'] = [];
|
||||
}
|
||||
|
||||
$user['groups'] = array_unique(array_merge($user['groups'], $groups));
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
} else if (isset($_POST['bulk_remove_from_group']) && isset($_POST['groups'])) {
|
||||
// Bulk remove users from groups
|
||||
$groups = $_POST['groups'];
|
||||
|
||||
foreach ($usernames as $username) {
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
if ($user->file()->exists()) {
|
||||
if (!isset($user['groups']) || !is_array($user['groups'])) {
|
||||
$user['groups'] = [];
|
||||
}
|
||||
|
||||
$user['groups'] = array_unique(array_diff($user['groups'], $groups));
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
} else if (isset($_POST['bulk_add_acl']) && isset($_POST['permissions'])) {
|
||||
// Bulk add permissions to users
|
||||
$access = [];
|
||||
foreach ($_POST['permissions'] as $p) {
|
||||
Dot::set($access, $p, true);
|
||||
}
|
||||
|
||||
foreach ($usernames as $username) {
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
if ($user->file()->exists()) {
|
||||
if (!isset($user['access']) || !is_array($user['access'])) {
|
||||
$user['access'] = [];
|
||||
}
|
||||
|
||||
$user['access'] = array_merge_recursive($user['access'], $access);
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
} else if (isset($_POST['bulk_remove_acl']) && isset($_POST['permissions'])) {
|
||||
// Bulk remove permissions from users
|
||||
foreach ($usernames as $username) {
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
if ($user->file()->exists()) {
|
||||
if (!isset($user['access']) || !is_array($user['access'])) {
|
||||
$user['access'] = [];
|
||||
}
|
||||
|
||||
$access = $user['access'];
|
||||
foreach ($_POST['permissions'] as $p) {
|
||||
Dot::delete($access, $p);
|
||||
}
|
||||
$user['access'] = $access;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->grav->redirect($this->plugin->getPreviousUrl());
|
||||
}
|
||||
}
|
||||
|
||||
$vars['fields'] = $this->plugin->getModalsConfiguration()['add_user']['fields'];
|
||||
$vars['bulkFields'] = $this->plugin->getModalsConfiguration()['bulk_user']['fields'];
|
||||
$vars['groupnames'] = Group::groupNames();
|
||||
$permissions = array_keys($this->grav['admin']->getPermissions());
|
||||
foreach ($permissions as $k=>&$v) $v = ['text' => $v, 'value' => $v];
|
||||
$vars['permissions'] = $permissions;
|
||||
|
||||
// List style (grid or list)
|
||||
$listStyle = $uri->param('listStyle');
|
||||
if ($listStyle !== 'grid' && $listStyle !== 'list') {
|
||||
$listStyle = $this->plugin->getPluginConfigValue('default_list_style', 'grid');
|
||||
}
|
||||
$vars['listStyle'] = $listStyle;
|
||||
|
||||
$users = $this->users();
|
||||
|
||||
// Filtering
|
||||
$filterException = false;
|
||||
$filter = (empty($_GET['filter'])) ? '' : $_GET['filter'];
|
||||
$vars['filter'] = $filter;
|
||||
if ($filter) {
|
||||
try {
|
||||
$language = new ExpressionLanguage();
|
||||
$language->addFunction(ExpressionFunction::fromPhp('count'));
|
||||
foreach ($users as $k => $user) {
|
||||
if (!is_array($user->groups)) {
|
||||
$user->groups = [];
|
||||
}
|
||||
|
||||
if (!$language->evaluate($_GET['filter'], ['user' => $user])) {
|
||||
unset($users[$k]);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$vars['filterException'] = $exception;
|
||||
$filterException = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($filterException) {
|
||||
$users = [];
|
||||
}
|
||||
|
||||
// Pagination
|
||||
$perPage = $this->plugin->getPluginConfigValue('pagination.per_page', 10);
|
||||
$pagination = new ArrayPagination($users, $perPage);
|
||||
$pagination->paginate($uri->param('page'));
|
||||
|
||||
$vars['pagination'] = [
|
||||
'current' => $pagination->getCurrentPage(),
|
||||
'count' => $pagination->getPagesCount(),
|
||||
'total' => $pagination->getRowsCount(),
|
||||
'perPage' => $pagination->getRowsPerPage(),
|
||||
'startOffset' => $pagination->getStartOffset(),
|
||||
'endOffset' => $pagination->getEndOffset()
|
||||
];
|
||||
$vars['users'] = $pagination->getPaginatedRows();
|
||||
$vars['user'] = false;
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function users() {
|
||||
if ($this->usersCached) {
|
||||
return $this->usersCached;
|
||||
}
|
||||
|
||||
$users = [];
|
||||
$dir = $this->getAccountDir();
|
||||
|
||||
// Try cache
|
||||
$cache = $this->grav['cache'];
|
||||
$cacheKey = $this->plugin->name . '.users';
|
||||
|
||||
$modifyTime = filemtime($dir);
|
||||
$usersCache = $cache->fetch($cacheKey);
|
||||
if (!$usersCache || $modifyTime > $usersCache['modifyTime']) {
|
||||
// Find accounts
|
||||
$files = $dir ? array_diff(scandir($dir), ['.', '..']) : [];
|
||||
foreach ($files as $file) {
|
||||
if (Utils::endsWith($file, YAML_EXT)) {
|
||||
$user = $this->grav['accounts']->load(trim(pathinfo($file, PATHINFO_FILENAME)));
|
||||
$users[$user->username] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate and/or refresh cache
|
||||
$this->saveUsersToCache($users);
|
||||
} else {
|
||||
$users = $usersCache['users'];
|
||||
}
|
||||
|
||||
$this->usersCached = $users;
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
private function saveUsersToCache($users) {
|
||||
$cache = $this->grav['cache'];
|
||||
$cacheKey = $this->plugin->name . '.users';
|
||||
$dir = $this->getAccountDir();
|
||||
$modifyTime = filemtime($dir);
|
||||
|
||||
$usersCache = [
|
||||
'modifyTime' => $modifyTime,
|
||||
'users' => $users,
|
||||
];
|
||||
|
||||
$cache->save($cacheKey, $usersCache);
|
||||
}
|
||||
|
||||
private function getAccountDir() {
|
||||
if ($this->accountDirCached) {
|
||||
return $this->grav['locator']->findResource('account://');
|
||||
}
|
||||
|
||||
return $this->accountDirCached = $this->grav['locator']->findResource('account://');
|
||||
}
|
||||
|
||||
public function removeUser($username) {
|
||||
$user = $this->grav['accounts']->load($username);
|
||||
|
||||
if ($user->file()->exists()) {
|
||||
$users = $this->users();
|
||||
$user->file()->delete();
|
||||
// Prevent users cache refresh
|
||||
unset($users[$username]);
|
||||
$this->saveUsersToCache($users);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function userNames() {
|
||||
$instance = self::$instance;
|
||||
$users = $instance->users();
|
||||
|
||||
$userNames = [];
|
||||
foreach ($users as $u) {
|
||||
$userNames[$u['username']] = $u['username'];
|
||||
}
|
||||
|
||||
return $userNames;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user