monster_menus-9.0.x-dev/src/Plugin/MMSearchAction/ModifyPermissions.php
src/Plugin/MMSearchAction/ModifyPermissions.php
<?php
namespace Drupal\monster_menus\Plugin\MMSearchAction;
use Drupal\Core\Form\FormStateInterface;
use Drupal\monster_menus\Annotation\MMSearchAction;
use Drupal\monster_menus\Constants;
use Drupal\monster_menus\Entity\MMTree;
use Drupal\monster_menus\MMSearchAction\MMSearchActionBase;
use Drupal\node\Entity\Node;
/**
* Provides the MM Search Results Action to modify page/node permissions.
*
* @MMSearchAction(
* id = "mm_search_action_modify_perms",
* label = @Translation("modify permissions"),
* description = @Translation("Provides the MM Search Results Action to modify page/node permissions."),
* useDrupalSettings = true,
* jsInit = "MMSR_init_action_modify_perms",
* )
*/
class ModifyPermissions extends MMSearchActionBase {
use ResultsTrait;
public const ADD_USER_GROUP = 'add_ug';
public const DEL_USER_GROUP = 'del_ug';
public const OWNER = 'owner';
public const SUB_APPLY = 'au';
public const SESSION_DATA = 'mmsr-mp';
/**
* @inheritDoc
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$x = ['@thing' => $this->t('permissions')];
switch ($this->getConfiguration('search_type')) {
case self::SEARCH_TYPE_GROUPS:
$mp_modes = [
Constants::MM_PERMS_WRITE => $this->t('delete/change settings'),
Constants::MM_PERMS_SUB => $this->t('append sub-groups'),
Constants::MM_PERMS_READ => $this->t('see group members'),
];
break;
case self::SEARCH_TYPE_PAGES:
$mp_modes = [
Constants::MM_PERMS_WRITE => $this->t('delete/change settings'),
Constants::MM_PERMS_SUB => $this->t('append sub-pages'),
Constants::MM_PERMS_APPLY => $this->t('add content'),
self::SUB_APPLY => $this->t('append sub-pages AND add content'),
Constants::MM_PERMS_READ => $this->t('read'),
];
break;
default:
$x = ['@thing' => $this->t('"Who can edit or delete this content"')];
$mp_modes = [];
}
$form['modify_mode'] = [
'#type' => 'select',
'#options' => [
self::ADD_USER_GROUP => $this->t('add users/groups to @thing', $x),
self::DEL_USER_GROUP => $this->t('remove users/groups from @thing', $x),
self::OWNER => $this->t('change the owner', $x),
],
'#default_value' => $_SESSION[self::SESSION_DATA]['modify_mode'] ?? self::ADD_USER_GROUP,
];
$form['modify_perms'] = [
'modify' => [
'#type' => 'container',
'#tree' => TRUE,
'users_w-choose' => [
'#type' => 'textfield',
'#attributes' => ['autocomplete' => 'off'], // Prevent FF from caching a previous value
'#autocomplete_route_name' => 'monster_menus.autocomplete',
'#size' => 30,
],
'users_w' => [
'#type' => 'mm_userlist',
'#mm_list_autocomplete_name' => 'modify[users_w-choose]',
'#default_value' => $_SESSION[self::SESSION_DATA]['users_w'] ?? [],
],
'groups_w' => [
'#type' => 'mm_grouplist',
'#default_value' => $_SESSION[self::SESSION_DATA]['groups_w'] ?? [],
],
'owner' => [
'userlist-choose' => [
'#type' => 'textfield',
'#attributes' => ['autocomplete' => 'off'], // Prevent FF from caching a previous value
'#autocomplete_route_name' => 'monster_menus.autocomplete',
'#size' => 30,
],
'userlist' => [
'#type' => 'mm_userlist',
'#title' => $this->t('Owner'),
'#mm_list_autocomplete_name' => 'modify[owner][userlist-choose]',
'#default_value' => $_SESSION[self::SESSION_DATA]['owner'] ?? [0 => ''],
'#mm_list_min' => 1,
'#mm_list_max' => 1,
],
],
],
];
if ($mp_modes) {
$form['modify_perms']['modify']['mp_mode'] = [
'#type' => 'select',
'#title' => $this->t('with the permission'),
'#options' => $mp_modes,
'#default_value' => $_SESSION[self::SESSION_DATA]['mp_mode'] ?? NULL,
];
}
$form['actions'] = [
'#type' => 'actions',
'calc' => [
'#type' => 'submit',
'#value' => $this->t('Calculate'),
'#attributes' => ['onclick' => 'MMSR_recalculate_action(this); return false;'],
],
'mp_result' => [
'#type' => 'submit',
'#value' => $this->t('Modify Permissions'),
'#attributes' => ['onclick' => 'var t = jQuery("#mmsr-mp-status-text").text(); if (!t || confirm(t)) MMSR_recalculate_action(this); return false;'],
],
];
$this->addStatusMarkup($form);
return $form;
}
/**
* @inheritDoc
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->setSubmittedValues($form_state);
$this->iterate($this->iterateNode(...), $this->iteratePage(...));
$_SESSION[self::SESSION_DATA] = [
'modify_mode' => $this->values['modify_mode'],
'groups_w' => $this->values['modify']['groups_w'] ?? [],
'users_w' => $this->values['modify']['users_w'] ?? [],
'owner' => $this->values['modify']['owner']['userlist'] ?? [],
'mp_mode' => $this->values['modify']['mp_mode'] ?? '',
];
$this->returnResults($this->updateNeeded);
}
public function iterateNode($row) {
if (mm_content_user_can_node($row->nid, Constants::MM_PERMS_WRITE)) {
if ($node = Node::load($row->nid)) {
$this->countAllowed++;
$changed = FALSE;
switch ($this->values['modify_mode']) {
case self::ADD_USER_GROUP:
foreach (['users_w', 'groups_w'] as $ug) {
if (!empty($this->values['modify'][$ug])) {
if (array_diff_key($this->values['modify'][$ug], $node->__get($ug))) {
$changed = TRUE;
if ($this->updateNeeded) {
$node->__set($ug, $node->__get($ug) + $this->values['modify'][$ug]);
}
}
}
}
break;
case self::DEL_USER_GROUP:
foreach (['users_w', 'groups_w'] as $ug) {
if (!empty($this->values['modify'][$ug])) {
if (array_intersect_key($node->__get($ug), $this->values['modify'][$ug])) {
$changed = TRUE;
if ($this->updateNeeded) {
$node->__set($ug, array_diff_key($node->__get($ug), $this->values['modify'][$ug]));
}
}
}
}
break;
case self::OWNER:
$changed = $this->processOwner($node) || $changed;
break;
}
if ($changed) {
$this->countChanged++;
if ($this->updateNeeded) {
$node->save();
}
}
}
}
}
public function iteratePage($row) {
if (mm_content_user_can($row->mmtid, Constants::MM_PERMS_WRITE)) {
if ($tree = MMTree::load($row->mmtid)) {
$this->countAllowed++;
$changed = FALSE;
switch ($this->values['modify_mode']) {
case self::ADD_USER_GROUP:
foreach (['users', 'groups'] as $ug) {
$valkey = "{$ug}_w";
if (!empty($this->values['modify'][$valkey])) {
$adds = array_keys($this->values['modify'][$valkey]);
foreach (str_split($this->values['modify']['mp_mode']) as $mode) {
if (array_diff($adds, $tree->perms[$mode][$ug])) {
$changed = TRUE;
if ($this->updateNeeded) {
$this->setTreePerms($tree, $mode, $ug, array_unique(array_merge($tree->perms[$mode][$ug], $adds)));
}
}
}
}
}
break;
case self::DEL_USER_GROUP:
foreach (['users', 'groups'] as $ug) {
$valkey = "{$ug}_w";
if (!empty($this->values['modify'][$valkey])) {
$dels = array_keys($this->values['modify'][$valkey]);
foreach ($tree->perms as $mode => $list) {
if (array_intersect($list[$ug], $dels)) {
$changed = TRUE;
if ($this->updateNeeded) {
$this->setTreePerms($tree, $mode, $ug, array_diff($list[$ug], $dels));
}
}
}
}
}
break;
case self::OWNER:
$changed = $this->processOwner($tree) || $changed;
break;
}
if ($changed) {
$this->countChanged++;
if ($this->updateNeeded) {
$tree->save();
}
}
}
}
}
private function setTreePerms(MMTree $tree, $mode, $ug, $perms) {
$settings = $tree->getExtendedSettings();
$settings['perms'][$mode][$ug] = $perms;
$tree->setExtendedSettings($settings);
}
private function processOwner($entity) {
if (!empty($this->values['modify']['owner']['userlist'])) {
$uid = mm_ui_mmlist_key0($this->values['modify']['owner']['userlist']);
if ($entity->getOwnerId() != $uid) {
if ($this->updateNeeded) {
$entity->setOwnerId($uid);
}
return TRUE;
}
}
return FALSE;
}
/**
* @inheritDoc
*/
public function applies() {
return TRUE;
}
/**
* @inheritDoc
*/
public function access() {
if ($this->getConfiguration('result_count') > 0) {
$return = $this->iterate(function ($row) {
if (mm_content_user_can_node($row->nid, Constants::MM_PERMS_WRITE)) {
return TRUE;
}
}, function ($row) {
if (mm_content_user_can($row->mmtid, Constants::MM_PERMS_WRITE)) {
return TRUE;
}
});
return !empty($return);
}
return FALSE;
}
}