Repo for the search and displace core module including the interface to select files and search and displace operations to run on them. https://searchanddisplace.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.2 KiB

3 years ago
3 years ago
  1. <?php
  2. namespace App\SearchDisplace;
  3. use App\SearchDisplace\Searchers\Searcher;
  4. class SearchAndDisplace
  5. {
  6. protected $documentContent;
  7. protected $info;
  8. protected $searchOnly = false;
  9. public function __construct($documentContent, $info, $searchOnly = false)
  10. {
  11. $this->documentContent = $documentContent;
  12. $this->info = $info;
  13. $this->searchOnly = $searchOnly;
  14. }
  15. public function execute()
  16. {
  17. $searchResult = $this->search();
  18. if ($this->searchOnly) {
  19. return $searchResult;
  20. }
  21. return $this->displace($searchResult);
  22. }
  23. /**
  24. *
  25. * @return mixed
  26. * @throws \Exception
  27. */
  28. protected function search()
  29. {
  30. $searcher = new Searcher($this->info['searchers'], $this->documentContent);
  31. return $searcher->execute();
  32. }
  33. protected function displace($searchResult)
  34. {
  35. $replacementIndexes = [];
  36. $replacements = [];
  37. foreach ($this->info['searchers'] as $searcher) {
  38. $replacements[$searcher['key']] = $searcher;
  39. }
  40. $searchers = [];
  41. foreach ($searchResult as $searcher => $searcherResults) {
  42. $replacementIndexes[$searcher] = [];
  43. foreach ($searcherResults as $searcherResult) {
  44. $searchers[$searcherResult['start']] = array_merge($searcherResult, [
  45. 'searcher' => $searcher
  46. ]);
  47. }
  48. }
  49. ksort($searchers);
  50. $updatedDocumentContent = '';
  51. $currentIndex = 0;
  52. foreach ($searchers as $s => $searcherItem) {
  53. $partialContent = substr($this->documentContent, $currentIndex, $searcherItem['start'] - $currentIndex);
  54. $updatedDocumentContent = $updatedDocumentContent . $partialContent;
  55. $start = mb_strlen($updatedDocumentContent);
  56. $replacementValue = $replacements[$searcherItem['searcher']]['type'] === 'replace'
  57. ? $replacements[$searcherItem['searcher']]['value']
  58. : $this->getDisplaceValue($replacements[$searcherItem['searcher']]['value'], $searcherItem['content']);
  59. $updatedDocumentContent = $updatedDocumentContent . $replacementValue;
  60. $end = mb_strlen($updatedDocumentContent) - 1;
  61. if ($start <= $end) {
  62. $replacementIndexes[$searcherItem['searcher']][] = [
  63. 'start' => $start,
  64. 'end' => $end,
  65. 'original_start' => $searcherItem['start'],
  66. 'original_end' => $searcherItem['end'],
  67. ];
  68. }
  69. $currentIndex = $searcherItem['end'] + 1;
  70. }
  71. if ($currentIndex < strlen($this->documentContent) - 1) {
  72. $updatedDocumentContent = $updatedDocumentContent . substr($this->documentContent, $currentIndex);
  73. }
  74. return [
  75. 'content' => $updatedDocumentContent,
  76. 'indexes' => $replacementIndexes,
  77. ];
  78. }
  79. protected function getDisplaceValue($displaceValue, $content)
  80. {
  81. // return "<$displaceValue>$content</$displaceValue>";
  82. return "{{$displaceValue}}{$content}{/{$displaceValue}}";
  83. }
  84. }