/**
  *
  * @param String $pathLocation - enter dot for anything in current directory.
  * @param String $logFileLocation - where should the log file be saved. This file contains all the details about actual changes made.
  * @param String $to - if you set this to, for example 3.0 then the code will be upgraded from 2.4 to 3.0.
  * @param Boolean $doBasicReplacement - If set to false to show proposed changes on screen. If set to true, basic replacements (i.e. straight forward replace A with B scenarios will be made)
  * @param Boolean $markStickingPoints - If set to false nothing happens, if set to true  any code that need changing manually will be marked in the code itself.
  * @param Array $ignoreFolderArray - a list of folders that should not be searched (and replaced) - folders that are automatically ignore are: CMS, SAPPHIRE, FRAMEWORK (all in lowercase)
  * outputs to screen and/or to file
  */
 public function run($pathLocation = ".", $logFileLocation = "", $to = "3.0", $doBasicReplacement = false, $markStickingPoints = false, $ignoreFolderArray = array())
 {
     if (!file_exists($pathLocation)) {
         $this->addToOutput("\n\n");
         user_error("ERROR: could not find specified path: " . $pathLocation);
         $this->addToOutput("\n\n");
         $this->addToOutput("---END ---\n");
     }
     if ($this->checkReplacementIssues) {
         $this->checkReplacementIssues();
         $this->addToOutput("---END ---\n");
     }
     //basic checks
     if (!$doBasicReplacement && $markStickingPoints) {
         user_error("You have to set doBasicReplacement = TRUE before you can set markStickingPoints = TRUE");
     }
     if (!is_array($ignoreFolderArray)) {
         user_error("the ignoreFolderArray param should be an array");
     }
     $style = "BASIC";
     if ($markStickingPoints) {
         $style = "COMPLICATED";
     }
     if ($doBasicReplacement) {
         $this->addToOutput("\n#################################### \n    REAL {$style} REPLACEMENTS \n####################################\n ");
     } else {
         $this->addToOutput("\n#################################### \n    TEST ALL REPLACEMENTS ONLY \n#################################### \n ");
         $logFileLocation = null;
     }
     //get replacements
     $replacementDataObject = new ReplacementData();
     $previousTos = $replacementDataObject->getTos();
     $previousMigrationsDone = true;
     $migrationChecksDone = false;
     $this->numberOfStraightReplacements = 0;
     $this->numberOfAllReplacements = 0;
     foreach ($previousTos as $previousTo) {
         $totalForOneVersion = 0;
         $this->addToOutput("\n------------------------------------\nUpgrade to Silverstripe: {$previousTo} \n------------------------------------");
         if ($to == $previousTo) {
             $migrationChecksDone = true;
             if (!$previousMigrationsDone) {
                 echo $this->printItNow();
                 die("\nError: Your code is not ready to migrate to {$to} (see above)");
             }
         }
         $numberToAdd = $this->numberOfReplacements($pathLocation, $previousTo, $ignoreFolderArray, true);
         $totalForOneVersion += $numberToAdd;
         $this->numberOfStraightReplacements += $numberToAdd;
         if ($this->numberOfStraightReplacements == 0) {
             $this->addToOutput("\n[BASIC: DONE] migration to {$previousTo} for basic replacements completed.");
         } else {
             $this->addToOutput("\n[BASIC: TO DO] migration to {$previousTo} for basic replacements NOT completed yet ({$numberToAdd} items to do).");
             $previousMigrationsDone = false;
         }
         $numberToAdd = $this->numberOfReplacements($pathLocation, $previousTo, $ignoreFolderArray, false);
         $totalForOneVersion += $numberToAdd;
         $this->numberOfAllReplacements += $numberToAdd;
         if ($this->numberOfAllReplacements == 0) {
             $this->addToOutput("\n[COMPLEX: DONE] migration to {$previousTo} for complicated items completed.");
         } else {
             $this->addToOutput("\n[COMPLEX: UNSURE] migration to {$previousTo} for complicated items NOT completed yet ({$numberToAdd} items to do).");
         }
         $this->addToOutput("\n------------------------------------\n{$totalForOneVersion} items to do for {$previousTo} \n------------------------------------\n");
         $totalForOneVersion = 0;
         $this->addToOutput("\n\n");
         if ($migrationChecksDone) {
             break;
         }
     }
     $textSearchMachine = new TextSearch();
     //set basics
     $textSearchMachine->addIgnoreFolderArray($ignoreFolderArray);
     //setting extensions to search files within
     $textSearchMachine->setBasePath($pathLocation);
     if ($logFileLocation) {
         $textSearchMachine->setLogFileLocation($logFileLocation);
     } else {
         $textSearchMachine->setLogFileLocation($pathLocation . "/ss_upgrade_log.txt");
     }
     $array = $replacementDataObject->getReplacementArrays($to);
     foreach ($array as $extension => $extensionArray) {
         $this->addToOutput("\n\n\n\n++++++++++++++++++++++++++++++++++++ \n    CHECKING {$extension} FILES \n++++++++++++++++++++++++++++++++++++ \n\n\n\n");
         $textSearchMachine->setExtensions(array($extension));
         //setting extensions to search files within
         foreach ($extensionArray as $replaceArray) {
             $find = $replaceArray[0];
             //$replace = $replaceArray[1]; unset($replaceArray[1]);
             //$fullReplacement = (isset($replaceArray[2]) ? "/* ".$replaceArray[2]." */\n" : "").$replaceArray[1];
             $fullReplacement = "";
             $isStraightReplace = true;
             if (isset($replaceArray[2])) {
                 // Has comment
                 $isStraightReplace = false;
                 $fullReplacement = "/*\n" . $this->marker . "\nFIND: " . $replaceArray[0] . "\nNOTE: " . $replaceArray[2] . " \n" . $this->endMarker . "\n*/" . $replaceArray[1];
             } else {
                 // Straight replace
                 $fullReplacement = $replaceArray[1];
             }
             $comment = isset($replaceArray[2]) ? $replaceArray[2] : "";
             $codeReplacement = $replaceArray[1];
             if (!$find) {
                 user_error("no find is specified, replace is: {$replace}");
             }
             if (!$fullReplacement) {
                 user_error("no replace is specified, find is: {$find}");
             }
             if ($doBasicReplacement) {
                 if (!$markStickingPoints && !$isStraightReplace) {
                     continue;
                 }
                 $textSearchMachine->setSearchKey($find, 0, $isStraightReplace ? "BASIC" : "COMPLEX");
                 $textSearchMachine->setReplacementKey($fullReplacement);
                 $textSearchMachine->startSearching();
                 //starting search
                 //output - only write to log for real replacements!
                 //$textSearchMachine->writeLogToFile($logFileLocation);
             } else {
                 $textSearchMachine->setSearchKey($find, 0, $isStraightReplace ? "BASIC" : "COMPLEX");
                 $textSearchMachine->setFutureReplacementKey($codeReplacement);
                 $textSearchMachine->startSearching();
                 //starting search
                 //output - only write to log for real replacements!
             }
             //$textSearchMachine->showLog();//showing log
         }
         $replacements = $textSearchMachine->showFormattedSearchTotals(false);
         if ($replacements) {
             $this->addToOutput($textSearchMachine->getOutput());
         } else {
             //flush output anyway!
             $textSearchMachine->getOutput();
             $this->addToOutput("\n No replacements for  {$extension} \n------------------------------------\n");
         }
     }
     return $this->printItNow();
 }