Source of file SearchAndReplace.php
Size: 10,592 Bytes - Last Modified: 2020-07-03T12:08:09+00:00
/var/www/docs.ssmods.com/process/src/src/Tasks/IndividualTasks/SearchAndReplace.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 | <?php namespace Sunnysideup\UpgradeToSilverstripe4\Tasks\IndividualTasks; use Sunnysideup\UpgradeToSilverstripe4\Api\LoadReplacementData; use Sunnysideup\UpgradeToSilverstripe4\Api\SearchAndReplaceAPI; use Sunnysideup\UpgradeToSilverstripe4\Tasks\Task; /** * Replaces a bunch of code snippets in preparation of the upgrade. * Controversial replacements will be replaced with a comment * next to it so you can review replacements easily. */ class SearchAndReplace extends Task { protected $taskStep = 's30'; /** * for debugging purposes * @var bool */ protected $debug = false; /** * check if there are double-ups in replacement. * @var bool */ protected $checkReplacementIssues = false; /** * string used to show issues in replacement in the actual code being replaced. * * @var string */ protected $replacementHeader = 'automated upgrade'; /** * folder containing the replacement file * * @var string */ protected $folderContainingReplacementData = ''; /** * list of folders to ignore in search and replace * @var array */ protected $ignoreFolderArray = [ '.git', '.svn', ]; /** * the names of the folder that contains the data we need * e.g. SS4 / SS37 * IMPORTANT! * * @var array */ protected $sourceFolders = [ 'SS4', ]; public function getTitle() { return 'Search and Replace'; } public function getDescription() { return ' Replaces a bunch of code snippets in preparation of the upgrade. Controversial replacements will be replaced with a comment next to it so you can review replacements easily.'; } public function setCheckReplacementIssues(bool $b) { $this->checkReplacementIssues = $b; return $this; } public function setIgnoreFolderArray(array $a) { $this->ignoreFolderArray = $a; return $this; } public function setFolderContainingReplacementData(string $s) { $this->folderContainingReplacementData = $s; return $this; } public function setSourceFolders(array $a) { $this->sourceFolders = $a; return $this; } public function runActualTask($params = []) { //replacement data $replacementDataObjects = $this->getReplacementDataObjects(); foreach ($replacementDataObjects as $replacementDataObject) { if ($this->checkReplacementIssues) { $this->checkReplacementDataIssues($replacementDataObject); } $replacementArray = $replacementDataObject->getReplacementArrays(); if ($this->debug) { $this->mu()->colourPrint($replacementArray); } //replace API foreach ($this->mu()->getExistingModuleDirLocationsWithThemeFolders() as $moduleOrThemeDir) { $textSearchMachine = new SearchAndReplaceAPI($moduleOrThemeDir); $textSearchMachine->setIsReplacingEnabled(true); $textSearchMachine->addToIgnoreFolderArray($this->ignoreFolderArray); foreach ($replacementArray as $path => $pathArray) { $path = $moduleOrThemeDir . '/' . $path ?: ''; $path = $this->mu()->checkIfPathExistsAndCleanItUp($path); if (! file_exists($path)) { $this->mu()->colourPrint("SKIPPING ${path}"); } else { $textSearchMachine->setSearchPath($path); foreach ($pathArray as $extension => $extensionArray) { //setting extensions to search files within $textSearchMachine->setExtensions(explode('|', $extension)); $this->mu()->colourPrint( "++++++++++++++++++++++++++++++++++++\n" . "CHECKING\n" . "IN ${path}\n" . "FOR ${extension} FILES\n" . 'BASE ' . $moduleOrThemeDir . "\n" . "++++++++++++++++++++++++++++++++++++\n" ); foreach ($extensionArray as $find => $findDetails) { $replace = isset($findDetails['R']) ? $findDetails['R'] : $find; $comment = isset($findDetails['C']) ? $findDetails['C'] : ''; $ignoreCase = isset($findDetails['I']) ? $findDetails['I'] : false; $caseSensitive = ! $ignoreCase; //$replace = $replaceArray[1]; unset($replaceArray[1]); //$fullReplacement = // (isset($replaceArray[2]) ? "/* ".$replaceArray[2]." */\n" : "").$replaceArray[1]; $fullReplacement = $replace; $isStraightReplace = true; if ($comment) { $isStraightReplace = false; } if (! $find) { user_error("no find is specified, replace is: ${replace}"); } if (! $fullReplacement) { user_error(' No replace is specified, find is: ${find}. We suggest setting your final replace to a single space if you would like to replace with NOTHING. '); } $replaceKey = $isStraightReplace ? 'BASIC' : 'COMPLEX'; $textSearchMachine->setSearchKey($find, $caseSensitive, $replaceKey); $textSearchMachine->setReplacementKey($fullReplacement); if ($comment) { $textSearchMachine->setComment($comment); } $textSearchMachine->setReplacementHeader($this->replacementHeader); $textSearchMachine->startSearchAndReplace(); } $replacements = $textSearchMachine->showFormattedSearchTotals(); if ($replacements) { } else { //flush output anyway! $this->mu()->colourPrint("No replacements for ${extension}"); } $this->mu()->colourPrint($textSearchMachine->getOutput()); } } } } } } protected function hasCommitAndPush() { return true; } protected function getReplacementDataObjects(): array { $array = []; foreach ($this->sourceFolders as $sourceFolder) { $array[] = new LoadReplacementData( $this->mu(), $this->folderContainingReplacementData, $sourceFolder ); } return $array; } /** * 1. check that one find is not used twice: * find can be found 2x * @param mixed $replacementDataObject */ private function checkReplacementDataIssues($replacementDataObject) { $replacementDataObject->getReplacementArrays(null); $arrLanguages = $replacementDataObject->getLanguages(); $fullFindArray = $replacementDataObject->getFlatFindArray(); $fullReplaceArray = $replacementDataObject->getFlatReplacedArray(); //1. check that one find may not stop another replacement. foreach ($arrLanguages as $language) { if (! isset($fullFindArray[$language])) { continue; } unset($keyOuterDoneSoFar); $keyOuterDoneSoFar = []; foreach ($fullFindArray[$language] as $keyOuter => $findStringOuter) { $keyOuterDoneSoFar[$keyOuter] = true; foreach ($fullFindArray[$language] as $keyInner => $findStringInner) { if (! isset($keyOuterDoneSoFar[$keyInner])) { if ($keyOuter !== $keyInner) { $findStringOuterReplaced = str_replace($findStringInner, '...', $findStringOuter); if ($findStringOuter === $findStringInner || $findStringOuterReplaced !== $findStringOuter) { $this->mu()->colourPrint(" ERROR in ${language}: \t\t we are trying to find the same thing twice (A and B) ---- A: (${keyOuter}): \t\t ${findStringOuter} ---- B: (${keyInner}): \t\t ${findStringInner}"); } } } } } } //2. check that a replacement is not mentioned before the it is being replaced foreach ($arrLanguages as $language) { if (! isset($fullReplaceArray[$language])) { continue; } unset($keyOuterDoneSoFar); $keyOuterDoneSoFar = []; foreach ($fullReplaceArray[$language] as $keyOuter => $findStringOuter) { $keyOuterDoneSoFar[$keyOuter] = true; foreach ($fullFindArray[$language] as $keyInner => $findStringInner) { if (isset($keyOuterDoneSoFar[$keyInner])) { if ($keyOuter !== $keyInner) { $findStringOuterReplaced = str_replace($findStringInner, '...', $findStringOuter); if ($findStringOuter === $findStringInner || $findStringOuterReplaced !== $findStringOuter) { $this->mu()->colourPrint(" ERROR in ${language}: \t\t there is a replacement (A) that was earlier tried to be found (B). ---- A: (${keyOuter}): \t\t ${findStringOuter} ---- B: (${keyInner}): \t\t ${findStringInner}"); } } } } } } $this->mu()->colourPrint(''); } } |