Last active
August 30, 2023 06:43
-
-
Save renalpha/4881b784e7f14d649cf4f4d276e1e929 to your computer and use it in GitHub Desktop.
LocalValetDriver for Typo3 working on Laravel Herd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class LocalValetDriver extends Valet\Drivers\ValetDriver | |
{ | |
/* | |
|-------------------------------------------------------------------------- | |
| Document Root Subdirectory | |
|-------------------------------------------------------------------------- | |
| | |
| This subdirectory contains the public server resources, such as the | |
| index.php, the typo3 and fileadmin system directories. Change it | |
| to '', if you don't use a subdirectory but valet link directly. | |
| | |
*/ | |
protected string $documentRoot = '/public'; | |
/* | |
|-------------------------------------------------------------------------- | |
| Forbidden URI Patterns | |
|-------------------------------------------------------------------------- | |
| | |
| All of these patterns won't be accessible from your web server. Instead, | |
| the server will throw a 403 forbidden response, if you try to access | |
| these files via the HTTP layer. Use regex syntax here and escape @. | |
| | |
*/ | |
protected array $forbiddenUriPatterns = [ | |
'_(recycler|temp)_/', | |
'^/(typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(Resources/Private|Tests)/', | |
'^/typo3/.+\.map$', | |
'^/typo3temp/var/', | |
'\.(htaccess|gitkeep|gitignore)$', | |
]; | |
/** | |
* Determine if the driver serves the request. For TYPO3, this is the | |
* case, if a folder called "typo3" is present in the document root. | |
* | |
* @param string $sitePath | |
* @param string $siteName | |
* @param string $uri | |
* @return bool | |
*/ | |
public function serves(string $sitePath, string $siteName, string $uri): bool | |
{ | |
$typo3Dir = $sitePath . $this->documentRoot . '/typo3'; | |
return file_exists($typo3Dir) && is_dir($typo3Dir); | |
} | |
/** | |
* Determine if the incoming request is for a static file. That is, it is | |
* no PHP script file and the URI points to a valid file (no folder) on | |
* the disk. Access to those static files will be authorized. | |
* | |
* @param string $sitePath | |
* @param string $siteName | |
* @param string $uri | |
* @return string|false | |
*/ | |
public function isStaticFile(string $sitePath, string $siteName, string $uri): string|false | |
{ | |
// May the file contains a cache busting version string like filename.12345678.css | |
// If that is the case, the file cannot be found on disk, so remove the version | |
// identifier before retrying below. | |
if (!$this->isActualFile($filePath = $sitePath . $this->documentRoot . $uri)) { | |
$uri = preg_replace("@^(.+)\.(\d+)\.(js|css|png|jpg|gif|gzip)$@", "$1.$3", $uri); | |
} | |
// Now that any possible version string is cleared from the filename, the resulting | |
// URI should be a valid file on disc. So assemble the absolut file name with the | |
// same schema as above and if it exists, authorize access and return its path. | |
if ($this->isActualFile($filePath = $sitePath . $this->documentRoot . $uri)) { | |
return $this->isAccessAuthorized($uri) ? $filePath : false; | |
} | |
// This file cannot be found in the current project and thus cannot be served. | |
return false; | |
} | |
/** | |
* Determines if the given URI is blacklisted so that access is prevented. | |
* | |
* @param string $uri | |
* @return boolean | |
*/ | |
private function isAccessAuthorized(string $uri): bool | |
{ | |
foreach ($this->forbiddenUriPatterns as $forbiddenUriPattern) { | |
if (preg_match("@$forbiddenUriPattern@", $uri)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* Get the fully resolved path to the application's front controller. | |
* This can be the currently requested PHP script, a folder that | |
* contains an index.php or the global index.php otherwise. | |
* | |
* @param string $sitePath | |
* @param string $siteName | |
* @param string $uri | |
* @return string | |
*/ | |
public function frontControllerPath(string $sitePath, string $siteName, string $uri): string | |
{ | |
// without modifying the URI, redirect if necessary | |
$this->handleRedirectBackendShorthandUris($uri); | |
// from now on, remove trailing / for convenience for all the following join operations | |
$uri = rtrim($uri, '/'); | |
if (preg_match('/.(js|css|gzip|gif|jpg|jpeg|png)$/', $uri) && !file_exists($sitePath . $this->documentRoot . $uri)) { | |
http_response_code(404); | |
die(); | |
} | |
// try to find the responsible script file for the requested folder / script URI | |
if (file_exists($absoluteFilePath = $sitePath . $this->documentRoot . $uri)) { | |
if (is_dir($absoluteFilePath)) { | |
if (file_exists($absoluteFilePath . '/index.php')) { | |
// this folder can be served by index.php | |
return $this->serveScript($sitePath, $siteName, $uri . '/index.php'); | |
} | |
if (file_exists($absoluteFilePath . '/index.html')) { | |
// this folder can be served by index.html | |
return $absoluteFilePath . '/index.html'; | |
} | |
} else { | |
if (pathinfo($absoluteFilePath, PATHINFO_EXTENSION) === 'php') { | |
// this file can be served directly | |
return $this->serveScript($sitePath, $siteName, $uri); | |
} | |
} | |
} | |
if (str_contains($uri, '/typo3/')) { | |
return $this->serveScript($sitePath, $siteName, '/typo3/index.php'); | |
} | |
// the global index.php will handle all other cases | |
return $this->serveScript($sitePath, $siteName, '/index.php'); | |
} | |
/** | |
* Direct access to installtool via domain.dev/typo3/install/ will be redirected to | |
* sysext install script. domain.dev/typo3 will be redirected to /typo3/, because | |
* the generated JavaScript URIs on the login screen would be broken on /typo3. | |
* | |
* @param string $uri | |
*/ | |
private function handleRedirectBackendShorthandUris(string $uri): void | |
{ | |
if (rtrim($uri, '/') === '/typo3/install') { | |
header('Location: /typo3/sysext/install/Start/Install.php'); | |
die(); | |
} | |
if ($uri === '/typo3') { | |
header('Location: /typo3/'); | |
die(); | |
} | |
} | |
/** | |
* Configures the $_SERVER globals for serving the script at | |
* the specified URI and returns it absolute file path. | |
* | |
* @param string $sitePath | |
* @param string $siteName | |
* @param string $uri | |
* @return string | |
*/ | |
private function serveScript(string $sitePath, string $siteName, string $uri): string | |
{ | |
$docroot = $sitePath . $this->documentRoot; | |
$abspath = $docroot . $uri; | |
$_SERVER['SERVER_NAME'] = $siteName . '.test'; | |
$_SERVER['DOCUMENT_ROOT'] = $docroot; | |
$_SERVER['DOCUMENT_URI'] = $uri; | |
$_SERVER['SCRIPT_FILENAME'] = $abspath; | |
$_SERVER['SCRIPT_NAME'] = $uri; | |
$_SERVER['PHP_SELF'] = $uri; | |
putenv('TYPO3_CONTEXT=Development/Valet'); | |
ini_set('max_execution_time', 240); | |
ini_set('max_input_vars', 2000); | |
ini_set('xdebug.max_nesting_level', 800); | |
return $abspath; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment