summaryrefslogtreecommitdiff
path: root/app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php')
-rw-r--r--app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php313
1 files changed, 171 insertions, 142 deletions
diff --git a/app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php b/app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php
index 4fc78f0d53..3003201798 100644
--- a/app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php
+++ b/app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php
@@ -25,165 +25,194 @@ use Throwable;
/**
* Class BatchUpdateSearchReplacePlugin Batch Update plugin: search/replace
*/
-class BatchUpdateSearchReplacePlugin extends BatchUpdateBasePlugin {
- /** @var string Search string */
- private $search;
+class BatchUpdateSearchReplacePlugin extends BatchUpdateBasePlugin
+{
+ /** @var string Search string */
+ private $search;
- /** @var string Replace string */
- private $replace;
+ /** @var string Replace string */
+ private $replace;
- /** @var string simple/wildcards/regex */
- private $method;
+ /** @var string simple/wildcards/regex */
+ private $method;
- /** @var string Search string, converted to a regex */
- private $regex;
+ /** @var string Search string, converted to a regex */
+ private $regex;
- /** @var string "i" for case insensitive, "" for case sensitive */
- private $case;
+ /** @var string "i" for case insensitive, "" for case sensitive */
+ private $case;
- /** @var string Message for bad user parameters */
- private $error;
+ /** @var string Message for bad user parameters */
+ private $error;
- /**
- * User-friendly name for this plugin.
- *
- * @return string
- */
- public function getName() {
- return I18N::translate('Search and replace');
- }
+ /**
+ * User-friendly name for this plugin.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return I18N::translate('Search and replace');
+ }
- /**
- * Description / help-text for this plugin.
- *
- * @return string
- */
- public function getDescription() {
- return /* I18N: Description of the “Search and replace” option of the batch update module */ I18N::translate('Search and replace text, using simple searches or advanced pattern matching.');
- }
+ /**
+ * Description / help-text for this plugin.
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return /* I18N: Description of the “Search and replace” option of the batch update module */
+ I18N::translate('Search and replace text, using simple searches or advanced pattern matching.');
+ }
- /**
- * This plugin will update all types of record.
- *
- * @return string[]
- */
- public function getRecordTypesToUpdate() {
- return ['INDI', 'FAM', 'SOUR', 'REPO', 'NOTE', 'OBJE'];
- }
+ /**
+ * This plugin will update all types of record.
+ *
+ * @return string[]
+ */
+ public function getRecordTypesToUpdate()
+ {
+ return [
+ 'INDI',
+ 'FAM',
+ 'SOUR',
+ 'REPO',
+ 'NOTE',
+ 'OBJE',
+ ];
+ }
- /**
- * Does this record need updating?
- *
- * @param GedcomRecord $record
- *
- * @return bool
- */
- public function doesRecordNeedUpdate(GedcomRecord $record): bool {
- $gedcom = $record->getGedcom();
+ /**
+ * Does this record need updating?
+ *
+ * @param GedcomRecord $record
+ *
+ * @return bool
+ */
+ public function doesRecordNeedUpdate(GedcomRecord $record): bool
+ {
+ $gedcom = $record->getGedcom();
- return !$this->error && preg_match('/(?:' . $this->regex . ')/mu' . $this->case, $gedcom);
- }
+ return !$this->error && preg_match('/(?:' . $this->regex . ')/mu' . $this->case, $gedcom);
+ }
- /**
- * Apply any updates to this record
- *
- * @param GedcomRecord $record
- *
- * @return string
- */
- public function updateRecord(GedcomRecord $record): string {
- $old_gedcom = $record->getGedcom();
+ /**
+ * Apply any updates to this record
+ *
+ * @param GedcomRecord $record
+ *
+ * @return string
+ */
+ public function updateRecord(GedcomRecord $record): string
+ {
+ $old_gedcom = $record->getGedcom();
- // Allow "\n" to indicate a line-feed in replacement text.
- // Back-references such as $1, $2 are handled automatically.
- $new_gedcom = preg_replace('/' . $this->regex . '/mu' . $this->case, str_replace('\n', "\n", $this->replace), $old_gedcom);
+ // Allow "\n" to indicate a line-feed in replacement text.
+ // Back-references such as $1, $2 are handled automatically.
+ $new_gedcom = preg_replace('/' . $this->regex . '/mu' . $this->case, str_replace('\n', "\n", $this->replace), $old_gedcom);
- return $new_gedcom;
- }
+ return $new_gedcom;
+ }
- /**
- * Process the user-supplied options.
- *
- * @param Request $request
- */
- public function getOptions(Request $request) {
- parent::getOptions($request);
+ /**
+ * Process the user-supplied options.
+ *
+ * @param Request $request
+ */
+ public function getOptions(Request $request)
+ {
+ parent::getOptions($request);
- $this->search = $request->get('search', '');
- $this->replace = $request->get('replace', '');
- $this->method = $request->get('method', 'exact');
- $this->case = $request->get('case', '');
+ $this->search = $request->get('search', '');
+ $this->replace = $request->get('replace', '');
+ $this->method = $request->get('method', 'exact');
+ $this->case = $request->get('case', '');
- $this->error = '';
- switch ($this->method) {
- case 'exact':
- $this->regex = preg_quote($this->search, '/');
- break;
- case 'words':
- $this->regex = '\b' . preg_quote($this->search, '/') . '\b';
- break;
- case 'wildcards':
- $this->regex = '\b' . str_replace(['\*', '\?'], ['.*', '.'], preg_quote($this->search, '/')) . '\b';
- break;
- case 'regex':
- $this->regex = $this->search;
- // Check for invalid regular expressions.
- // A valid regex on a null string returns zero.
- // An invalid regex on a null string returns false and throws a warning.
- try {
- preg_match('/' . $this->search . '/', null);
- } catch (Throwable $ex) {
- DebugBar::addThrowable($ex);
+ $this->error = '';
+ switch ($this->method) {
+ case 'exact':
+ $this->regex = preg_quote($this->search, '/');
+ break;
+ case 'words':
+ $this->regex = '\b' . preg_quote($this->search, '/') . '\b';
+ break;
+ case 'wildcards':
+ $this->regex = '\b' . str_replace([
+ '\*',
+ '\?',
+ ], [
+ '.*',
+ '.',
+ ], preg_quote($this->search, '/')) . '\b';
+ break;
+ case 'regex':
+ $this->regex = $this->search;
+ // Check for invalid regular expressions.
+ // A valid regex on a null string returns zero.
+ // An invalid regex on a null string returns false and throws a warning.
+ try {
+ preg_match('/' . $this->search . '/', null);
+ } catch (Throwable $ex) {
+ DebugBar::addThrowable($ex);
- $this->error = '<div class="alert alert-danger">' . /* I18N: http://en.wikipedia.org/wiki/Regular_expression */ I18N::translate('The regular expression appears to contain an error. It can’t be used.') . '</div>';
- }
- break;
- }
- }
+ $this->error = '<div class="alert alert-danger">' . /* I18N: http://en.wikipedia.org/wiki/Regular_expression */
+ I18N::translate('The regular expression appears to contain an error. It can’t be used.') . '</div>';
+ }
+ break;
+ }
+ }
- /**
- * Generate a form to ask the user for options.
- *
- * @return string
- */
- public function getOptionsForm() {
- $descriptions = [
- 'exact' => I18N::translate('Match the exact text, even if it occurs in the middle of a word.'),
- 'words' => I18N::translate('Match the exact text, unless it occurs in the middle of a word.'),
- 'wildcards' => I18N::translate('Use a “?” to match a single character, use “*” to match zero or more characters.'),
- 'regex' => /* I18N: http://en.wikipedia.org/wiki/Regular_expression */ I18N::translate('Regular expressions are an advanced pattern matching technique.') . '<br>' . /* I18N: %s is a URL */ I18N::translate('See %s for more information.', '<a href="http://php.net/manual/regexp.reference.php">php.net/manual/regexp.reference.php</a>'),
- ];
+ /**
+ * Generate a form to ask the user for options.
+ *
+ * @return string
+ */
+ public function getOptionsForm()
+ {
+ $descriptions = [
+ 'exact' => I18N::translate('Match the exact text, even if it occurs in the middle of a word.'),
+ 'words' => I18N::translate('Match the exact text, unless it occurs in the middle of a word.'),
+ 'wildcards' => I18N::translate('Use a “?” to match a single character, use “*” to match zero or more characters.'),
+ 'regex' => /* I18N: http://en.wikipedia.org/wiki/Regular_expression */
+ I18N::translate('Regular expressions are an advanced pattern matching technique.') . '<br>' . /* I18N: %s is a URL */
+ I18N::translate('See %s for more information.', '<a href="http://php.net/manual/regexp.reference.php">php.net/manual/regexp.reference.php</a>'),
+ ];
- return
- '<div class="row form-group">' .
- '<label class="col-sm-3 col-form-label">' . I18N::translate('Search text/pattern') . '</label>' .
- '<div class="col-sm-9">' .
- '<input class="form-control" name="search" size="40" value="' . e($this->search) .
- '" onchange="this.form.submit();">' .
- '</div></div>' .
- '<div class="row form-group">' .
- '<label class="col-sm-3 col-form-label">' . I18N::translate('Replacement text') . '</label>' .
- '<div class="col-sm-9">' .
- '<input class="form-control" name="replace" size="40" value="' . e($this->replace) .
- '" onchange="this.form.submit();"></td></tr>' .
- '</div></div>' .
- '<div class="row form-group">' .
- '<label class="col-sm-3 col-form-label">' . I18N::translate('Search method') . '</label>' .
- '<div class="col-sm-9">' .
- '<select class="form-control" name="method" onchange="this.form.submit();">' .
- '<option value="exact" ' . ($this->method == 'exact' ? 'selected' : '') . '>' . I18N::translate('Exact text') . '</option>' .
- '<option value="words" ' . ($this->method == 'words' ? 'selected' : '') . '>' . I18N::translate('Whole words only') . '</option>' .
- '<option value="wildcards" ' . ($this->method == 'wildcards' ? 'selected' : '') . '>' . I18N::translate('Wildcards') . '</option>' .
- '<option value="regex" ' . ($this->method == 'regex' ? 'selected' : '') . '>' . I18N::translate('Regular expression') . '</option>' .
- '</select>' .
- '<p class="small text-muted">' . $descriptions[$this->method] . '</p>' . $this->error .
- '</div></div>' .
- '<div class="row form-group">' .
- '<label class="col-sm-3 col-form-label">' . I18N::translate('Case insensitive') . '</label>' .
- '<div class="col-sm-9">' .
- Bootstrap4::radioButtons('case', ['' => I18N::translate('no'), 'i' => I18N::translate('yes')], ($this->case ? 'i' : ''), true, ['onchange' => 'this.form.submit();']) .
- '<p class="small text-muted">' . /* I18N: Help text for "Case insensitive" searches */ I18N::translate('Match both upper and lower case letters.') . '</p>' .
- '</div></div>' .
- parent::getOptionsForm();
- }
+ return
+ '<div class="row form-group">' .
+ '<label class="col-sm-3 col-form-label">' . I18N::translate('Search text/pattern') . '</label>' .
+ '<div class="col-sm-9">' .
+ '<input class="form-control" name="search" size="40" value="' . e($this->search) .
+ '" onchange="this.form.submit();">' .
+ '</div></div>' .
+ '<div class="row form-group">' .
+ '<label class="col-sm-3 col-form-label">' . I18N::translate('Replacement text') . '</label>' .
+ '<div class="col-sm-9">' .
+ '<input class="form-control" name="replace" size="40" value="' . e($this->replace) .
+ '" onchange="this.form.submit();"></td></tr>' .
+ '</div></div>' .
+ '<div class="row form-group">' .
+ '<label class="col-sm-3 col-form-label">' . I18N::translate('Search method') . '</label>' .
+ '<div class="col-sm-9">' .
+ '<select class="form-control" name="method" onchange="this.form.submit();">' .
+ '<option value="exact" ' . ($this->method == 'exact' ? 'selected' : '') . '>' . I18N::translate('Exact text') . '</option>' .
+ '<option value="words" ' . ($this->method == 'words' ? 'selected' : '') . '>' . I18N::translate('Whole words only') . '</option>' .
+ '<option value="wildcards" ' . ($this->method == 'wildcards' ? 'selected' : '') . '>' . I18N::translate('Wildcards') . '</option>' .
+ '<option value="regex" ' . ($this->method == 'regex' ? 'selected' : '') . '>' . I18N::translate('Regular expression') . '</option>' .
+ '</select>' .
+ '<p class="small text-muted">' . $descriptions[$this->method] . '</p>' . $this->error .
+ '</div></div>' .
+ '<div class="row form-group">' .
+ '<label class="col-sm-3 col-form-label">' . I18N::translate('Case insensitive') . '</label>' .
+ '<div class="col-sm-9">' .
+ Bootstrap4::radioButtons('case', [
+ '' => I18N::translate('no'),
+ 'i' => I18N::translate('yes'),
+ ], ($this->case ? 'i' : ''), true, ['onchange' => 'this.form.submit();']) .
+ '<p class="small text-muted">' . /* I18N: Help text for "Case insensitive" searches */
+ I18N::translate('Match both upper and lower case letters.') . '</p>' .
+ '</div></div>' .
+ parent::getOptionsForm();
+ }
}