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';
}
