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.

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