getDefaultStructureDefinition($webserverType), null); return new StructureFacade($rootNode); } /** * Default definition of folder and file structure with dynamic * permission settings */ private function getDefaultStructureDefinition(WebserverType $webserverType): array { $filePermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask']; $directoryPermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']; if (Environment::getPublicPath() === Environment::getProjectPath()) { $structure = [ // Note that root node has no trailing slash like all others 'name' => Environment::getPublicPath(), 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'typo3temp', 'type' => LinkOrDirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContent' => '', ], $this->getTemporaryAssetsFolderStructure(), [ 'name' => 'var', 'type' => LinkOrDirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/typo3temp-var-htaccess', ], [ 'name' => 'cache', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'build', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'lock', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'transient', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], ], ], ], ], $this->getFileadminStructure(), ], ]; // Have a default .htaccess if running apache web server or a default web.config if running IIS if ($webserverType->isApacheServer()) { $structure['children'][] = [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/root-htaccess', ]; } elseif ($webserverType->isMicrosoftInternetInformationServer()) { $structure['children'][] = [ 'name' => 'web.config', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/root-web-config', ]; } if (!Environment::isComposerMode()) { $structure['children'][] = [ 'name' => 'typo3conf', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'ext', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'l10n', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'sites', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'system', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], ], ]; } } else { // This is when the public path is a subfolder (e.g. public/ or web/) $publicPath = rtrim(Environment::getRelativePublicPath(), '/'); $publicPathSubStructure = [ [ 'name' => 'typo3temp', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContent' => '', ], $this->getTemporaryAssetsFolderStructure(), ], ], $this->getFileadminStructure(), ]; // Have a default .htaccess if running apache web server or a default web.config if running IIS if ($webserverType->isApacheServer()) { $publicPathSubStructure[] = [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/root-htaccess', ]; } elseif ($webserverType->isMicrosoftInternetInformationServer()) { $publicPathSubStructure[] = [ 'name' => 'web.config', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/root-web-config', ]; } if (!Environment::isComposerMode()) { $publicPathSubStructure[] = [ 'name' => 'typo3conf', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ]; } $structure = [ // Note that root node has no trailing slash like all others 'name' => Environment::getProjectPath(), 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'config', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'sites', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'system', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], ], ], $this->getPublicStructure($publicPath, $publicPathSubStructure), [ 'name' => 'var', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/typo3temp-var-htaccess', ], [ 'name' => 'charset', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'cache', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'labels', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'lock', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'transient', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], ], ], ], ]; } return $structure; } /** * Get public path structure while resolving nested paths */ private function getPublicStructure(string $publicPath, array $subStructure): array { $directoryPermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']; $publicPathParts = array_reverse(explode('/', $publicPath)); $lastNode = null; foreach ($publicPathParts as $publicPathPart) { $node = [ 'name' => $publicPathPart, 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ]; if ($lastNode !== null) { $node['children'][] = $lastNode; } else { $node['children'] = $subStructure; } $lastNode = $node; } return $lastNode; } private function getFileadminStructure(): array { $filePermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask']; $directoryPermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']; return [ 'name' => !empty($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir']) ? rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') : 'fileadmin', 'type' => LinkOrDirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/resources-root-htaccess', ], [ 'name' => '_temp_', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/fileadmin-temp-htaccess', ], [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/fileadmin-temp-index.html', ], ], ], [ 'name' => 'user_upload', 'type' => LinkOrDirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '_temp_', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContent' => '', ], [ 'name' => 'importexport', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => '.htaccess', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/fileadmin-user_upload-temp-importexport-htaccess', ], [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContentFile' => self::TEMPLATE_PATH . '/fileadmin-temp-index.html', ], ], ], ], ], [ 'name' => 'index.html', 'type' => FileNode::class, 'targetPermission' => $filePermission, 'targetContent' => '', ], ], ], ], ]; } /** * This defines the structure for typo3temp/assets */ private function getTemporaryAssetsFolderStructure(): array { $directoryPermission = $GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']; return [ 'name' => 'assets', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, 'children' => [ [ 'name' => 'css', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'js', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => 'images', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], [ 'name' => '_processed_', 'type' => DirectoryNode::class, 'targetPermission' => $directoryPermission, ], ], ]; } }