monster_menus-9.0.x-dev/src/PermissionsSolver.php
src/PermissionsSolver.php
<?php
/**
* @file
* Contains \Drupal\monster_menus\Form\ListSitesForm.
*/
namespace Drupal\monster_menus;
use Drupal\Core\Database\Database;
use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
class PermissionsSolver {
public static function getSolverForm(array &$form, $mmtid = NULL) {
mm_static($form, 'solver_mm_list_callback', $mmtid);
$form['solver_form'] = [
'#prefix' => '<div class="hidden" id="solver-form">',
'#suffix' => '<div id="mm-solver-table"></div></div>',
];
_mm_ui_userlist_setup([-1 => ''], $form['solver_form'], 'solver', t("User's name"), TRUE, '');
$form['solver_form']['solver-choose']['#title'] = '';
$form['solver_form']['solver']['#mm_list_other_callback'] = 'mmSolverCallback';
$form['solver_form']['solver']['#description'] = t('Choose a user to see their actual permissions for this page, taking into account the permissions of all parent pages.');
$title = t('Solve permissions issues');
$form['mm-solver-link'] = [
'#type' => 'link',
'#weight' => -10,
'#prefix' => '<div id="mm-solver-link">',
'#suffix' => '</div>',
'#title' => $title,
'#url' => Url::fromRoute('monster_menus.solver', ['mm_tree' => $mmtid, 'user' => 0]),
'#options' => [
'fragment' => 'solver-form',
'external' => TRUE,
'attributes' => [
'id' => mm_ui_modal_dialog(['minWidth' => 500, 'minHeight' => 400], $form),
'title' => $title,
],
],
];
return $form;
}
public static function getSolverTable($mmtid, AccountInterface $acct) {
$list = mm_content_get_parents_with_self($mmtid, FALSE, FALSE);
$user_access = [];
$is_admin = $acct->id() == 1;
foreach (['administer all menus', 'administer all users', 'administer all groups', 'view all menus'] as $access_mode) {
if ($acct->isAuthenticated() || str_starts_with($access_mode, 'view')) {
$user_access[$access_mode] = $acct->hasPermission($access_mode);
}
else {
$user_access[$access_mode] = FALSE;
}
}
$is_admin |= $user_access['administer all menus'];
$is_user = $is_group = $is_recycled = FALSE;
$can_read = $can_recycle = TRUE;
$header = [t('Page'), t('Edit'), t('Add subpages'), t('Add content'), t('Read')];
$rows = [];
$all_modes = [
Constants::MM_PERMS_WRITE => 1,
Constants::MM_PERMS_SUB => 1,
Constants::MM_PERMS_APPLY => 1,
Constants::MM_PERMS_READ => 1,
];
$everyone = [
Constants::MM_PERMS_WRITE => t('everyone can edit'),
Constants::MM_PERMS_SUB => t('everyone can add subpages'),
Constants::MM_PERMS_APPLY => t('everyone can add content'),
Constants::MM_PERMS_READ => t('everyone can read')
];
$readable = [
Constants::MM_PERMS_WRITE => t('can edit this page'),
Constants::MM_PERMS_SUB => t('can add subpages to this page'),
Constants::MM_PERMS_APPLY => t('can add content to this page'),
];
$yes = ['#theme' => 'mm_ui_mark_yesno', '#yes' => TRUE];
$yes = \Drupal::service('renderer')->render($yes);
$no = ['#theme' => 'mm_ui_mark_yesno', '#yes' => FALSE];
$no = \Drupal::service('renderer')->render($no);
foreach ($list as $entry) {
$modes = [];
$reasons = [
Constants::MM_PERMS_WRITE => [],
Constants::MM_PERMS_SUB => [],
Constants::MM_PERMS_APPLY => [],
Constants::MM_PERMS_READ => [],
];
$item = mm_content_get($entry);
if ($entry == mm_content_users_mmtid()) {
$is_user = TRUE;
}
elseif ($entry == mm_content_groups_mmtid()) {
$is_group = TRUE;
}
if ($item->name == Constants::MM_ENTRY_NAME_RECYCLE) {
$is_recycled = TRUE;
}
$name = mm_content_get_name($item);
if ($entry != 1) {
$url = mm_content_user_can($entry, Constants::MM_PERMS_WRITE) ? 'monster_menus.handle_page_settings' : 'entity.mm_tree.canonical';
$name = Link::fromTextAndUrl($name, Url::fromRoute($url, ['mm_tree' => $entry]))->toString();
}
$row = [$name];
if ($is_admin || ($is_user && $user_access['administer all users'] || $is_group && $user_access['administer all groups'])) {
$modes = $all_modes;
$reasons[Constants::MM_PERMS_WRITE][] = $reasons[Constants::MM_PERMS_SUB][] = $reasons[Constants::MM_PERMS_APPLY][] = $reasons[Constants::MM_PERMS_READ][] = t('is an administrator');
}
if (!$is_admin && $user_access['view all menus']) {
$modes[Constants::MM_PERMS_READ] = 1;
$reasons[Constants::MM_PERMS_READ][] = t('can view all pages');
}
if (!$can_read) {
$reasons[Constants::MM_PERMS_WRITE][] = $reasons[Constants::MM_PERMS_SUB][] = $reasons[Constants::MM_PERMS_APPLY][] = $reasons[Constants::MM_PERMS_READ][] = t('cannot read parent');
}
else {
if ($item->uid == $acct->id()) {
$modes = $all_modes;
$reasons[Constants::MM_PERMS_WRITE][] = $reasons[Constants::MM_PERMS_SUB][] = $reasons[Constants::MM_PERMS_APPLY][] = $reasons[Constants::MM_PERMS_READ][] = t('is the owner');
}
foreach ($everyone as $mode => $reason)
if (str_contains($item->default_mode ?? '', $mode)) {
$modes[$mode] = 1;
$reasons[$mode][] = $reason;
}
$db = Database::getConnection();
$select = $db->select('mm_tree_access', 'a');
$select->join('mm_group', 'g', 'g.gid = a.gid');
$select->leftJoin('mm_tree', 't', 't.mmtid = g.gid');
$select->leftJoin('mm_virtual_group', 'v', 'v.vgid = g.vgid');
$and = $db->Condition('AND');
$and->condition('g.vgid', 0)
->condition('g.uid', $acct->id());
$or = $db->Condition('OR');
$or->condition('v.uid', $acct->id())
->condition($and);
$select->fields('a', ['mode', 'gid'])
->condition('a.mmtid', $entry)
->condition($or);
$result = mm_retry_query($select);
foreach ($result as $mode_obj) {
$modes[$mode_obj->mode] = 1;
$reasons[$mode_obj->mode][] = $mode_obj->gid < 0 ? t('is a listed user') : t('is in the group %name', ['%name' => mm_content_get_name($mode_obj->gid)]);
}
if ($item->name == Constants::MM_ENTRY_NAME_RECYCLE) {
$can_recycle = $can_recycle && mm_content_user_can_recycle($entry, Constants::MM_PERMS_READ, $acct);
if ($can_recycle) {
$reasons[Constants::MM_PERMS_READ][] = t('can edit something in bin');
$modes[Constants::MM_PERMS_READ] = 1;
}
else {
$reasons[Constants::MM_PERMS_READ][] = t('cannot edit anything in bin');
}
}
else {
if (isset($modes[Constants::MM_PERMS_WRITE])) {
$modes[Constants::MM_PERMS_SUB] = $modes[Constants::MM_PERMS_APPLY] = $modes[Constants::MM_PERMS_READ] = 1;
$reasons[Constants::MM_PERMS_SUB][] = $reasons[Constants::MM_PERMS_APPLY][] = $reasons[Constants::MM_PERMS_READ][] = $readable[Constants::MM_PERMS_WRITE];
}
else {
foreach ([Constants::MM_PERMS_SUB, Constants::MM_PERMS_APPLY] as $mode) {
if (isset($modes[$mode])) {
$modes[Constants::MM_PERMS_READ] = 1;
$reasons[Constants::MM_PERMS_READ][] = $readable[$mode];
}
}
}
if ($is_recycled) {
if (!isset($modes[Constants::MM_PERMS_READ]) || !$can_recycle) {
$reasons[Constants::MM_PERMS_READ][] = t('cannot edit anything in bin');
}
}
}
}
foreach (array_keys($all_modes) as $mode) {
if (!$reasons[$mode]) $reasons[$mode][] = t('not permitted');
$tip = [
'#theme' => 'tooltip',
'#text' => isset($modes[$mode]) ? $yes : $no,
'#title' => t('reason(s)'),
'#tip' => '<ul><li>' . join('; </li><li>', $reasons[$mode]) . '</li></ul>',
'#html' => TRUE,
];
$row[] = \Drupal::service('renderer')->render($tip);
}
$rows[] = $row;
$can_read = isset($modes[Constants::MM_PERMS_READ]);
}
return [
[
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#attributes' => ['id' => 'mm-solver'],
],
[
'#markup' => '<div class="description">' . t('Put the mouse over any @yes or @no symbol above to see the reason(s).<br /><b>Note:</b> The table above does not take into account any unsaved changes to settings.', ['@yes' => $yes, '@no' => $no]) . '</div>'
],
];
}
}
