Skip to content

Commit

Permalink
Merge pull request #1201 from laravel/mes/symlink-valet-socks
Browse files Browse the repository at this point in the history
Update `valet.sock` to be a symlink to an existing `valet{version}.sock` file
  • Loading branch information
mattstauffer authored Mar 14, 2022
2 parents 3570c74 + 383aa62 commit 80b7e61
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 206 deletions.
13 changes: 13 additions & 0 deletions cli/Valet/Nginx.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,17 @@ public function uninstall()
$this->brew->uninstallFormula('nginx nginx-full');
$this->cli->quietly('rm -rf '.BREW_PREFIX.'/etc/nginx '.BREW_PREFIX.'/var/log/nginx');
}

/**
* Return a list of all sites with explicit Nginx configurations.
*
* @return \Illuminate\Support\Collection
*/
public function configuredSites()
{
return collect($this->files->scandir(VALET_HOME_PATH.'/Nginx'))
->reject(function ($file) {
return starts_with($file, '.');
});
}
}
135 changes: 54 additions & 81 deletions cli/Valet/PhpFpm.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,16 @@ public function install()

$this->files->ensureDirExists(VALET_HOME_PATH.'/Log', user());

$this->createConfigurationFiles();
$phpVersion = $this->brew->linkedPhp();
$this->createConfigurationFiles($phpVersion);

// Remove old valet.sock
$this->files->unlink(VALET_HOME_PATH.'/valet.sock');
$this->cli->quietly('sudo rm '.VALET_HOME_PATH.'/valet.sock');

$this->restart();

$this->symlinkPrimaryValetSock($phpVersion);
}

/**
Expand All @@ -74,26 +81,23 @@ public function uninstall()
*
* Writes FPM config file, pointing to the correct .sock file, and log and ini files.
*
* @param string|null $phpVersion
* @param string $phpVersion
* @return void
*/
public function createConfigurationFiles($phpVersion = null)
public function createConfigurationFiles($phpVersion)
{
info(sprintf('Updating PHP configuration%s...', ($phpVersion ? ' for '.$phpVersion : '')));
info("Updating PHP configuration for {$phpVersion}...");

$fpmConfigFile = $this->fpmConfigPath($phpVersion);

$this->files->ensureDirExists(dirname($fpmConfigFile), user());

// Create FPM Config File from stub
$contents = str_replace(
['VALET_USER', 'VALET_HOME_PATH'],
[user(), VALET_HOME_PATH],
['VALET_USER', 'VALET_HOME_PATH', 'valet.sock'],
[user(), VALET_HOME_PATH, self::fpmSockName($phpVersion)],
$this->files->get(__DIR__.'/../stubs/etc-phpfpm-valet.conf')
);
if ($phpVersion) {
$contents = str_replace('valet.sock', self::fpmSockName($phpVersion), $contents);
}
$this->files->put($fpmConfigFile, $contents);

// Create other config files from stubs
Expand Down Expand Up @@ -210,7 +214,6 @@ public function isolateDirectory($directory, $version)
$this->brew->ensureInstalled($version, [], $this->taps);

$oldCustomPhpVersion = $this->site->customPhpVersion($site); // Example output: "74"
$this->cli->quietly('sudo rm '.VALET_HOME_PATH.'/'.$this->fpmSockName($oldCustomPhpVersion));
$this->createConfigurationFiles($version);

$this->site->isolate($site, $version);
Expand Down Expand Up @@ -245,6 +248,22 @@ public function unIsolateDirectory($directory)
info(sprintf('The site [%s] is now using the default PHP version.', $site));
}

/**
* List all directories with PHP isolation configured.
*
* @return \Illuminate\Support\Collection
*/
public function isolatedDirectories()
{
$configuredSites = $this->nginx->configuredSites();

return $configuredSites->filter(function ($item) {
return strpos($this->files->get(VALET_HOME_PATH.'/Nginx/'.$item), ISOLATED_PHP_VERSION) !== false;
})->map(function ($item) {
return ['url' => $item, 'version' => $this->normalizePhpVersion($this->site->customPhpVersion($item))];
});
}

/**
* Use a specific version of PHP globally.
*
Expand All @@ -269,15 +288,6 @@ public function useVersion($version, $force = false)

// Unlink the current global PHP if there is one installed
if ($this->brew->hasLinkedPhp()) {
$linkedPhp = $this->brew->linkedPhp();

// Update the old FPM to keep running, using a custom sock file, so existing isolated sites aren't broken
$this->createConfigurationFiles($linkedPhp);

// Update existing custom Nginx config files; if they're using the old or new PHP version,
// update them to the new correct sock file location
$this->updateConfigurationForGlobalUpdate($version, $linkedPhp);

$currentVersion = $this->brew->getLinkedPhpFormula();
info(sprintf('Unlinking current version: %s', $currentVersion));
$this->brew->unlink($currentVersion);
Expand All @@ -288,10 +298,6 @@ public function useVersion($version, $force = false)

$this->stopRunning();

// remove any orphaned valet.sock files that PHP didn't clean up due to version conflicts
$this->files->unlink(VALET_HOME_PATH.'/valet.sock');
$this->cli->quietly('sudo rm '.VALET_HOME_PATH.'/valet*.sock');

$this->install();

$newVersion = $version === 'php' ? $this->brew->determineAliasedVersion($version) : $version;
Expand All @@ -304,16 +310,23 @@ public function useVersion($version, $force = false)
return $newVersion;
}

/**
* Symlink (Capistrano-style) a given Valet.sock file to be the primary valet.sock.
*
* @param string $phpVersion
* @return void
*/
public function symlinkPrimaryValetSock($phpVersion)
{
$this->files->symlinkAsUser(VALET_HOME_PATH.'/'.$this->fpmSockName($phpVersion), VALET_HOME_PATH.'/valet.sock');
}

/**
* If passed php7.4, or php74, 7.4, or 74 formats, normalize to [email protected] format.
*/
public function normalizePhpVersion($version)
{
if (strpos($version, 'php') === false) {
$version = 'php'.$version;
}

return preg_replace('/(php)([0-9+])(?:.)?([0-9+])/i', '$1@$2.$3', $version);
return preg_replace('/(?:php@?)?([0-9+])(?:.)?([0-9+])/i', 'php@$1.$2', $version);
}

/**
Expand Down Expand Up @@ -356,42 +369,6 @@ public static function fpmSockName($phpVersion = null)
return "valet{$versionInteger}.sock";
}

/**
* Update all existing Nginx files when running a global PHP version update.
*
* If a given file is pointing to `valet.sock`, it's targeting the old global PHP version;
* update it to point to the new custom sock file for that version.
*
* If a given file is pointing the custom sock file for the new global version, that new
* version will now be hosted at `valet.sock`, so update the config file to point to that instead.
*
* @param string $newPhpVersion
* @param string $oldPhpVersion
* @return void
*/
public function updateConfigurationForGlobalUpdate($newPhpVersion, $oldPhpVersion)
{
collect($this->files->scandir(VALET_HOME_PATH.'/Nginx'))
->reject(function ($file) {
return starts_with($file, '.');
})
->each(function ($file) use ($newPhpVersion, $oldPhpVersion) {
$content = $this->files->get(VALET_HOME_PATH.'/Nginx/'.$file);

if (! starts_with($content, '# Valet isolated PHP version')) {
return;
}

if (strpos($content, self::fpmSockName($newPhpVersion)) !== false) {
info(sprintf('Updating site %s to keep using version: %s', $file, $newPhpVersion));
$this->files->put(VALET_HOME_PATH.'/Nginx/'.$file, str_replace(self::fpmSockName($newPhpVersion), 'valet.sock', $content));
} elseif (strpos($content, 'valet.sock') !== false) {
info(sprintf('Updating site %s to keep using version: %s', $file, $oldPhpVersion));
$this->files->put(VALET_HOME_PATH.'/Nginx/'.$file, str_replace('valet.sock', self::fpmSockName($oldPhpVersion), $content));
}
});
}

/**
* Get a list including the global PHP version and allPHP versions currently serving "isolated sites" (sites with
* custom Nginx configs pointing them to a specific PHP version).
Expand All @@ -404,23 +381,19 @@ public function utilizedPhpVersions()
return self::fpmSockName($this->normalizePhpVersion($version));
})->unique();

return collect($this->files->scandir(VALET_HOME_PATH.'/Nginx'))
->reject(function ($file) {
return starts_with($file, '.');
})
->map(function ($file) use ($fpmSockFiles) {
$content = $this->files->get(VALET_HOME_PATH.'/Nginx/'.$file);

// Get the normalized PHP version for this config file, if it's defined
foreach ($fpmSockFiles as $sock) {
if (strpos($content, $sock) !== false) {
// Extract the PHP version number from a custom .sock path;
// for example, "valet74.sock" will output "php74"
$phpVersion = 'php'.str_replace(['valet', '.sock'], '', $sock);

return $this->normalizePhpVersion($phpVersion); // Example output [email protected]
}
return $this->nginx->configuredSites()->map(function ($file) use ($fpmSockFiles) {
$content = $this->files->get(VALET_HOME_PATH.'/Nginx/'.$file);

// Get the normalized PHP version for this config file, if it's defined
foreach ($fpmSockFiles as $sock) {
if (strpos($content, $sock) !== false) {
// Extract the PHP version number from a custom .sock path;
// for example, "valet74.sock" will output "php74"
$phpVersion = 'php'.str_replace(['valet', '.sock'], '', $sock);

return $this->normalizePhpVersion($phpVersion); // Example output [email protected]
}
})->merge([$this->brew->getLinkedPhpFormula()])->filter()->unique()->values()->toArray();
}
})->merge([$this->brew->getLinkedPhpFormula()])->filter()->unique()->values()->toArray();
}
}
19 changes: 9 additions & 10 deletions cli/Valet/Site.php
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ public function secure($url, $siteConf = null, $certificateExpireInDays = 396, $

// If the user had isolated the PHP version for this site, swap out .sock file
if ($phpVersion) {
$siteConf = $this->replaceSockFile($siteConf, "valet{$phpVersion}.sock", $phpVersion);
$siteConf = $this->replaceSockFile($siteConf, $phpVersion);
}

$this->files->putAsUser($this->nginxPath($url), $siteConf);
Expand Down Expand Up @@ -706,16 +706,14 @@ public function buildSecureNginxServer($url, $siteConf = null)
*/
public function isolate($valetSite, $phpVersion)
{
$fpmSockName = PhpFpm::fpmSockName($phpVersion);

if ($this->files->exists($this->nginxPath($valetSite))) {
// Modify the existing config if it exists (likely because it's secured)
$siteConf = $this->files->get($this->nginxPath($valetSite));
$siteConf = $this->replaceSockFile($siteConf, $fpmSockName, $phpVersion);
$siteConf = $this->replaceSockFile($siteConf, $phpVersion);
} else {
$siteConf = str_replace(
['VALET_HOME_PATH', 'VALET_SERVER_PATH', 'VALET_STATIC_PREFIX', 'VALET_SITE', 'VALET_PHP_FPM_SOCKET', 'VALET_ISOLATED_PHP_VERSION'],
[VALET_HOME_PATH, VALET_SERVER_PATH, VALET_STATIC_PREFIX, $valetSite, $fpmSockName, $phpVersion],
[VALET_HOME_PATH, VALET_SERVER_PATH, VALET_STATIC_PREFIX, $valetSite, PhpFpm::fpmSockName($phpVersion), $phpVersion],
$this->replaceLoopback($this->files->get(__DIR__.'/../stubs/site.valet.conf'))
);
}
Expand Down Expand Up @@ -1084,7 +1082,7 @@ public function customPhpVersion($url)
if ($this->files->exists($this->nginxPath($url))) {
$siteConf = $this->files->get($this->nginxPath($url));

if (starts_with($siteConf, '# Valet isolated PHP version')) {
if (starts_with($siteConf, '# '.ISOLATED_PHP_VERSION)) {
$firstLine = explode(PHP_EOL, $siteConf)[0];

return preg_replace("/[^\d]*/", '', $firstLine); // Example output: "74" or "81"
Expand All @@ -1096,15 +1094,16 @@ public function customPhpVersion($url)
* Replace .sock file in an Nginx site configuration file contents.
*
* @param string $siteConf
* @param string $sockFile
* @param string $phpVersion
* @return string
*/
public function replaceSockFile($siteConf, $sockFile, $phpVersion)
public function replaceSockFile($siteConf, $phpVersion)
{
$sockFile = PhpFpm::fpmSockName($phpVersion);

$siteConf = preg_replace('/valet[0-9]*.sock/', $sockFile, $siteConf);
$siteConf = preg_replace('/# Valet isolated PHP version.*\n/', '', $siteConf); // Remove `Valet isolated PHP version` line from config
$siteConf = preg_replace('/# '.ISOLATED_PHP_VERSION.'.*\n/', '', $siteConf); // Remove ISOLATED_PHP_VERSION line from config

return '# Valet isolated PHP version : '.$phpVersion.PHP_EOL.$siteConf;
return '# '.ISOLATED_PHP_VERSION.'='.$phpVersion.PHP_EOL.$siteConf;
}
}
2 changes: 2 additions & 0 deletions cli/includes/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

define('BREW_PREFIX', (new CommandLine())->runAsUser('printf $(brew --prefix)'));

define('ISOLATED_PHP_VERSION', 'ISOLATED_PHP_VERSION');

/**
* Output the given text to the console.
*
Expand Down
2 changes: 1 addition & 1 deletion cli/stubs/site.valet.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Valet isolated PHP version : VALET_ISOLATED_PHP_VERSION
# ISOLATED_PHP_VERSION=VALET_ISOLATED_PHP_VERSION
server {
listen 127.0.0.1:80;
server_name VALET_SITE www.VALET_SITE *.VALET_SITE;
Expand Down
50 changes: 33 additions & 17 deletions cli/valet.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
*/
Container::setInstance(new Container);

$version = '2.18.9';
$version = '2.18.10';

$app = new Application('Laravel Valet', $version);

Expand Down Expand Up @@ -210,6 +210,17 @@
info('The ['.$url.'] site will now serve traffic over HTTP.');
})->descriptions('Stop serving the given domain over HTTPS and remove the trusted TLS certificate');

/**
* Get all the current secured sites.
*/
$app->command('secured', function () {
$sites = collect(Site::secured())->map(function ($url) {
return ['Site' => $url];
});

table(['Site'], $sites->all());
});

/**
* Create an Nginx proxy config for the specified domain.
*/
Expand Down Expand Up @@ -491,9 +502,9 @@
]);

/**
* Allow the user to change the version of php valet uses.
* Allow the user to change the version of php Valet uses.
*/
$app->command('use [phpVersion] [--force] [--site=]', function ($phpVersion, $force, $site) {
$app->command('use [phpVersion] [--force]', function ($phpVersion, $force) {
if (! $phpVersion) {
$path = getcwd().'/.valetphprc';
$linkedVersion = Brew::linkedPhp();
Expand All @@ -509,30 +520,35 @@
}
}

PhpFpm::useVersion($phpVersion, $force, $site);
})->descriptions('Change the version of PHP used by valet', [
PhpFpm::useVersion($phpVersion, $force);
})->descriptions('Change the version of PHP used by Valet', [
'phpVersion' => 'The PHP version you want to use, e.g [email protected]',
'--site' => 'Isolate PHP version of a specific valet site. e.g: --site=site.test',
]);

/**
* Allow the user to change the version of php valet uses to serve a given site.
* Allow the user to change the version of PHP Valet uses to serve the current site.
*/
$app->command('isolate [site] [phpVersion] ', function ($site, $phpVersion) {
PhpFpm::isolateDirectory($site, $phpVersion);
})->descriptions('Change the version of PHP used by valet to serve a given site', [
'site' => 'The valet site (e.g. site.test) you want to isolate to a given PHP version',
$app->command('isolate [phpVersion] ', function ($phpVersion) {
PhpFpm::isolateDirectory(basename(getcwd()), $phpVersion);
})->descriptions('Change the version of PHP used by Valet to serve the current working directory', [
'phpVersion' => 'The PHP version you want to use, e.g [email protected]',
]);

/**
* Allow the user to un-do specifying the version of php valet uses to serve a given site.
* Allow the user to un-do specifying the version of PHP Valet uses to serve the current site.
*/
$app->command('unisolate [site] ', function ($site) {
PhpFpm::unIsolateDirectory($site);
})->descriptions('Stop customizing the version of PHP used by valet to serve a given site', [
'site' => 'The valet site (e.g. site.test) you want to un-isolate',
]);
$app->command('unisolate', function () {
PhpFpm::unIsolateDirectory(basename(getcwd()));
})->descriptions('Stop customizing the version of PHP used by Valet to serve the current working directory');

/**
* List isolated sites.
*/
$app->command('isolated', function () {
$sites = PhpFpm::isolatedDirectories();

table(['Path', 'PHP Version'], $sites->all());
})->descriptions('List all sites using isolated versions of PHP.');

/**
* Tail log file.
Expand Down
Loading

0 comments on commit 80b7e61

Please sign in to comment.