platform/src/Core/Framework/Update/Services/UpdateHtaccess.php line 33

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Update\Services;
  3. use Shopware\Core\Framework\Update\Event\UpdatePostFinishEvent;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. class UpdateHtaccess implements EventSubscriberInterface
  6. {
  7.     private const MARKER_START '# BEGIN Shopware';
  8.     private const MARKER_STOP '# END Shopware';
  9.     private const INSTRUCTIONS '# The directives (lines) between "# BEGIN Shopware" and "# END Shopware" are dynamically generated. Any changes to the directives between these markers will be overwritten.';
  10.     private const OLD_FILES = [
  11.         '9ab5be8c4bbff3490f3ae367af8a30d7'// https://github.com/shopware/production/commit/bebf9adc90bf5d7b0d53a149cc5bdba328696086
  12.         'ba812f2a64b337b032b10685ca6e2308'// https://github.com/shopware/production/commit/18ce6ffc904b8d2d237dc4ee6654c1fa9a6df719
  13.     ];
  14.     private string $htaccessPath;
  15.     public function __construct(string $htaccessPath)
  16.     {
  17.         $this->htaccessPath $htaccessPath;
  18.     }
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         return [
  22.             UpdatePostFinishEvent::class => 'update',
  23.         ];
  24.     }
  25.     public function update(): void
  26.     {
  27.         if (!file_exists($this->htaccessPath) || !file_exists($this->htaccessPath '.dist')) {
  28.             return;
  29.         }
  30.         if (\in_array(md5_file($this->htaccessPath), self::OLD_FILEStrue)) {
  31.             $this->replaceFile($this->htaccessPath);
  32.             return;
  33.         }
  34.         $content file_get_contents($this->htaccessPath);
  35.         // User has deleted the markers. So we will ignore the update process
  36.         if (strpos($contentself::MARKER_START) === false || strpos($contentself::MARKER_STOP) === false) {
  37.             return;
  38.         }
  39.         $this->updateByMarkers($this->htaccessPath);
  40.     }
  41.     /**
  42.      * Replace entire .htaccess from dist
  43.      */
  44.     private function replaceFile(string $path): void
  45.     {
  46.         $dist $path '.dist';
  47.         if (!file_exists($dist)) {
  48.             return;
  49.         }
  50.         $perms fileperms($dist);
  51.         copy($dist$path);
  52.         if ($perms) {
  53.             chmod($path$perms 0644);
  54.         }
  55.     }
  56.     private function updateByMarkers(string $path): void
  57.     {
  58.         [$pre$_$post] = $this->getLinesFromMarkedFile($path);
  59.         [$_$existing$_] = $this->getLinesFromMarkedFile($path '.dist');
  60.         if (!\in_array(self::INSTRUCTIONS$existingtrue)) {
  61.             array_unshift($existingself::INSTRUCTIONS);
  62.         }
  63.         array_unshift($existingself::MARKER_START);
  64.         $existing[] = self::MARKER_STOP;
  65.         $newFile implode("\n"array_merge($pre$existing$post));
  66.         $perms fileperms($path);
  67.         file_put_contents($path$newFile);
  68.         if ($perms) {
  69.             chmod($path$perms 0644);
  70.         }
  71.     }
  72.     private function getLinesFromMarkedFile(string $path): array
  73.     {
  74.         $fp fopen($path'rb+');
  75.         if (!$fp) {
  76.             return [];
  77.         }
  78.         $lines = [];
  79.         while (!feof($fp)) {
  80.             if ($line fgets($fp)) {
  81.                 $lines[] = rtrim($line"\r\n");
  82.             }
  83.         }
  84.         $foundStart false;
  85.         $foundStop false;
  86.         $preLines = [];
  87.         $postLines = [];
  88.         $existingLines = [];
  89.         foreach ($lines as $line) {
  90.             if (!$foundStart && strpos($lineself::MARKER_START) === 0) {
  91.                 $foundStart true;
  92.                 continue;
  93.             }
  94.             if (!$foundStop && strpos($lineself::MARKER_STOP) === 0) {
  95.                 $foundStop true;
  96.                 continue;
  97.             }
  98.             if (!$foundStart) {
  99.                 $preLines[] = $line;
  100.             } elseif ($foundStop) {
  101.                 $postLines[] = $line;
  102.             } else {
  103.                 $existingLines[] = $line;
  104.             }
  105.         }
  106.         return [$preLines$existingLines$postLines];
  107.     }
  108. }