Skip to content
Snippets Groups Projects

Draft: Take translations into account to find and replace searched text

Files
3
+ 115
166
@@ -40,52 +40,81 @@ class Node extends Entity {
$conditionVals = parent::buildCondition($values['search'], $values['mode'], $values['wholeword'], $values['regex'], $values['preceded'], $values['followed']);
$this->addQueryCondition($query, $conditionVals, $fieldname, $values['mode'], $values['language']);
// Disable the normal access check.
// Run Drupal database query.
$query->accessCheck(FALSE);
$nids = $query->execute();
// Iterate over matched entities (nodes) in all saerched languages
// to extract information that will be rendered in the results.
$languages = $values['language'] === 'all' ? array_keys(AdminHelper::getAllEnabledLanguages()) : [$values['language']];
foreach ($nids as $nid) {
foreach ($languages as $language) {
// Results key must be unique, accounting for > 1 language.
$result_key = $values['language'] === 'all' ? "$nid-$language" : "$nid";
$node = CoreNode::load($nid);
if (!$node->hasTranslation($language)) {
continue;
}
$node = $node->getTranslation($language);
$nodeField = $node->get($fieldname);
$fieldType = $nodeField->getFieldDefinition()->getType();
if (in_array($fieldType, ['text_with_summary', 'text', 'text_long'])) {
// @todo Add support for fields with cardinality > 1.
$fieldValue = $nodeField->getValue()[0] ?? [];
// Find all instances of the term we're looking for.
preg_match_all($conditionVals['phpRegex'], $fieldValue['value'], $matches, PREG_OFFSET_CAPTURE);
if (empty($matches) || !isset($matches[0]) || !isset($matches[0][0])) {
// Match not guaranteed for nodes with > 1 language.
continue;
}
$entities = $query->execute();
// Iterate over matched entities (nodes) to extract information that will
// be rendered in the results.
foreach ($entities as $id) {
$node = CoreNode::load($id);
$nodeField = $node->get($fieldname);
$fieldType = $nodeField->getFieldDefinition()->getType();
if (in_array($fieldType, ['text_with_summary', 'text', 'text_long'])) {
$fieldValue = $nodeField->getValue()[0];
$title_collect[$id]['title'] = $node->getTitle();
// Find all instances of the term we're looking for.
preg_match_all($conditionVals['phpRegex'], $fieldValue['value'], $matches, PREG_OFFSET_CAPTURE);
$newValues = [];
// Build an array of strings which are displayed in the results.
foreach ($matches[0] as $v) {
// The offset of the matched term(s) in the field's text.
$start = $v[1];
if ($values['preceded'] !== '') {
// Bolding won't work if starting position is in the middle of a
// word (non-word bounded searches), therefore move the start
// position back as many character as there are in the 'preceded'
// text.
$start -= strlen($values['preceded']);
// Build an array of strings which are displayed in the results.
$newValues = [];
foreach ($matches[0] as $v) {
// The offset of the matched term(s) in the field's text.
$start = $v[1];
if ($values['preceded'] !== '') {
// Bolding won't work if starting position is in the middle of
// a word (non-word bounded searches), therefore move the start
// position back as many character as there are in the
// 'preceded' text.
$start -= strlen($values['preceded']);
}
// Extract part of the text which include the search term plus six
// "words" following it. After finding the string, bold the search
// term.
$replaced = preg_replace($conditionVals['phpRegex'], "<strong>$v[0]</strong>", preg_split("/\s+/", substr($fieldValue['value'], $start), 6));
if (count($replaced) > 1) {
// The final index contains the remainder of the text, which we
// don't care about, so we discard it.
array_pop($replaced);
}
$newValues[] = implode(' ', $replaced);
}
// Extract part of the text which include the search term plus six
// "words" following it. After finding the string, bold the search
// term.
$replaced = preg_replace($conditionVals['phpRegex'], "<strong>$v[0]</strong>", preg_split("/\s+/", substr($fieldValue['value'], $start), 6));
if (count($replaced) > 1) {
// The final index contains the remainder of the text, which we
// don't care about, so we discard it.
array_pop($replaced);
$title_collect[$result_key]['title'] = $node->getTitle();
$title_collect[$result_key]['field'] = $newValues;
$title_collect[$result_key]['view_url'] = $node->toUrl()->toString();
$title_collect[$result_key]['edit_url'] = $node->toUrl('edit-form')->toString();
}
elseif (in_array($fieldType, ['string', 'link'])) {
preg_match($conditionVals['phpRegex'], $nodeField->getString(), $matches, PREG_OFFSET_CAPTURE);
if (empty($matches) || !isset($matches[0]) || !isset($matches[0][0])) {
// Match not guaranteed for nodes with > 1 language.
continue;
}
$newValues[] = implode(' ', $replaced);
$match = $matches[0][0];
$replaced = preg_replace($conditionVals['phpRegex'], "<strong>$match</strong>", $nodeField->getString());
$title_collect[$result_key]['title'] = $node->getTitle();
$title_collect[$result_key]['field'] = [$replaced];
$title_collect[$result_key]['view_url'] = $node->toUrl()->toString();
$title_collect[$result_key]['edit_url'] = $node->toUrl('edit-form')->toString();
}
$title_collect[$id]['field'] = $newValues;
}
elseif (in_array($fieldType, ['string', 'link'])) {
$title_collect[$id]['title'] = $node->getTitle();
preg_match($conditionVals['phpRegex'], $nodeField->getString(), $matches, PREG_OFFSET_CAPTURE);
$match = $matches[0][0];
$replaced = preg_replace($conditionVals['phpRegex'], "<strong>$match</strong>", $nodeField->getString());
$title_collect[$id]['field'] = [$replaced];
}
}
}
@@ -101,9 +130,12 @@ class Node extends Entity {
*/
public function replace(string $field, array $values, array $undo_data): array {
$data = $undo_data;
[$entityType, $bundle, $fieldname] = explode(':', $field);
try {
// $field will be string composed of entity type, bundle name, and field
// name delimited by ':' characters.
[$entityType, $bundle, $fieldname] = explode(':', $field);
$query = $this->entityTypeManager->getStorage($entityType)->getQuery();
$query->condition('type', $bundle);
if ($values['published']) {
@@ -115,77 +147,53 @@ class Node extends Entity {
// Disable the normal access check.
$query->accessCheck(FALSE);
$entities = $query->execute();
$languages = $values['language'] === 'all' ? array_keys(AdminHelper::getAllEnabledLanguages()) : [$values['language']];
$nids = $query->execute();
foreach ($entities as $id) {
$node = CoreNode::load($id);
$nodeField = $node->get($fieldname);
$fieldType = $nodeField->getFieldDefinition()->getType();
if (in_array($fieldType, ['text_with_summary', 'text', 'text_long'])) {
if ($values['language'] === 'all') {
$other_languages = AdminHelper::getAllEnabledLanguages();
foreach ($other_languages as $langcode => $languageName) {
if ($node->hasTranslation($langcode)) {
$node = $node->getTranslation($langcode);
$nodeField = $node->get($fieldname);
}
$fieldValue = $nodeField->getValue()[0];
// Replace the search term with the replacement term.
$fieldValue['value'] = preg_replace($conditionVals['phpRegex'], $values['replace'], $fieldValue['value']);
$node->$fieldname = $fieldValue;
}
// Iterate over matched entities (nodes) to perform the replacement.
foreach ($nids as $nid) {
foreach ($languages as $language) {
$node = CoreNode::load($nid);
if ($node->hasTranslation($language)) {
$node = $node->getTranslation($language);
}
else {
$requested_lang = $values['language'];
if ($node->hasTranslation($requested_lang)) {
$node = $node->getTranslation($requested_lang);
$nodeField = $node->get($fieldname);
}
$fieldValue = $nodeField->getValue()[0];
$nodeField = $node->get($fieldname);
$fieldType = $nodeField->getFieldDefinition()->getType();
if (in_array($fieldType, ['text_with_summary', 'text', 'text_long'])) {
// @todo Add support for fields with cardinality > 1.
$fieldValue = $nodeField->getValue()[0] ?? [];
// Replace the search term with the replacement term.
$fieldValue['value'] = preg_replace($conditionVals['phpRegex'], $values['replace'], $fieldValue['value']);
$node->$fieldname = $fieldValue;
}
if (!isset($data["node:$id"]['new_vid'])) {
$data["node:$id"]['old_vid'] = $node->vid->getString();
// Crete a new revision so that we can have the option of undoing it
// later on.
$node->setNewRevision();
$node->revision_log = $this->t('Replaced %search with %replace via Scanner Search and Replace module.', [
'%search' => $values['search'],
'%replace' => $values['replace'],
]);
$node->setRevisionUserId($this->currentUser->id());
elseif ($fieldType == 'string') {
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $nodeField->getString());
$node->$fieldname = $fieldValue;
}
// Save the updated node.
$node->save();
// Fetch the new revision id.
$data["node:$id"]['new_vid'] = $node->vid->getString();
}
elseif ($fieldType == 'string') {
if (!isset($data["node:$id"]['new_vid'])) {
if ($values['language'] === 'all') {
$all_languages = AdminHelper::getAllEnabledLanguages();
foreach ($all_languages as $langcode => $languageName) {
if ($node->hasTranslation($langcode)) {
$node = $node->getTranslation($langcode);
$nodeField = $node->get($fieldname);
elseif ($fieldType == 'link') {
$new_value = [];
foreach ($nodeField->getValue() as $delta => $field_value) {
foreach ($field_value as $field_element => $field_element_value) {
if (is_string($field_element_value)) {
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $field_element_value);
}
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $nodeField->getString());
$node->$fieldname = $fieldValue;
}
}
else {
$requested_lang = $values['language'];
if ($node->hasTranslation($requested_lang)) {
// $nodeField = $nodeField->getTranslation($requested_lang);
$node = $node->getTranslation($requested_lang);
$nodeField = $node->get($fieldname);
else {
$fieldValue = $field_element_value;
}
$new_value[$delta][$field_element] = $fieldValue;
}
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $nodeField->getString());
$node->$fieldname = $fieldValue;
}
$data["node:$id"]['old_vid'] = $node->vid->getString();
$node->$fieldname = $new_value;
}
// Create a new revision and save the node for this translation.
if (!isset($data["node:$nid"]['new_vid'])) {
$data["node:$nid"]['old_vid'] = $node->vid->getString();
// Crete a new revision so that we can have the option of undoing it
// later on.
$node->setNewRevision();
$node->revision_log = $this->t('Replaced %search with %replace via Scanner Search and Replace module.', [
'%search' => $values['search'],
@@ -193,70 +201,11 @@ class Node extends Entity {
]);
$node->setRevisionUserId($this->currentUser->id());
}
// Save the updated node.
$node->save();
$data["node:$id"]['new_vid'] = $node->vid->getString();
}
elseif ($fieldType == 'link') {
if (!isset($data["node:$id"]['new_vid'])) {
if ($values['language'] === 'all') {
$all_languages = AdminHelper::getAllEnabledLanguages();
foreach ($all_languages as $langcode => $languageName) {
if ($node->hasTranslation($langcode)) {
$node = $node->getTranslation($langcode);
$nodeField = $node->get($fieldname);
}
$new_value = [];
foreach ($nodeField->getValue() as $delta => $field_value) {
foreach ($field_value as $field_element => $field_element_value) {
if (is_string($field_element_value)) {
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $field_element_value);
}
else {
$fieldValue = $field_element_value;
}
$new_value[$delta][$field_element] = $fieldValue;
}
}
$node->$fieldname = $new_value;
}
$data["node:$id"]['old_vid'] = $node->vid->getString();
$node->setNewRevision();
$node->revision_log = $this->t('Replaced %search with %replace via Scanner Search and Replace module.', [
'%search' => $values['search'],
'%replace' => $values['replace'],
]);
}
else {
$requested_lang = $values['language'];
if ($node->hasTranslation($requested_lang)) {
// $nodeField = $nodeField->getTranslation($requested_lang);
$node = $node->getTranslation($requested_lang);
$nodeField = $node->get($fieldname);
}
$new_value = [];
foreach ($nodeField->getValue() as $delta => $field_value) {
foreach ($field_value as $field_element => $field_element_value) {
if (is_string($field_element_value)) {
$fieldValue = preg_replace($conditionVals['phpRegex'], $values['replace'], $field_element_value);
}
else {
$fieldValue = $field_element_value;
}
$new_value[$delta][$field_element] = $fieldValue;
}
}
$node->$fieldname = $new_value;
$data["node:$id"]['old_vid'] = $node->vid->getString();
$node->setNewRevision();
$node->revision_log = $this->t('Replaced %search with %replace via Scanner Search and Replace module.', [
'%search' => $values['search'],
'%replace' => $values['replace'],
]);
}
}
$node->setRevisionUserId($this->currentUser->id());
$node->save();
$data["node:$id"]['new_vid'] = $node->vid->getString();
// Fetch the new revision id.
$data["node:$nid"]['new_vid'] = $node->vid->getString();
}
}
}
Loading