Skip to content

Commit

Permalink
[!!!][TASK] New Content Block folder structure
Browse files Browse the repository at this point in the history
  • Loading branch information
nhovratov committed Sep 16, 2024
1 parent 5d37c15 commit c4a3f08
Show file tree
Hide file tree
Showing 177 changed files with 537 additions and 386 deletions.
2 changes: 1 addition & 1 deletion Classes/Backend/Preview/PageLayout.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected function getContentBlocksLayoutRootPaths(string $contentBlockPrivatePa
protected function getContentBlockPrivatePath(ContentTypeInterface $contentTypeDefinition): string
{
$contentBlockExtPath = $this->getEditorPreviewExtPath($contentTypeDefinition);
$contentBlockPrivatePath = $contentBlockExtPath . '/' . ContentBlockPathUtility::getPrivateFolder();
$contentBlockPrivatePath = $contentBlockExtPath . '/' . ContentBlockPathUtility::getTemplatesFolder();
return $contentBlockPrivatePath;
}

Expand Down
2 changes: 1 addition & 1 deletion Classes/Backend/Preview/PreviewRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string
$contentTypeDefinition = $contentTypeCollection->getFirst();
}
$contentBlockExtPath = $this->contentBlockRegistry->getContentBlockExtPath($contentTypeDefinition->getName());
$contentBlockPrivatePath = $contentBlockExtPath . '/' . ContentBlockPathUtility::getPrivateFolder();
$contentBlockPrivatePath = $contentBlockExtPath . '/' . ContentBlockPathUtility::getTemplatesFolder();

// Fall back to standard preview rendering if EditorPreview.html does not exist.
$editorPreviewExtPath = $contentBlockExtPath . '/' . ContentBlockPathUtility::getBackendPreviewPath();
Expand Down
19 changes: 11 additions & 8 deletions Classes/Builder/ContentBlockBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ public function create(LoadedContentBlock $contentBlock): void

$this->initializeRegistries($contentBlock);

// Create public Assets directory.
$publicPath = $basePath . '/' . ContentBlockPathUtility::getPublicFolder();
GeneralUtility::mkdir_deep($publicPath);
// Create base directories for a Content Block.
$assetsPath = $basePath . '/' . ContentBlockPathUtility::getAssetsFolder();
$templatePath = $basePath . '/' . ContentBlockPathUtility::getTemplatesFolder();
$languagePath = $basePath . '/' . ContentBlockPathUtility::getLanguageFolder();
GeneralUtility::mkdir_deep($assetsPath);
GeneralUtility::mkdir_deep($templatePath);
GeneralUtility::mkdir_deep($languagePath);

$this->createLabelsXlf($contentBlock, $basePath);
$this->createEditorInterfaceYaml($contentBlock, $basePath);
Expand All @@ -76,7 +80,7 @@ public function create(LoadedContentBlock $contentBlock): void
if ($contentType === ContentType::CONTENT_ELEMENT) {
$this->createFrontendHtml($contentBlock, $basePath);
$this->createBackendPreviewHtml($contentBlock, $basePath);
$this->createExamplePublicAssets($publicPath);
$this->createExamplePublicAssets($assetsPath);
}
$this->copyDefaultIcon($contentType, $basePath);
if ($contentType === ContentType::PAGE_TYPE) {
Expand Down Expand Up @@ -115,7 +119,6 @@ protected function createEditorInterfaceYaml(LoadedContentBlock $contentBlock, s

protected function createLabelsXlf(LoadedContentBlock $contentBlock, string $basePath): void
{
GeneralUtility::mkdir_deep($basePath . '/' . ContentBlockPathUtility::getLanguageFolderPath());
$xliffContent = $this->languageFileGenerator->generate($contentBlock);
GeneralUtility::writeFile(
$basePath . '/' . ContentBlockPathUtility::getLanguageFilePath(),
Expand All @@ -142,15 +145,15 @@ protected function createFrontendHtml(LoadedContentBlock $contentBlock, string $
protected function createExamplePublicAssets(string $publicPath): void
{
GeneralUtility::writeFile(
$publicPath . '/EditorPreview.css',
$publicPath . '/editor-preview.css',
'/* Created by Content Blocks */'
);
GeneralUtility::writeFile(
$publicPath . '/Frontend.css',
$publicPath . '/frontend.css',
'/* Created by Content Blocks */'
);
GeneralUtility::writeFile(
$publicPath . '/Frontend.js',
$publicPath . '/frontend.js',
'/* Created by Content Blocks */'
);
}
Expand Down
2 changes: 1 addition & 1 deletion Classes/Command/GenerateLanguageFileCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
protected function writeLabelsXlf(LoadedContentBlock $contentBlock): void
{
$contentBlockPath = GeneralUtility::getFileAbsFileName($contentBlock->getExtPath());
$labelsFolder = $contentBlockPath . '/' . ContentBlockPathUtility::getLanguageFolderPath();
$labelsFolder = $contentBlockPath . '/' . ContentBlockPathUtility::getLanguageFolder();
$labelsXlfPath = $contentBlockPath . '/' . ContentBlockPathUtility::getLanguageFilePath();
$result = $this->languageFileGenerator->generate($contentBlock);
GeneralUtility::mkdir_deep($labelsFolder);
Expand Down
6 changes: 3 additions & 3 deletions Classes/Generator/HtmlTemplateCodeGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function generateEditorPreviewTemplate(LoadedContentBlock $contentBlockCo
$package = $contentBlockConfiguration->getName();
$vendor = $contentBlockConfiguration->getVendor();

$defaultContent[] = '<f:asset.css identifier="content-block-' . $vendor . '-' . $package . '-be" href="{cb:assetPath()}/EditorPreview.css"/>';
$defaultContent[] = '<f:asset.css identifier="content-block-' . $vendor . '-' . $package . '-be" href="{cb:assetPath()}/editor-preview.css"/>';
$defaultContent[] = '';
$defaultContent[] = 'Preview for Content Block: ' . $contentBlockConfiguration->getName() . '<br>';
$defaultContent[] = 'Header: {data.header}';
Expand All @@ -64,8 +64,8 @@ public function generateFrontendTemplate(LoadedContentBlock $contentBlockConfigu
{
$package = $contentBlockConfiguration->getName();
$vendor = $contentBlockConfiguration->getVendor();
$frontendTemplate[] = '<f:asset.css identifier="content-block-css-' . $vendor . '-' . $package . '" href="{cb:assetPath()}/Frontend.css"/>';
$frontendTemplate[] = '<f:asset.script identifier="content-block-js-' . $vendor . '-' . $package . '" src="{cb:assetPath()}/Frontend.js"/>';
$frontendTemplate[] = '<f:asset.css identifier="content-block-css-' . $vendor . '-' . $package . '" href="{cb:assetPath()}/frontend.css"/>';
$frontendTemplate[] = '<f:asset.script identifier="content-block-js-' . $vendor . '-' . $package . '" src="{cb:assetPath()}/frontend.js"/>';
$frontendTemplate[] = '';
$frontendTemplate[] = 'Frontend template for Content Block: ' . $contentBlockConfiguration->getName() . '<br>';
$frontendTemplate[] = 'Header: {data.header}';
Expand Down
2 changes: 1 addition & 1 deletion Classes/Generator/LanguageFileGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected function wrap(string $content, string $date, string $vendor, string $n
$xliffContent = <<<HEREDOC
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file datatype="plaintext" original="Labels.xlf" source-language="en" date="$date" product-name="$vendor/$name">
<file datatype="plaintext" original="labels.xlf" source-language="en" date="$date" product-name="$vendor/$name">
<header/>
<body>
$content
Expand Down
12 changes: 6 additions & 6 deletions Classes/Loader/ContentBlockLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ protected function loadContentBlocksInExtension(string $path, string $extensionK
$contentBlockFolderName = $splFileInfo->getRelativePathname();
$contentBlockExtPath = ContentBlockPathUtility::getContentBlockExtPath($extensionKey, $contentBlockFolderName, $contentType);
$editorInterfaceYaml = $this->parseEditorInterfaceYaml($absoluteContentBlockPath, $contentBlockExtPath, $contentType);
if ($editorInterfaceYaml === null) {
continue;
}
$result[] = $this->loadSingleContentBlock(
$editorInterfaceYaml['name'],
$contentType,
Expand All @@ -157,15 +160,12 @@ protected function loadContentBlocksInExtension(string $path, string $extensionK
return $result;
}

protected function parseEditorInterfaceYaml(string $absoluteContentBlockPath, string $contentBlockExtPath, ContentType $contentType): array
protected function parseEditorInterfaceYaml(string $absoluteContentBlockPath, string $contentBlockExtPath, ContentType $contentType): ?array
{
$contentBlockDefinitionFileName = ContentBlockPathUtility::getContentBlockDefinitionFileName();
$yamlPath = $absoluteContentBlockPath . '/' . $contentBlockDefinitionFileName;
if (!file_exists($yamlPath)) {
throw new \RuntimeException(
'Found Content Block folder in "' . $contentBlockExtPath . '" but ' . $contentBlockDefinitionFileName . ' is missing.',
1711039210
);
return null;
}
$editorInterfaceYaml = Yaml::parseFile($yamlPath);
if (!is_array($editorInterfaceYaml) || strlen($editorInterfaceYaml['name'] ?? '') < 3 || !str_contains($editorInterfaceYaml['name'], '/')) {
Expand Down Expand Up @@ -285,7 +285,7 @@ protected function publishAssets(array $loadedContentBlocks): void
$fileSystem = new Filesystem();
foreach ($loadedContentBlocks as $loadedContentBlock) {
$hostExtension = $loadedContentBlock->getHostExtension();
$contentBlockExtPublicPath = $loadedContentBlock->getExtPath() . '/' . ContentBlockPathUtility::getPublicFolder();
$contentBlockExtPublicPath = $loadedContentBlock->getExtPath() . '/' . ContentBlockPathUtility::getAssetsFolder();
$contentBlockAbsolutePublicPath = GeneralUtility::getFileAbsFileName($contentBlockExtPublicPath);
// If the Content Block does not have an Assets folder, nothing to publish here.
if (!file_exists($contentBlockAbsolutePublicPath)) {
Expand Down
2 changes: 1 addition & 1 deletion Classes/Service/Icon/ContentTypeIconResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static function resolve(ContentTypeIconResolverInput $input): ?ContentTyp
{
$allowedFileExtension = ['svg', 'png', 'gif'];
foreach ($allowedFileExtension as $fileExtension) {
$iconPathWithoutFileExtension = ContentBlockPathUtility::getPublicFolder() . '/' . $input->identifier;
$iconPathWithoutFileExtension = ContentBlockPathUtility::getAssetsFolder() . '/' . $input->identifier;
$relativeIconPath = $iconPathWithoutFileExtension . '.' . $fileExtension;
$checkIconPath = $input->absolutePath . '/' . $relativeIconPath;
if (!file_exists($checkIconPath)) {
Expand Down
13 changes: 5 additions & 8 deletions Classes/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,20 +162,17 @@ public static function getContentBlockTypoScript(ContainerInterface $container):
foreach ($tableDefinition->getContentTypeDefinitionCollection() ?? [] as $typeDefinition) {
if ($tableDefinition->getContentType() === ContentType::CONTENT_ELEMENT) {
$extPath = $contentBlockRegistry->getContentBlockExtPath($typeDefinition->getName());
$privatePath = $extPath . '/' . ContentBlockPathUtility::getPrivateFolder();
$template = ContentBlockPathUtility::getFrontendTemplateFileNameWithoutExtension();
$privatePath = $extPath . '/' . ContentBlockPathUtility::getTemplatesFolder();
$template = ContentBlockPathUtility::getFrontendTemplateFileName();
$typoScript = <<<HEREDOC
tt_content.{$typeDefinition->getTypeName()} =< lib.contentBlock
tt_content.{$typeDefinition->getTypeName()} {
templateName = {$template}
templateRootPaths {
20 = $privatePath/
}
file = $privatePath/$template
partialRootPaths {
20 = $privatePath/Partials/
20 = $privatePath/partials/
}
layoutRootPaths {
20 = $privatePath/Layouts/
20 = $privatePath/layouts/
}
}
HEREDOC;
Expand Down
155 changes: 155 additions & 0 deletions Classes/Update/ContentBlockFolderStructureMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\ContentBlocks\Update;

use Symfony\Component\Finder\Finder;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;

#[UpgradeWizard('contentBlocksFolderStructureMigration')]
class ContentBlockFolderStructureMigration implements UpgradeWizardInterface
{
public function __construct(
protected readonly PackageManager $packageManager,
) {}

public function getTitle(): string
{
return 'Content Block folder structure migration';
}

public function getDescription(): string
{
return 'Migrates to the new lowercase folder structure for single Content Blocks.';
}

public function executeUpdate(): bool
{
foreach ($this->findContentBlockPaths() as $path) {
$this->migrate($path);
}
return true;
}

public function updateNecessary(): bool
{
return $this->findContentBlockPaths() !== [];
}

public function getPrerequisites(): array
{
return [];
}

/**
* @return string[]
*/
protected function findContentBlockPaths(): array
{
$contentBlockPaths = [];
foreach ($this->packageManager->getActivePackages() as $package) {
$contentElementsFolder = $package->getPackagePath() . 'ContentBlocks/ContentElements';
$pageTypesFolder = $package->getPackagePath() . 'ContentBlocks/PageTypes';
$recordTypesFolder = $package->getPackagePath() . 'ContentBlocks/RecordTypes';
if (is_dir($contentElementsFolder)) {
$contentBlockPaths[] = $this->loadContentBlocksInExtension($contentElementsFolder);
}
if (is_dir($pageTypesFolder)) {
$contentBlockPaths[] = $this->loadContentBlocksInExtension($pageTypesFolder);
}
if (is_dir($recordTypesFolder)) {
$contentBlockPaths[] = $this->loadContentBlocksInExtension($recordTypesFolder);
}
}
$contentBlockPaths = array_merge(...$contentBlockPaths);
return $contentBlockPaths;
}

/**
* @return string[]
*/
protected function loadContentBlocksInExtension(string $path): array
{
$result = [];
$finder = new Finder();
$finder->directories()->depth(0)->in($path);
foreach ($finder as $splFileInfo) {
$absoluteContentBlockPath = $splFileInfo->getPathname();
if (file_exists($absoluteContentBlockPath . '/EditorInterface.yaml')) {
$result[] = $absoluteContentBlockPath;
}
}
return $result;
}

protected function migrate(string $path): void
{
rename($path . '/EditorInterface.yaml', $path . '/config.yaml');
if (file_exists($path . '/Source')) {
rename($path . '/Source', $path . '/templates');
}
if (file_exists($path . '/templates/Frontend.html')) {
rename($path . '/templates/Frontend.html', $path . '/templates/frontend.html');
}
if (file_exists($path . '/templates/Partials')) {
rename($path . '/templates/Partials', $path . '/templates/partials');
}
if (file_exists($path . '/templates/Layouts')) {
rename($path . '/templates/Layouts', $path . '/templates/layouts');
}
if (file_exists($path . '/templates/EditorPreview.html')) {
rename($path . '/templates/EditorPreview.html', $path . '/templates/preview.html');
}
if (file_exists($path . '/templates/Language')) {
rename($path . '/templates/Language', $path . '/language');
}
if (file_exists($path . '/language/Labels.xlf')) {
rename($path . '/language/Labels.xlf', $path . '/language/labels.xlf');
$this->migrateLocalizedLabelFiles($path . '/language');
}
if (file_exists($path . '/Assets')) {
rename($path . '/Assets', $path . '/assets');
}
if (file_exists($path . '/assets/Icon.svg')) {
rename($path . '/assets/Icon.svg', $path . '/assets/icon.svg');
}
if (file_exists($path . '/assets/IconHideInMenu.svg')) {
rename($path . '/assets/IconHideInMenu.svg', $path . '/assets/icon-hide-in-menu.svg');
}
if (file_exists($path . '/assets/IconRoot.svg')) {
rename($path . '/assets/IconRoot.svg', $path . '/assets/icon-root.svg');
}
}

protected function migrateLocalizedLabelFiles(string $languagePath): void
{
$finder = new Finder();
$finder->files()->name('*.xlf')->in($languagePath);
foreach ($finder as $splFileInfo) {
$fileName = $splFileInfo->getFilename();
$parts = explode('.', $fileName);
if (count($parts) !== 3) {
continue;
}
$parts[1] = 'labels';
$newFileName = implode('.', $parts);
rename($splFileInfo->getPathname(), $languagePath . '/' . $newFileName);
}
}
}
Loading

0 comments on commit c4a3f08

Please sign in to comment.