diff --git a/cli/Valet/Drivers/Specific/StatamicV2ValetDriver.php b/cli/Valet/Drivers/Specific/StatamicV2ValetDriver.php new file mode 100644 index 0000000..4eee35c --- /dev/null +++ b/cli/Valet/Drivers/Specific/StatamicV2ValetDriver.php @@ -0,0 +1,127 @@ +isActualFile($staticFilePath = $sitePath.$uri)) { + return $staticFilePath; + } elseif ($this->isActualFile($staticFilePath = $sitePath.'/public'.$uri)) { + return $staticFilePath; + } + + return false; + } + + /** + * Get the fully resolved path to the application's front controller. + */ + public function frontControllerPath(string $sitePath, string $siteName, string $uri): ?string + { + if ($_SERVER['REQUEST_METHOD'] === 'GET' && $this->isActualFile($staticPath = $this->getStaticPath($sitePath))) { + return $staticPath; + } + + if ($uri === '/installer.php') { + return $sitePath.'/installer.php'; + } + + $scriptName = '/index.php'; + + if ($this->isActualFile($sitePath.'/index.php')) { + $indexPath = $sitePath.'/index.php'; + } + + if ($isAboveWebroot = $this->isActualFile($sitePath.'/public/index.php')) { + $indexPath = $sitePath.'/public/index.php'; + } + + $sitePathPrefix = ($isAboveWebroot) ? $sitePath.'/public' : $sitePath; + + if ($locale = $this->getUriLocale($uri)) { + if ($this->isActualFile($localeIndexPath = $sitePathPrefix.'/'.$locale.'/index.php')) { + // Force trailing slashes on locale roots. + if ($uri === '/'.$locale) { + header('Location: '.$uri.'/'); + exit; + } + + $indexPath = $localeIndexPath; + $scriptName = '/'.$locale.'/index.php'; + } + } + + $_SERVER['SCRIPT_NAME'] = $scriptName; + $_SERVER['SCRIPT_FILENAME'] = $sitePathPrefix.$scriptName; + + return $indexPath; + } + + /** + * Get the locale from this URI. + */ + public function getUriLocale(string $uri): ?string + { + $parts = explode('/', $uri); + $locale = $parts[1]; + + if (count($parts) < 2 || ! in_array($locale, $this->getLocales())) { + return null; + } + + return $locale; + } + + /** + * Get the list of possible locales used in the first segment of a URI. + */ + public function getLocales(): array + { + return [ + 'af', 'ax', 'al', 'dz', 'as', 'ad', 'ao', 'ai', 'aq', 'ag', 'ar', 'am', 'aw', 'au', 'at', 'az', 'bs', 'bh', + 'bd', 'bb', 'by', 'be', 'bz', 'bj', 'bm', 'bt', 'bo', 'bq', 'ba', 'bw', 'bv', 'br', 'io', 'bn', 'bg', 'bf', + 'bi', 'cv', 'kh', 'cm', 'ca', 'ky', 'cf', 'td', 'cl', 'cn', 'cx', 'cc', 'co', 'km', 'cg', 'cd', 'ck', 'cr', + 'ci', 'hr', 'cu', 'cw', 'cy', 'cz', 'dk', 'dj', 'dm', 'do', 'ec', 'eg', 'sv', 'gq', 'er', 'ee', 'et', 'fk', + 'fo', 'fj', 'fi', 'fr', 'gf', 'pf', 'tf', 'ga', 'gm', 'ge', 'de', 'gh', 'gi', 'gr', 'gl', 'gd', 'gp', 'gu', + 'gt', 'gg', 'gn', 'gw', 'gy', 'ht', 'hm', 'va', 'hn', 'hk', 'hu', 'is', 'in', 'id', 'ir', 'iq', 'ie', 'im', + 'il', 'it', 'jm', 'jp', 'je', 'jo', 'kz', 'ke', 'ki', 'kp', 'kr', 'kw', 'kg', 'la', 'lv', 'lb', 'ls', 'lr', + 'ly', 'li', 'lt', 'lu', 'mo', 'mk', 'mg', 'mw', 'my', 'mv', 'ml', 'mt', 'mh', 'mq', 'mr', 'mu', 'yt', 'mx', + 'fm', 'md', 'mc', 'mn', 'me', 'ms', 'ma', 'mz', 'mm', 'na', 'nr', 'np', 'nl', 'nc', 'nz', 'ni', 'ne', 'ng', + 'nu', 'nf', 'mp', 'no', 'om', 'pk', 'pw', 'ps', 'pa', 'pg', 'py', 'pe', 'ph', 'pn', 'pl', 'pt', 'pr', 'qa', + 're', 'ro', 'ru', 'rw', 'bl', 'sh', 'kn', 'lc', 'mf', 'pm', 'vc', 'ws', 'sm', 'st', 'sa', 'sn', 'rs', 'sc', + 'sl', 'sg', 'sx', 'sk', 'si', 'sb', 'so', 'za', 'gs', 'ss', 'es', 'lk', 'sd', 'sr', 'sj', 'sz', 'se', 'ch', + 'sy', 'tw', 'tj', 'tz', 'th', 'tl', 'tg', 'tk', 'to', 'tt', 'tn', 'tr', 'tm', 'tc', 'tv', 'ug', 'ua', 'ae', + 'gb', 'us', 'um', 'uy', 'uz', 'vu', 've', 'vn', 'vg', 'vi', 'wf', 'eh', 'ye', 'zm', 'zw', 'en', 'zh', + ]; + } + + /** + * Get the path to a statically cached page. + */ + protected function getStaticPath(string $sitePath): string + { + $parts = parse_url($_SERVER['REQUEST_URI']); + $query = isset($parts['query']) ? $parts['query'] : ''; + + return $sitePath.'/static'.$parts['path'].'_'.$query.'.html'; + } +} diff --git a/cli/Valet/Drivers/Specific/StatamicValetDriver.php b/cli/Valet/Drivers/Specific/StatamicValetDriver.php index 7392a6a..cb233d5 100644 --- a/cli/Valet/Drivers/Specific/StatamicValetDriver.php +++ b/cli/Valet/Drivers/Specific/StatamicValetDriver.php @@ -2,126 +2,45 @@ namespace Valet\Drivers\Specific; -use Valet\Drivers\ValetDriver; +use Valet\Drivers\LaravelValetDriver; -class StatamicValetDriver extends ValetDriver +class StatamicValetDriver extends LaravelValetDriver { /** * Determine if the driver serves the request. */ public function serves(string $sitePath, string $siteName, string $uri): bool { - return is_dir($sitePath.'/statamic'); - } - - /** - * Determine if the incoming request is for a static file. - */ - public function isStaticFile(string $sitePath, string $siteName, string $uri)/*: string|false */ - { - if (strpos($uri, '/site') === 0 && strpos($uri, '/site/themes') !== 0) { - return false; - } elseif (strpos($uri, '/local') === 0 || strpos($uri, '/statamic') === 0) { - return false; - } elseif ($this->isActualFile($staticFilePath = $sitePath.$uri)) { - return $staticFilePath; - } elseif ($this->isActualFile($staticFilePath = $sitePath.'/public'.$uri)) { - return $staticFilePath; - } - - return false; + return file_exists($sitePath.'/please') + && parent::serves($sitePath, $siteName, $uri); } /** * Get the fully resolved path to the application's front controller. */ - public function frontControllerPath(string $sitePath, string $siteName, string $uri): ?string + public function frontControllerPath(string $sitePath, string $siteName, string $uri): string { - if ($_SERVER['REQUEST_METHOD'] === 'GET' && $this->isActualFile($staticPath = $this->getStaticPath($sitePath))) { + $staticPath = $this->getStaticPath($sitePath); + + if ($staticPath && $this->isActualFile($staticPath)) { return $staticPath; } - if ($uri === '/installer.php') { - return $sitePath.'/installer.php'; - } - - $scriptName = '/index.php'; - - if ($this->isActualFile($sitePath.'/index.php')) { - $indexPath = $sitePath.'/index.php'; - } - - if ($isAboveWebroot = $this->isActualFile($sitePath.'/public/index.php')) { - $indexPath = $sitePath.'/public/index.php'; - } - - $sitePathPrefix = ($isAboveWebroot) ? $sitePath.'/public' : $sitePath; - - if ($locale = $this->getUriLocale($uri)) { - if ($this->isActualFile($localeIndexPath = $sitePathPrefix.'/'.$locale.'/index.php')) { - // Force trailing slashes on locale roots. - if ($uri === '/'.$locale) { - header('Location: '.$uri.'/'); - exit; - } - - $indexPath = $localeIndexPath; - $scriptName = '/'.$locale.'/index.php'; - } - } - - $_SERVER['SCRIPT_NAME'] = $scriptName; - $_SERVER['SCRIPT_FILENAME'] = $sitePathPrefix.$scriptName; - - return $indexPath; + return parent::frontControllerPath($sitePath, $siteName, $uri); } /** - * Get the locale from this URI. + * Get the path to the static file. */ - public function getUriLocale(string $uri): ?string + private function getStaticPath(string $sitePath) { - $parts = explode('/', $uri); - $locale = $parts[1]; - - if (count($parts) < 2 || ! in_array($locale, $this->getLocales())) { - return null; + if (! $uri = $_SERVER['REQUEST_URI'] ?? null) { + return; } - return $locale; - } + $parts = parse_url($uri); + $query = $parts['query'] ?? ''; - /** - * Get the list of possible locales used in the first segment of a URI. - */ - public function getLocales(): array - { - return [ - 'af', 'ax', 'al', 'dz', 'as', 'ad', 'ao', 'ai', 'aq', 'ag', 'ar', 'am', 'aw', 'au', 'at', 'az', 'bs', 'bh', - 'bd', 'bb', 'by', 'be', 'bz', 'bj', 'bm', 'bt', 'bo', 'bq', 'ba', 'bw', 'bv', 'br', 'io', 'bn', 'bg', 'bf', - 'bi', 'cv', 'kh', 'cm', 'ca', 'ky', 'cf', 'td', 'cl', 'cn', 'cx', 'cc', 'co', 'km', 'cg', 'cd', 'ck', 'cr', - 'ci', 'hr', 'cu', 'cw', 'cy', 'cz', 'dk', 'dj', 'dm', 'do', 'ec', 'eg', 'sv', 'gq', 'er', 'ee', 'et', 'fk', - 'fo', 'fj', 'fi', 'fr', 'gf', 'pf', 'tf', 'ga', 'gm', 'ge', 'de', 'gh', 'gi', 'gr', 'gl', 'gd', 'gp', 'gu', - 'gt', 'gg', 'gn', 'gw', 'gy', 'ht', 'hm', 'va', 'hn', 'hk', 'hu', 'is', 'in', 'id', 'ir', 'iq', 'ie', 'im', - 'il', 'it', 'jm', 'jp', 'je', 'jo', 'kz', 'ke', 'ki', 'kp', 'kr', 'kw', 'kg', 'la', 'lv', 'lb', 'ls', 'lr', - 'ly', 'li', 'lt', 'lu', 'mo', 'mk', 'mg', 'mw', 'my', 'mv', 'ml', 'mt', 'mh', 'mq', 'mr', 'mu', 'yt', 'mx', - 'fm', 'md', 'mc', 'mn', 'me', 'ms', 'ma', 'mz', 'mm', 'na', 'nr', 'np', 'nl', 'nc', 'nz', 'ni', 'ne', 'ng', - 'nu', 'nf', 'mp', 'no', 'om', 'pk', 'pw', 'ps', 'pa', 'pg', 'py', 'pe', 'ph', 'pn', 'pl', 'pt', 'pr', 'qa', - 're', 'ro', 'ru', 'rw', 'bl', 'sh', 'kn', 'lc', 'mf', 'pm', 'vc', 'ws', 'sm', 'st', 'sa', 'sn', 'rs', 'sc', - 'sl', 'sg', 'sx', 'sk', 'si', 'sb', 'so', 'za', 'gs', 'ss', 'es', 'lk', 'sd', 'sr', 'sj', 'sz', 'se', 'ch', - 'sy', 'tw', 'tj', 'tz', 'th', 'tl', 'tg', 'tk', 'to', 'tt', 'tn', 'tr', 'tm', 'tc', 'tv', 'ug', 'ua', 'ae', - 'gb', 'us', 'um', 'uy', 'uz', 'vu', 've', 'vn', 'vg', 'vi', 'wf', 'eh', 'ye', 'zm', 'zw', 'en', 'zh', - ]; - } - - /** - * Get the path to a statically cached page. - */ - protected function getStaticPath(string $sitePath): string - { - $parts = parse_url($_SERVER['REQUEST_URI']); - $query = isset($parts['query']) ? $parts['query'] : ''; - - return $sitePath.'/static'.$parts['path'].'_'.$query.'.html'; + return $sitePath.'/public/static'.$parts['path'].'_'.$query.'.html'; } } diff --git a/cli/Valet/Drivers/ValetDriver.php b/cli/Valet/Drivers/ValetDriver.php index 7ce2498..9d6fff1 100644 --- a/cli/Valet/Drivers/ValetDriver.php +++ b/cli/Valet/Drivers/ValetDriver.php @@ -45,8 +45,9 @@ public static function assign(string $sitePath, string $siteName, string $uri): $drivers = array_merge($drivers, static::customDrivers()); // Queue Valet-shipped drivers + $drivers[] = 'Specific\StatamicValetDriver'; $drivers[] = 'LaravelValetDriver'; - $drivers = array_merge($drivers, $specificDrivers); + $drivers = array_unique(array_merge($drivers, $specificDrivers)); $drivers[] = 'BasicWithPublicValetDriver'; $drivers[] = 'BasicValetDriver'; diff --git a/tests/Drivers/StatamicV2ValetDriverTest.php b/tests/Drivers/StatamicV2ValetDriverTest.php new file mode 100644 index 0000000..630e6d1 --- /dev/null +++ b/tests/Drivers/StatamicV2ValetDriverTest.php @@ -0,0 +1,31 @@ +assertTrue($driver->serves($this->projectDir('statamicv2'), 'my-site', '/')); + } + + public function test_it_doesnt_serve_non_statamic_projects() + { + $driver = new StatamicV2ValetDriver(); + + $this->assertFalse($driver->serves($this->projectDir('public-with-index-non-laravel'), 'my-site', '/')); + } + + public function test_it_gets_front_controller() + { + $driver = new StatamicV2ValetDriver(); + + $_SERVER['REQUEST_METHOD'] = 'GET'; + $_SERVER['REQUEST_URI'] = '/about/'; + + $projectPath = $this->projectDir('statamicv2'); + $this->assertEquals($projectPath.'/index.php', $driver->frontControllerPath($projectPath, 'my-site', '/')); + } +} diff --git a/tests/Drivers/StatamicValetDriverTest.php b/tests/Drivers/StatamicValetDriverTest.php index ecd0eed..5d2f0ee 100644 --- a/tests/Drivers/StatamicValetDriverTest.php +++ b/tests/Drivers/StatamicValetDriverTest.php @@ -11,21 +11,38 @@ public function test_it_serves_statamic_projects() $this->assertTrue($driver->serves($this->projectDir('statamic'), 'my-site', '/')); } - public function test_it_doesnt_serve_non_statamic_projects() + public function test_it_doesnt_serve_non_statamic_projects_with_public_directory() { $driver = new StatamicValetDriver(); $this->assertFalse($driver->serves($this->projectDir('public-with-index-non-laravel'), 'my-site', '/')); } + public function test_it_doesnt_serve_laravel_projects() + { + $driver = new StatamicValetDriver(); + + $this->assertFalse($driver->serves($this->projectDir('laravel'), 'my-site', '/')); + } + public function test_it_gets_front_controller() { $driver = new StatamicValetDriver(); - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_SERVER['REQUEST_URI'] = '/about/'; + $projectPath = $this->projectDir('statamic'); + $this->assertEquals($projectPath.'/public/index.php', $driver->frontControllerPath($projectPath, 'my-site', '/')); + } - $projectPath = $this->projectDir('statamicv1'); - $this->assertEquals($projectPath.'/index.php', $driver->frontControllerPath($projectPath, 'my-site', '/')); + public function test_it_serves_statically_cached_pages() + { + $driver = new StatamicValetDriver(); + + $projectPath = $this->projectDir('statamic'); + + $_SERVER['REQUEST_URI'] = '/test'; + $this->assertEquals($projectPath.'/public/static/test_.html', $driver->frontControllerPath($projectPath, 'my-site', '/test')); + + $_SERVER['REQUEST_URI'] = '/test?foo=bar&baz=qux'; + $this->assertEquals($projectPath.'/public/static/test_foo=bar&baz=qux.html', $driver->frontControllerPath($projectPath, 'my-site', '/test')); } } diff --git a/tests/Drivers/ValetDriverTest.php b/tests/Drivers/ValetDriverTest.php index 4f71bfc..74360a9 100644 --- a/tests/Drivers/ValetDriverTest.php +++ b/tests/Drivers/ValetDriverTest.php @@ -30,6 +30,15 @@ public function test_it_prioritizes_non_basic_matches() $this->assertNotEquals('Valet\Drivers\BasicValetDriver', get_class($assignedDriver)); } + public function test_it_prioritizes_statamic() + { + $assignedDriver = ValetDriver::assign($this->projectDir('statamic'), 'my-site', '/'); + $this->assertEquals('Valet\Drivers\Specific\StatamicValetDriver', get_class($assignedDriver)); + + $assignedDriver = ValetDriver::assign($this->projectDir('laravel'), 'my-site', '/'); + $this->assertEquals('Valet\Drivers\LaravelValetDriver', get_class($assignedDriver)); + } + public function test_it_checks_composer_dependencies() { $driver = new BasicValetDriver; diff --git a/tests/Drivers/projects/statamic/statamic/.gitkeep b/tests/Drivers/projects/statamic/artisan similarity index 100% rename from tests/Drivers/projects/statamic/statamic/.gitkeep rename to tests/Drivers/projects/statamic/artisan diff --git a/tests/Drivers/projects/statamic/please b/tests/Drivers/projects/statamic/please new file mode 100644 index 0000000..e69de29 diff --git a/tests/Drivers/projects/statamic/public/index.php b/tests/Drivers/projects/statamic/public/index.php new file mode 100644 index 0000000..e69de29 diff --git a/tests/Drivers/projects/statamic/public/static/test_.html b/tests/Drivers/projects/statamic/public/static/test_.html new file mode 100644 index 0000000..e69de29 diff --git a/tests/Drivers/projects/statamic/public/static/test_foo=bar&baz=qux.html b/tests/Drivers/projects/statamic/public/static/test_foo=bar&baz=qux.html new file mode 100644 index 0000000..e69de29 diff --git a/tests/Drivers/projects/statamicv2/index.php b/tests/Drivers/projects/statamicv2/index.php new file mode 100644 index 0000000..e69de29 diff --git a/tests/Drivers/projects/statamicv2/statamic/.gitkeep b/tests/Drivers/projects/statamicv2/statamic/.gitkeep new file mode 100644 index 0000000..e69de29