monster_menus-9.0.x-dev/modules/mm_webform/mm_webform.module

modules/mm_webform/mm_webform.module
<?php

/**
 * @file
 * Webform hooks implemented by Monster Menus
 */
use Drupal\mm_webform\Form\MMWebformUiEntityElementsForm;
use Drupal\mm_webform\Form\MMWebformEntityElementsForm;
use Drupal\mm_webform\Form\MMWebformEntitySettingsGeneralForm;
use Drupal\mm_webform\Form\MMWebformEntitySettingsFormForm;
use Drupal\mm_webform\Form\MMWebformEntitySettingsSubmissionsForm;
use Drupal\mm_webform\Form\MMWebformEntitySettingsConfirmationForm;
use Drupal\mm_webform\Form\MMWebformEntityHandlersForm;
use Drupal\mm_webform\Form\MMWebformHandlerAddForm;
use Drupal\mm_webform\Form\MMWebformHandlerEditForm;
use Drupal\mm_webform\Form\MMWebformHandlerDeleteForm;
use Drupal\mm_webform\Form\MMWebformHandlerDuplicateForm;
use Drupal\mm_webform\Plugin\WebformSourceEntity\MMWebformRouteParametersSourceEntity;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\mm_webform\MMWebformAccess;
use Drupal\monster_menus\Constants;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\Core\Url;
use Drupal\webform\Access\WebformAccessResult;
use Drupal\webform\Entity\Webform;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouteCollection;

const DUMMY_WEBFORM_ID = 'WEBFORM_DUMMY_ID';

/**
 * Implements hook_help().
 */
function mm_webform_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'monster_menus.add_node_with_type':
    case 'node.add':
      if (in_array($route_match->getParameter('node_type'), mm_webform_get_node_types_with_webforms())) {
        return t('Complete as much as you can of the information below, and click on Save. Then you will be able to add elements to your form.');
      }
      return '';

    case 'mm_webform.edit_form':
      $output = '<p>' . t('This page displays all the elements currently configured for this webform. You may add any number of elements to the form, even multiple of the same type. To add a new elements, fill in a name and select a type from the fields at the bottom of the table. Submit the form to create the new component or update any changed form values.') . '</p>';
      $output .= '<p>' . t('Click on any existing component\'s name to edit its settings.') . '</p>';
      return $output;
  }
  return '';
}

/**
 * Implements hook_entity_type_alter().
 */
function mm_webform_entity_type_alter(array &$entity_types) {
  if (isset($entity_types['webform'])) {
    $form_handlers = $entity_types['webform']->getHandlerClasses()['form'];
    $form_handlers['edit'] = mm_module_exists('webform_ui') ? MMWebformUiEntityElementsForm::class : MMWebformEntityElementsForm::class;
    $form_handlers['settings'] = MMWebformEntitySettingsGeneralForm::class;
    $form_handlers['settings_form'] = MMWebformEntitySettingsFormForm::class;
    $form_handlers['settings_submissions'] = MMWebformEntitySettingsSubmissionsForm::class;
    $form_handlers['settings_confirmation'] =MMWebformEntitySettingsConfirmationForm::class;
    $form_handlers['handlers'] =MMWebformEntityHandlersForm::class;
    $entity_types['webform']->setHandlerClass('form', $form_handlers);
  }
}

/**
 * Implements hook_menu_local_actions_alter().
 */
function mm_webform_menu_local_actions_alter(&$local_actions) {
  $changes = [
    'mm_webform.edit_form' => ['entity.webform_ui.element', 'entity.webform_ui.element.page', 'entity.webform_ui.element.layout'],
    'mm_webform.handlers' => ['entity.webform.handler.add_email'],
  ];
  foreach ($changes as $appears_on => $routes) {
    foreach ($routes as $route) {
      if (isset($local_actions[$route])) {
        $new_name = str_replace('entity.webform', 'mm_webform', $route);
        $local_actions[$new_name] = $local_actions[$route];
        $local_actions[$new_name]['appears_on'] = [$appears_on];
        $local_actions[$new_name]['route_name'] = str_replace('entity.webform', 'mm_webform', $local_actions[$new_name]['route_name']);
      }
    }
  }
}

/**
 * Implements hook_module_implements_alter().
 */
function mm_webform_module_implements_alter(&$implementations, $hook) {
  if (in_array($hook, ['entity_type_alter', 'node_links_alter'])) {
    // Move our implementation of these hooks to the end of the list, so that
    // entity_type_alter happens after webform_ui and webform_node and
    // node_links_alter happens after MM.
    $group = $implementations['mm_webform'];
    unset($implementations['mm_webform']);
    $implementations['mm_webform'] = $group;
  }
}

/**
 * Implements hook_mm_routing_alter().
 */
function mm_webform_mm_routing_alter(RouteCollection $collection) {
  $routes = [
    'entity.webform.edit_form' =>                 '/mm/{mm_tree}/node/{node}/edit/webform',
    'entity.webform.settings' =>                  '/mm/{mm_tree}/node/{node}/edit/webform/settings',
    'entity.webform.settings_form' =>             '/mm/{mm_tree}/node/{node}/edit/webform/form',
    'entity.webform.settings_submissions' =>      '/mm/{mm_tree}/node/{node}/edit/webform/submissions',
    'entity.webform.settings_confirmation' =>     '/mm/{mm_tree}/node/{node}/edit/webform/confirmation',
    'entity.webform.handlers' =>                  '/mm/{mm_tree}/node/{node}/edit/webform/handlers',
    'entity.webform.handler.add_email' =>         '/mm/{mm_tree}/node/{node}/edit/webform/handlers/add/email',
    'entity.webform.handler.edit_form' =>         '/mm/{mm_tree}/node/{node}/edit/webform/handlers/{webform_handler}/edit',
    'entity.webform.handler.duplicate_form' =>    '/mm/{mm_tree}/node/{node}/edit/webform/handlers/{webform_handler}/duplicate',
    'entity.webform.handler.delete_form' =>       '/mm/{mm_tree}/node/{node}/edit/webform/handlers/{webform_handler}/delete',
    'entity.webform.handler.disable' =>           '/mm/{mm_tree}/node/{node}/edit/webform/handlers/{webform_handler}/disable',
    'entity.webform.handler.enable' =>            '/mm/{mm_tree}/node/{node}/edit/webform/handlers/{webform_handler}/enable',
    'entity.webform_ui.change_element' =>         '/mm/{mm_tree}/node/{node}/edit/webform/element/{key}/change',
    'entity.webform_ui.element' =>                '/mm/{mm_tree}/node/{node}/edit/webform/element/add',
    'entity.webform_ui.element.add_form' =>       '/mm/{mm_tree}/node/{node}/edit/webform/element/add/{type}',
    'entity.webform_ui.element.add_page' =>       '/mm/{mm_tree}/node/{node}/edit/webform/element/add/page',
    'entity.webform_ui.element.add_layout' =>     '/mm/{mm_tree}/node/{node}/edit/webform/element/add/layout',
    'entity.webform_ui.element.edit_form' =>      '/mm/{mm_tree}/node/{node}/edit/webform/element/{key}/edit',
    'entity.webform_ui.element.duplicate_form' => '/mm/{mm_tree}/node/{node}/edit/webform/element/{key}/duplicate',
    'entity.webform_ui.element.delete_form' =>    '/mm/{mm_tree}/node/{node}/edit/webform/element/{key}/delete',
  ];
  foreach ($routes as $route_name => $new_path) {
    if ($route = $collection->get($route_name)) {
      $old_access = $route->getRequirement('_custom_access');
      $route = clone $route;
      $route->setPath($new_path);
      $options = $route->getOptions();
      // Use the page's theme.
      $options['_admin_route'] = FALSE;
      $params = $options['parameters'] ?? [];
      $params['mm_tree'] = ['type' => 'entity:mm_tree', 'converter' => 'paramconverter.entity'];
      // Remove _entity_access requirement
      $route->setRequirements([]);
      $route->setRequirement('mm_tree', '-?\d+');
      $params['node'] = ['type' => 'entity:node', 'converter' => 'paramconverter.entity'];
      $route->setRequirement('node', '\d+');
      $options['parameters'] = $params;
      $route->setOptions($options);
      switch ($route_name) {
        case 'entity.webform.handler.add_email':
          $route->setDefault('_form', MMWebformHandlerAddForm::class);
          $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::accessHandler');
          break;
        case 'entity.webform.handler.edit_form':
          $route->setDefault('_form', MMWebformHandlerEditForm::class);
          $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::access');
          break;
        case 'entity.webform.handler.disable':
        case 'entity.webform.handler.enable':
          $route->setDefault('_controller', '\Drupal\mm_webform\Form\MMWebformEntityHandlersForm:mmAjaxOperation');
          $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::access');
          break;
        case 'entity.webform.handler.delete_form':
          $route->setDefault('_form', MMWebformHandlerDeleteForm::class);
          $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::access');
          break;
        case 'entity.webform.handler.duplicate_form':
          $route->setDefault('_form', MMWebformHandlerDuplicateForm::class);
          $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::access');
          break;
        default:
          if (str_starts_with($route_name, 'entity.webform_ui.')) {
            $form = str_replace('WebformUiElement', 'MMWebformUiElement', $route->getDefault('_form'));
            $form = str_replace('\webform_ui', '\mm_webform', $form);
            $route->setDefault('_form', $form);
            if (strpos($old_access, 'checkWebformEditAccess')) {
              $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::accessWebformEdit');
            }
            else {
              $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::accessWebformElement');
            }
          }
          else {
            $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::access');
          }
          break;
      }
      $collection->add(str_replace('entity.webform', 'mm_webform', $route_name), $route);
    }
  }

  foreach (['entity.node.webform.results_submissions', 'entity.node.webform.results_submissions.custom'] as $path) {
    if ($route = $collection->get($path)) {
      $route->setDefault('entity_access', '');
      // Use the page's theme.
      $route->setOption('_admin_route', FALSE);
      $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::accessViewSubmission');
    }
  }

  if ($route = $collection->get('entity.node.webform.test_form')) {
    $route->setDefault('entity_access', '');
    $route->setRequirement('_custom_access', '\Drupal\mm_webform\MMWebformAccess::accessWebformEdit');
  }
}

/**
 * Implements hook_form_alter().
 */
function mm_webform_form_node_form_alter(&$form, FormStateInterface &$form_state) {
  /** @var NodeInterface $node */
  $node = $form_state->getFormObject()->getEntity();
  if ($webform_field = mm_webform_get_webform_field($node)) {
    $webform_field_name = $webform_field->getName();
    unset($form[$webform_field_name]['widget'][0]['webform_node_references']);
    $form[$webform_field_name]['widget'][0]['settings']['#access'] = FALSE;
    if (!$node->isNew()) {
      $form[$webform_field_name]['widget'][0]['target_id']['#access'] = FALSE;
    }
    else {
      $form[$webform_field_name]['widget'][0]['webform_mode'] = [
        '#type' => 'radios',
        '#options' => [
          'new' => t('Create a new, blank Webform'),
          'old' => t('Clone an existing Webform'),
        ],
        '#default_value' => 'new',
        '#weight' => -1,
      ];
      $form[$webform_field_name]['widget'][0]['target_id']['#description'] = t('Select the existing Webform upon which you would like to base your new Webform');
      $form[$webform_field_name]['widget'][0]['target_id']['#states']['visible'][':input[name="' . $webform_field_name . '[0][webform_mode]"]'] = ['value' => 'old'];
      // It's impossible to preview this node without creating a new Webform,
      // so don't allow it.
      if (isset($form['actions']['preview'])) {
        $form['actions']['preview']['#access'] = FALSE;
      }
      $form_state->setTemporaryValue('webform_field_name', $webform_field_name);
      $form['#validate'][] = '_mm_webform_node_form_validate';
      array_unshift($form['actions']['submit']['#submit'], '_mm_webform_node_form_submit_first');
      $form['actions']['submit']['#submit'][] = '_mm_webform_node_form_submit_last';
    }
  }
}

function _mm_webform_node_form_validate($form, FormStateInterface $form_state) {
  $webform_field_name = $form_state->getTemporaryValue('webform_field_name');
  $webform = $form_state->getValue($webform_field_name)[0];
  if ($webform['webform_mode'] == 'old' && empty($webform['target_id'])) {
    $form_state->setErrorByName($webform_field_name . '][0][target_id', t('You must choose an existing Webform to clone from.'));
  }
}

function _mm_webform_node_form_submit_first($form, FormStateInterface $form_state) {
  $webform_field_name = $form_state->getTemporaryValue('webform_field_name');
  $webform_elem = $form_state->getValue($webform_field_name)[0];
  $title = $form_state->getValue('title')[0]['value'];
  $i = 0;
  if ($webform_elem['webform_mode'] == 'old') {
    // Try to remove any existing numerical suffix, if possible.
    if (preg_match('/^(\w+?)(\d+)$/', $webform_elem['target_id'], $matches)) {
      $test_id = $matches[1];
      $i = $matches[2] + 1;
    }
    else {
      $test_id = $webform_elem['target_id'];
    }
  }
  else {
    $test_id = substr(preg_replace('/\W/', '_', strtolower($title)), 0, 20);
  }

  for (;;) {
    $new_id = $i ? "$test_id$i" : $test_id;
    if (!Webform::load($new_id)) {
      break;
    }
    $i++;
  }

  if ($webform_elem['webform_mode'] == 'old') {
    $webform = Webform::load($webform_elem['target_id']);
    $webform->setOriginalId(NULL)
      ->set('uuid', Drupal::service('uuid')->generate())
      ->set('title', $title)
      ->set('id', $new_id)
      ->enforceIsNew();
  }
  else {
    $webform = Webform::create(['id' => $new_id, 'title' => $title]);
  }
  // It doesn't make much sense to show the form's internal name, so hide it by
  // default.
  $webform->setSetting('form_title', WebformInterface::TITLE_SOURCE_ENTITY);
  $webform->save();
  $form_state->setValueForElement($form[$webform_field_name]['widget'][0]['target_id'], $new_id);
  $form_state->addBuildInfo('webform_id', $new_id);
}

function _mm_webform_node_form_submit_last($form, FormStateInterface $form_state) {
  $redirect = new Url('entity.node.edit_form', ['node' => $form_state->get('nid')], ['absolute' => TRUE]);
  // The node form code always redirects to node/NN, so this is the only
  // good way to make it go to the components page instead.
  $form_state->disableRedirect()->setResponse(new RedirectResponse($redirect->toString(), 303));
}

/**
 * Implements hook_form_alter().
 */
function mm_webform_form_webform_settings_form_alter(&$form, FormStateInterface &$form_state) {
  // Don't do anything if there's no node parameter in the URL.
  if (!($node = \Drupal::service('current_route_match')->getParameters()->get('node'))) {
    return;
  }
  /** @var NodeInterface $node */
  // It doesn't make sense to delete a webform attached to a node.
  $form['actions']['delete']['#access'] = FALSE;
  // Hide title, since it's not used when the webform is attached to a node.
  $form['general_settings']['title']['#access'] = FALSE;
  // Set admin description and hide it.
  $form['general_settings']['description']['#default_value'] = t('Associated with node #@nid, %title', ['@nid' => $node->id(), '%title' => $node->label()]);
  $form['general_settings']['description']['#access'] = FALSE;
  // Hide category.
  $form['general_settings']['category']['#access'] = FALSE;
  // Hide URL path settings.
  $form['page_settings']['page']['#default_value'] = FALSE;
  $form['page_settings']['#access'] = FALSE;
  // Close Advanced Settings by default.
  $form['advanced_settings']['#open'] = FALSE;
}

/**
 * Implements hook_form_alter().
 */
function mm_webform_form_webform_settings_form_form_alter(&$form, FormStateInterface &$form_state) {
  // It would be dangerous to allow this.
  $form['form_behaviors']['form_prepopulate_source_entity']['#default_value'] = FALSE;
  $form['form_behaviors']['form_prepopulate_source_entity']['#access'] = FALSE;
  $form['form_behaviors']['form_prepopulate_source_entity_required']['#access'] = FALSE;
  $form['form_behaviors']['form_prepopulate_source_entity_type']['#access'] = FALSE;
}

/**
 * Implements hook_form_alter().
 */
function mm_webform_form_webform_settings_submissions_form_alter(&$form, FormStateInterface $form_state) {
  // Don't do anything if there's no node parameter in the URL.
  if (!($node = \Drupal::service('current_route_match')->getParameters()->get('node'))) {
    return;
  }
  /** @var NodeInterface $node */
  $everyone = $node->__get('sub_others') ?? FALSE;
  $grouplist = $node->__get('sub_groups') ?? [];
  $userlist = $node->__get('sub_users') ?? [];
  if (count($userlist) || count($grouplist)) {
    $everyone = FALSE;
  }

  $form['submission_readers'] = [
    '#type' => 'details',
    '#title' => t('Who can read data submitted to this webform'),
    '#description' => t("Only the webform's editors and those people listed here can view what users post using the webform."),
    '#open' => TRUE,
  ];
  $form['submission_readers']['sub_groups'] = [
    '#type' => 'mm_grouplist',
    '#mm_list_other_id' => 'edit-sub_others',
    '#default_value' => $grouplist,
  ];
  $form_state->set('nid', $node->id());
  $form['actions']['submit']['#submit'][] = '_mm_webform_submissions_submit';

  _mm_ui_userlist_setup($userlist, $form['submission_readers'],
      'sub_users', t('Individual users'), FALSE, '', 'edit-sub_others');

  $form['submission_readers']['sub_others'] = [
    '#type' => 'checkbox',
    '#title' => t('Everyone'),
    '#default_value' => $everyone,
    '#attributes' => ['onchange' => "if (this.checked) { this.form['sub_groups'].delAll(); this.form['sub_users'].delAll();} return true;"],
  ];
}

function _mm_webform_submissions_submit($form, FormStateInterface $form_state) {
  $db = Database::getConnection();
  $values = $form_state->getValues();
  $nid = $form_state->get('nid');
  _mm_webform_delete_submitted_readers($nid);
  if ($values['sub_others']) {
    $db->insert('webform_submitted_readers')
      ->fields(['nid' => $nid, 'gid' => 0])
      ->execute();
  }
  else {
    foreach ($values['sub_groups'] as $gid => $name) {
      if ($gid) {
        $db->insert('webform_submitted_readers')
          ->fields(['nid' => $nid, 'gid' => $gid])
          ->execute();
      }
    }

    $adhoc_gid = '';
    foreach ($values['sub_users'] as $uid => $name) {
      if (isset($uid)) {
        _mm_content_ad_hoc_group($adhoc_gid, $uid);
      }
    }
    if ($adhoc_gid != '') {
      $db->insert('webform_submitted_readers')
        ->fields(['nid' => $nid, 'gid' => $adhoc_gid])
        ->execute();
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function mm_webform_form_webform_handlers_form_alter(&$form, FormStateInterface &$form_state) {
  // Don't do anything if there's no node parameter in the URL.
  if (!($node = \Drupal::service('current_route_match')->getParameters()->get('node'))) {
    return;
  }
  $form['handlers']['#empty'] = t('There are currently no emails setup for this webform.');
  $form['actions']['submit']['#value'] = t('Save');
}

/**
 * Implements hook_node_links_alter().
 */
function mm_webform_node_links_alter(array &$links, NodeInterface $node, array &$context) {
  if (mm_webform_has_webform_field($node) && $node->getType() && ($webform = MMWebformAccess::getWebformForNode($node))) {
    // Change the node edit link to go to the Elements tab.
    if (!empty($links['monster_menus']['#links'])) {
      foreach ($links['monster_menus']['#links'] as &$link) {
        if ($link['url']->getRouteName() == 'entity.node.edit_form') {
          $options = $link['url']->getOptions();
          unset($options['query']['destination']);
          $link['url'] = new Url('mm_webform.edit_form', $link['url']->getRouteParameters(), $options);
        }
      }
    }

    // Add a View Submissions link, if possible.
    if ($webform->hasSubmissions() && MMWebformAccess::accessViewSubmission(\Drupal::currentUser(), $node)->isAllowed() && mm_module_exists('webform_node')) {
      $links['mm_webform'] = [
        '#theme' => 'links__node__mm_webform',
        '#links' => [
          'mm_webform_results' => [
            'title' => t('View submissions'),
            'url' => Url::fromRoute('entity.node.webform.results_submissions', ['node' => $node->id()]),
            'attributes' => ['title' => t('View data posted using this webform')],
          ]
        ],
        '#attributes' => ['class' => ['links', 'inline']],
      ];
    }
  }
}

/**
 * Implements hook_webform_source_entity_info_alter().
 */
function mm_webform_webform_source_entity_info_alter(&$info) {
  // When editing form elements the built-in
  // RouteParametersWebformSourceEntity detects the "node" parameter in the
  // URL, which causes problems later on. Replace it with a version that ignores
  // this menu route.
  if (isset($info['route_parameters'])) {
    $info['route_parameters']['class'] = MMWebformRouteParametersSourceEntity::class;
  }
}

/**
 * Implements hook_ENTITY_TYPE_access() for Node entitites.
 */
function mm_webform_node_access(NodeInterface $node, $op, AccountInterface $account) {
  if ($op == 'webform_submission_view' && mm_webform_has_webform_field($node)) {
    if (!empty($node->__get('sub_users')) && in_array($account->id(), array_keys($node->__get('sub_users')))) {
      return AccessResult::allowed();
    }

    if (!empty($node->__get('sub_groups')) && mm_content_get_uids_in_group(array_keys($node->__get('sub_groups')), $account->id())) {
      return AccessResult::allowed();
    }

    if (mm_content_user_can_node($node, Constants::MM_PERMS_WRITE)) {
      return AccessResult::allowed();
    }
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_ENTITY_TYPE_access() for Webform entitites.
 */
function mm_webform_webform_access(WebformInterface $webform, $op, AccountInterface $account) {
  static $cache = [];
  $cid = implode(':', [$account->id(), $webform->id(), $op]);
  // If this webform is attached to a node, use the node's access to determine
  // that of the webform.
  if (!isset($cache[$cid])) {
    $cache[$cid] = AccessResult::neutral();
    /** @var NodeInterface $node $node * */
    foreach (mm_webform_get_nodes_from_webform($webform) as $nid => $node) {
      $result = $node->access($op, $account, TRUE);
      if (!$result->isNeutral()) {
        return $cache[$cid] = $result;
      }
      // In the case of submission_create, being able to view the node is enough.
      if ($op == 'submission_create') {
        $result = $node->access('view', $account, TRUE);
        if (!$result->isNeutral()) {
          return $cache[$cid] = $result;
        }
      }
    }
  }
  return $cache[$cid];
}

/**
 * Implements hook_webform_submission_access().
 */
function mm_webform_webform_submission_access($submission, $op, AccountInterface $account, WebformInterface $webform = NULL) {
  static $cache = [];
  /** @var WebformSubmissionInterface $submission */
  $webform = $webform ?: $submission->getWebform();
  $access = WebformAccessResult::neutral();
  /** @var NodeInterface $node $node **/
  foreach (mm_webform_get_nodes_from_webform($webform) as $nid => $node) {
    if (!isset($cache[$nid][$op])) {
      if (!$submission && $op == 'view') {
        $cache[$nid][$op] = mm_webform_node_access($node, 'webform_submission_view', $account);
      }
      else {
        $cache[$nid][$op] = WebformAccessResult::forbidden();
        if ($node->access('update', $account)) {
          // admin user or editor of this node
          $cache[$nid]['view'] = $cache[$nid]['update'] = $cache[$nid]['delete'] = WebformAccessResult::allowed($submission, TRUE);
        }
        elseif ($op == 'view') {
          // everyone, or this user is in a matching group; can also include the
          // anonymous user (sr.gid = 0) if "everyone" is checked
          $cache[$nid]['view'] = WebformAccessResult::allowedIf(Database::getConnection()
              ->query(
                'SELECT COUNT(DISTINCT sr.gid) FROM {webform_submitted_readers} sr ' .
                'LEFT JOIN {mm_group} g ON sr.gid = g.gid ' .
                'LEFT JOIN {mm_virtual_group} v ON v.vgid = g.vgid ' .
                'WHERE sr.nid = :nid AND (sr.gid = 0 OR v.uid = :uid1 OR g.vgid = 0 AND g.uid = :uid2)',
                [':nid' => $nid, ':uid1' => $account->id(), ':uid2' => $account->id()])
              ->fetchField() != 0);
          $cache[$nid]['update'] = $cache[$nid]['delete'] = WebformAccessResult::forbidden($submission, TRUE);
        }
      }
    }
    if ($access->orIf($cache[$nid][$op])->isAllowed()) {
      // We can't return $access here, since it might be neutral.
      return WebformAccessResult::allowed($submission, TRUE);
    }
  }
  return $access;
}

/**
* Implements hook_node_view().
*/
function mm_webform_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
  if (mm_webform_has_webform_field($node)) {
    if (!mm_content_user_can_node($node, Constants::MM_PERMS_READ)) {
      mm_node_load_fail($node, $view_mode == 'teaser');
    }
  }
}

/**
* Implements hook_node_delete().
*/
function mm_webform_node_delete(NodeInterface $node) {
  if (mm_webform_has_webform_field($node)) {
    _mm_webform_delete_submitted_readers($node->id());
  }
}

function _mm_webform_delete_submitted_readers($nid) {
  $db = Database::getConnection();
  // first delete individual users and "Everyone"
  //    DELETE sr,g FROM {webform_submitted_readers} sr LEFT JOIN {mm_group} g ON sr.gid = g.gid WHERE sr.nid = $nid AND sr.gid <= 0
  $select = $db->select('webform_submitted_readers', 'sr');
  $select->leftJoin('mm_group', 'g', 'g.gid = sr.gid');
  $select_gids = $select->fields('sr', ['gid'])
    ->condition('sr.nid', $nid)
    ->condition('sr.gid', 0, '<=')
    ->execute()
    ->fetchCol();
  if (!empty($select_gids)) {
    $db->delete('webform_submitted_readers')
      ->condition('gid', $select_gids, 'IN')
      ->execute();
    $db->delete('mm_group')
      ->condition('gid', $select_gids, 'IN')
      ->execute();
  }

  // then delete any groups if they exist
  //    DELETE FROM {webform_submitted_readers} WHERE nid = $nid
  $db->delete('webform_submitted_readers')
    ->condition('nid', $nid)
    ->execute();
}

/**
* Implements hook_node_load().
*/
function mm_webform_node_load($nodes) {
  foreach ($nodes as $node) {
    if (mm_webform_has_webform_field($node)) {
      $node->__set('sub_others', FALSE);
      $node->__set('sub_groups', []);
      $node->__set('sub_users', []);
      $result = Database::getConnection()->query(
        'SELECT r.gid,t.name FROM {webform_submitted_readers} r ' .
          'LEFT JOIN {mm_tree} t ON r.gid = t.mmtid ' .
        'WHERE r.gid >= :gid AND nid = :nid ORDER BY t.name', [':gid' => 0, ':nid' => $node->id()]);
      foreach ($result as $r) {
        if ($r->gid == 0) {
          $node->__set('sub_others', TRUE);
        }
        else {
          $node->__get('sub_groups')[$r->gid] = $r->name;
        }
      }

      $have_users = FALSE;
      $result = Database::getConnection()->query('SELECT gid FROM {webform_submitted_readers} WHERE gid < :gid AND nid = :nid', [':gid' => 0, ':nid' => $node->id()]);
      foreach ($result as $r) {
        $users = mm_content_get_users_in_group($r->gid, NULL, TRUE, Constants::MM_UI_MAX_USERS_IN_GROUP);
        if (!is_null($users)) {
          $node->__set('sub_users', $users);
          $have_users = TRUE;
        }
      }

      if ($have_users || $node->__get('sub_groups')) {
        $node->__set('sub_others', FALSE);
      }
    }
  }
}

/**
 * Implements hook_mm_copy_tree_node_alter().
 */
function mm_webform_mm_copy_tree_node_alter(NodeInterface $node, $old_catlist) {
  // When copying a webform node, clone the underlying Webform entity.
  // We can't clone the form yet, because we don't know the new node ID, so
  // set the target_id to a dummy value and set a special field for later.
  if ($node->getType() == 'webform' && ($old_webform = MMWebformAccess::getWebformForNode($node))) {
    $node->set(mm_webform_get_webform_field($node)->getName(), [['target_id' => DUMMY_WEBFORM_ID]]);
    $node->__set('old_webform_id', $old_webform->id());
  }
}

/**
 * Implements hook_ENTITY_insert().
 */
function mm_webform_node_insert(NodeInterface $node) {
  // When copying a webform node, clone the underlying Webform entity.
  if ($node->getType() == 'webform' && !empty($node->old_webform_id) && ($webform = Webform::load($node->old_webform_id))) {
    $new_webform = $webform->createDuplicate();
    $new_webform->set($new_webform->getEntityType()->getKey('id'), 'webform_' . $node->id());
    $new_webform->save();

    $reloaded_node = Node::load($node->id());
    $reloaded_node->set(mm_webform_get_webform_field($node)->getName(), [['target_id' => $new_webform->id()]]);
    $reloaded_node->save();
  }
}

function mm_webform_has_webform_field(NodeInterface $node) {
  return \Drupal::service('webform.entity_reference_manager')->getFieldname($node);
}

function mm_webform_get_webform_field(NodeInterface $node) {
  if ($field_name = mm_webform_has_webform_field($node)) {
    return $node->getFieldDefinition($field_name);
  }
  return FALSE;
}

function mm_webform_get_node_types_with_webforms() {
  static $node_types;

  if (!isset($node_types)) {
    $node_types = [];
    $map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('webform');
    if (isset($map['node'])) {
      foreach ($map['node'] as $field_name => $field_def) {
        if ($field_def['type'] == 'webform') {
          foreach ($field_def['bundles'] as $bundle) {
            $node_types[$bundle] = 0;
          }
        }
      }
      $node_types = array_keys($node_types);
    }
  }
  return $node_types;
}

function mm_webform_get_nodes_from_webform(WebformInterface $webform) {
  static $node_types;
  $nodes = [];

  if (!isset($node_types)) {
    $node_types = [];
    $map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('webform');
    if (isset($map['node'])) {
      $test_ids = [$webform->getEntityTypeId(), $webform->id()];
      foreach ($map['node'] as $field_name => $field_def) {
        if ($field_def['type'] == 'webform') {
          foreach ($test_ids as $id) {
            if (isset($field_def['bundles'][$id])) {
              $node_types[$field_name] = $field_def['bundles'][$id];
            }
          }
        }
      }
    }
  }

  foreach ($node_types as $field_name => $node_type) {
    $nodes += \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties(['type' => $node_type, $field_name => $webform->id()]);
  }
  return $nodes;
}

/**
 * Implements hook_preprocess_menu_local_action().
 *
 * Add .button--secondary to add page and layout actions.
 *
 * @see Drupal.behaviors.webformUiElementsActionsSecondary
 */
function mm_webform_preprocess_menu_local_action(&$variables) {
  if (\Drupal::routeMatch()->getRouteName() != 'mm_webform.edit_form') {
    return;
  }

  if (!in_array($variables['link']['#url']->getRouteName(), ['mm_webform_ui.element.add_page', 'mm_webform_ui.element.add_layout'])) {
    return;
  }

  $variables['link']['#options']['attributes']['class'][] = 'button--secondary';
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc