diff options
Diffstat (limited to 'app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php')
| -rw-r--r-- | app/Module/BatchUpdate/BatchUpdateSearchReplacePlugin.php | 313 |
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(); + } } |
