diff --git a/cli/Valet/Configuration.php b/cli/Valet/Configuration.php index 6492809e4..7905bde5e 100644 --- a/cli/Valet/Configuration.php +++ b/cli/Valet/Configuration.php @@ -431,7 +431,10 @@ public function read(): array { } /** - * Get an item from the configuration file using "dot" notation. + * Get an item from the configuration file. + * + * @uses Arr:get Gets a value from a nested array using "dot" notation. + * @link https://laravel.com/docs/13.x/helpers#method-array-get * * @param string|int|null $key * @param mixed $default @@ -445,6 +448,9 @@ public function get($key, $default = null) { /** * Update a specific key in the configuration file. * + * @uses Arr:set Sets a value within a nested array using "dot" notation. + * @link https://laravel.com/docs/13.x/helpers#method-array-set + * * @param string $key * @param mixed $value * @@ -452,7 +458,25 @@ public function get($key, $default = null) { */ public function updateKey(string $key, $value): array { return tap($this->read(), function (&$config) use ($key, $value) { - $config[$key] = $value; + Arr::set($config, $key, $value); + + $this->write($config); + }); + } + + /** + * Remove a specific key from the configuration file. + * + * @uses Arr:forget Removes a value within a nested array using "dot" notation. + * @link https://laravel.com/docs/13.x/helpers#method-array-forget + * + * @param string $key + * + * @return array + */ + public function removeKey(string $key): array { + return tap($this->read(), function (&$config) use ($key) { + Arr::forget($config, $key); $this->write($config); }); diff --git a/cli/Valet/Upgrader.php b/cli/Valet/Upgrader.php index 1e7e90671..3ffd7b3bc 100644 --- a/cli/Valet/Upgrader.php +++ b/cli/Valet/Upgrader.php @@ -72,14 +72,16 @@ private function pruneSymbolicLinks() { * This is a one-time upgrade that will be run when Valet is first installed. */ private function upgradeSymbolicLinks() { + // Migrate legacy symlinks upgrade key to the new format. + $this->migrateSymlinksUpgradeKey(); + if ($this->shouldUpgradeSymbolicLinks()) { info("Upgrading your linked sites from the old junction links to symbolic links..."); // Convert all junction links to symbolic links. $this->files->convertJunctionsToSymlinks($this->site->sitesPath()); - // Add a new key to the config file to indicate that the symlinks have been upgraded. - // This will prevent the upgrade from running again, since it is a one-time upgrade. - $this->config->updateKey("symlinks_upgraded", true); + // Mark this upgrade as complete so it will not run again. + $this->markAsUpgraded('symlinks'); info("Successfully upgraded junction links to symbolic links."); } @@ -96,9 +98,7 @@ private function upgradeSymbolicLinks() { * 2. The sites directory is not empty (`$isDirEmpty` is `false`). */ private function shouldUpgradeSymbolicLinks() { - // Get the value of the "symlinks_upgraded" key from the config. - // If the key doesn't exist, it will return false. - $symlinksUpgraded = $this->config->get("symlinks_upgraded", false); + $symlinksUpgraded = $this->isUpgraded('symlinks'); // Check if the sites directory is empty. $isDirEmpty = $this->files->isDirEmpty($this->site->sitesPath()); @@ -256,14 +256,14 @@ public function fixOldSampleValetDriver(): void { */ private function upgradeNginxSitePhpPortOverrides() { // If the PHP port definitions have already been upgraded, skip. - if (!$this->shouldUpgradeNginxSitePhpPortOverrides()) { + if ($this->isUpgraded('nginx_site_php_port_overrides')) { return; } // If the Nginx config directory doesn't exist, skip and mark it as upgraded to prevent // this from running again. if (!$this->files->exists($this->site->nginxPath())) { - $this->config->updateKey('php_port_overrides_upgraded', true); + $this->markAsUpgraded('nginx_site_php_port_overrides'); return; } @@ -293,15 +293,50 @@ private function upgradeNginxSitePhpPortOverrides() { info("Upgraded {$upgraded} Nginx site config(s) to the new PHP port override format."); } - $this->config->updateKey('php_port_overrides_upgraded', true); + $this->markAsUpgraded('nginx_site_php_port_overrides'); } /** - * Determine whether Nginx site PHP port overrides should be upgraded. + * Determine if a named upgrade has already been completed. + * + * @param string $upgradeId * * @return bool */ - private function shouldUpgradeNginxSitePhpPortOverrides() { - return !$this->config->get('php_port_overrides_upgraded', false); + private function isUpgraded(string $upgradeId): bool { + return $this->config->get("upgrades.{$upgradeId}", false); + } + + /** + * Mark a named upgrade as completed in the configuration. + * + * @param string $upgradeId + */ + private function markAsUpgraded(string $upgradeId): void { + $this->config->updateKey("upgrades.{$upgradeId}", true); + } + + /** + * Migrate legacy `symlinks_upgraded` upgrade key to the new `symlinks` key under + * the `upgrades` array in the configuration (`upgrades.symlinks`). + * + * If the legacy key exists but the new key doesn't, it marks the upgrade as completed, + * and removes legacy key from configuration. + */ + private function migrateSymlinksUpgradeKey(): void { + $legacyUpgradeKey = 'symlinks_upgraded'; + $newUpgradeKey = 'symlinks'; + + $hasNewKey = $this->config->get("upgrades.{$newUpgradeKey}", false); + $hasLegacyKey = $this->config->get($legacyUpgradeKey, false); + + // If the legacy key exists AND the new key doesn't, + // mark the new upgrade key as upgraded. + if ($hasLegacyKey && !$hasNewKey) { + $this->markAsUpgraded($newUpgradeKey); + } + + // Remove the legacy upgrade key to clean up the config. + $this->config->removeKey($legacyUpgradeKey); } }