monster_menus-9.0.x-dev/src/Plugin/MMSearchAction/ReplaceText.php
src/Plugin/MMSearchAction/ReplaceText.php
<?php
namespace Drupal\monster_menus\Plugin\MMSearchAction;
use Drupal\Core\Form\EnforcedResponseException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\monster_menus\Annotation\MMSearchAction;
use Drupal\monster_menus\Constants;
use Drupal\monster_menus\MMSearchAction\MMSearchActionBase;
use Drupal\node\Entity\Node;
/**
* Provides the MM Search Results Action to replace text within a node's title
* or body.
*
* @MMSearchAction(
* id = "mm_search_action_replace_text",
* label = @Translation("replace text"),
* description = @Translation("Provides the MM Search Results Action to replace text within a node's title or body."),
* useDrupalSettings = true,
* jsInit = "MMSR_init_action_replace_text",
* )
*/
class ReplaceText extends MMSearchActionBase {
use ResultsTrait;
final public const FIELD_TITLE = 'title';
final public const FIELD_BODY = 'body';
final public const METHOD_EXACT = 'exact';
final public const METHOD_REGEX = 'regex';
final public const SESSION_DATA = 'mmsr-rt';
private $error;
/**
* @inheritDoc
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['field'] = [
'#type' => 'select',
'#title' => $this->t('change the'),
'#options' => [
self::FIELD_TITLE => $this->t('title'),
self::FIELD_BODY => $this->t('body'),
],
'#default_value' => $_SESSION[self::SESSION_DATA]['field'] ?? self::FIELD_BODY,
];
$form['method'] = [
'#type' => 'select',
'#title' => $this->t('search for'),
'#options' => [
self::METHOD_EXACT => $this->t('the exact text'),
self::METHOD_REGEX => $this->t('the regular expression'),
],
'#default_value' => $_SESSION[self::SESSION_DATA]['method'] ?? self::METHOD_EXACT,
];
$form['from'] = [
'#type' => 'textarea',
'#default_value' => $_SESSION[self::SESSION_DATA]['from'] ?? '',
'#description' => 'placeholder',
'#rows' => 4,
];
$form['case'] = [
'#type' => 'checkbox',
'#title' => $this->t('case-sensitive'),
'#default_value' => $_SESSION[self::SESSION_DATA]['case'] ?? FALSE,
];
$form['to'] = [
'#type' => 'textarea',
'#title' => $this->t('change to'),
'#default_value' => $_SESSION[self::SESSION_DATA]['to'] ?? '',
'#description' => $this->t('Use <code>$1</code>, <code>$2</code>, etc. to substitute regex groupings.'),
'#rows' => 4,
];
$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('Replace Text'),
'#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(...), NULL);
$_SESSION[self::SESSION_DATA] = [
'field' => $this->values['field'],
'method' => $this->values['method'],
'from' => $this->values['from'],
'case' => $this->values['case'] ?? FALSE,
'to' => $this->values['to'],
];
if (!empty($this->error)) {
throw new EnforcedResponseException(mm_json_response([
'action_result' => $this->t('<span>Error evaluating regular expression: @error</span>', ['@error' => $this->error]),
'action_result_div' => '#mmsr-mp-status-text',
'action_result_js' => 'MMSR_action_modify_perms_update',
'mp_enable' => FALSE,
]));
}
$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++;
$field = $field_copy = $node->__get($this->values['field'])[0]->value;
switch ($this->values['method']) {
case self::METHOD_EXACT:
$field = !empty($this->values['case']) ?
str_replace($this->values['from'], $this->values['to'], $field) :
str_ireplace($this->values['from'], $this->values['to'], $field);
break;
case self::METHOD_REGEX:
$from = '{' . $this->values['from'] . '}s';
if (empty($this->values['case'])) {
$from .= 'i';
}
$field = preg_replace($from, $this->values['to'], $field);
if (is_null($field)) {
$this->error = preg_last_error() == PREG_INTERNAL_ERROR ? $this->t('Syntax error.') : preg_last_error_msg();
// Don't iterate anymore.
return 'error';
}
break;
}
if ($field != $field_copy) {
$this->countChanged++;
if ($this->updateNeeded) {
$node->__get($this->values['field'])[0]->value = $field;
$node->save();
}
}
}
}
}
/**
* @inheritDoc
*/
public function applies() {
return in_array($this->getConfiguration('search_type'), [self::SEARCH_TYPE_NODES, self::SEARCH_TYPE_NODES_ON_PAGES]);
}
/**
* @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;
}
}, NULL);
return !empty($return);
}
return FALSE;
}
}