Skip to content

Commit

Permalink
Merge pull request #5440 from mhsdesign/task/finalise-site-creation-m…
Browse files Browse the repository at this point in the history
…odule-for-90

BUGFIX: Remove import site from site creation module and fix delete sites (9.0)
  • Loading branch information
mhsdesign authored Jan 28, 2025
2 parents 52ea360 + 0df849a commit 89ab5fb
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

use Neos\ContentRepository\Core\Feature\NodeRenaming\Command\ChangeNodeAggregateName;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate;
use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeNameIsAlreadyCovered;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFound;
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\ContentRepositoryRegistry\Exception\ContentRepositoryNotFoundException;
Expand All @@ -41,10 +41,6 @@
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\Domain\Service\SiteService;
use Neos\Neos\Domain\Service\UserService;
use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult;
use Neos\SiteKickstarter\Generator\SitePackageGeneratorInterface;
use Neos\SiteKickstarter\Service\SiteGeneratorCollectingService;
use Neos\SiteKickstarter\Service\SitePackageGeneratorNameService;

/**
* The Neos Sites Management module controller
Expand Down Expand Up @@ -89,6 +85,18 @@ class SitesController extends AbstractModuleController
*/
protected $session;

/**
* This is not 100% correct, but it is as good as we can get it to work right now
* It works when the created site's name will use the configuration "*" which by default uses the default preset.
*
* As proposed here https://github.com/neos/neos-development-collection/issues/4470#issuecomment-2432140074
* the site must have a field to define the contentRepositoryId to correctly create sites dynamically.
*
* @Flow\InjectConfiguration("sitePresets.default.contentRepository")
* @var string|null
*/
protected $defaultContentRepositoryForNewSites;

#[Flow\Inject]
protected UserService $domainUserService;

Expand Down Expand Up @@ -236,65 +244,29 @@ public function updateSiteAction(Site $site, $newSiteNodeName)
*/
public function newSiteAction(): void
{
// This is not 100% correct, but it is as good as we can get it to work right now
try {
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())
->contentRepositoryId;
} catch (\RuntimeException) {
$contentRepositoryId = ContentRepositoryId::fromString('default');
$contentRepositoryId = ContentRepositoryId::fromString($this->defaultContentRepositoryForNewSites ?? '');
} catch (\InvalidArgumentException $e) {
throw new \RuntimeException('The default content repository for new sites configured in "Neos.Neos.sitePresets.default.contentRepository" is not valid.', 1736946907, $e);
}

try {
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
$documentNodeTypes = $contentRepository->getNodeTypeManager()->getSubNodeTypes(NodeTypeNameFactory::forSite(), false);
} catch (ContentRepositoryNotFoundException) {
$documentNodeTypes = [];
} catch (ContentRepositoryNotFoundException $e) {
throw new \RuntimeException(sprintf('The default content repository for new sites "%s" could not be instantiated.', $contentRepositoryId->value), 1736946907);
}

$documentNodeTypes = $contentRepository->getNodeTypeManager()->getSubNodeTypes(NodeTypeNameFactory::forSite(), false);

$sitePackages = $this->packageManager->getFilteredPackages('available', 'neos-site');

$this->view->assignMultiple([
'defaultContentRepositoryForNewSites' => $contentRepositoryId->value,
'sitePackages' => $sitePackages,
'documentNodeTypes' => $documentNodeTypes
]);
}

/**
* Import a site from site package.
*
* @param string $packageKey Package from where the import will come
* @Flow\Validate(argumentName="$packageKey", type="\Neos\Neos\Validation\Validator\PackageKeyValidator")
* @return void
*/
/*public function importSiteAction($packageKey)
{
try {
$this->siteImportService->importFromPackage($packageKey);
$this->addFlashMessage(
$this->getModuleLabel('sites.theSiteHasBeenImported.body'),
'',
Message::SEVERITY_OK,
[],
1412372266
);
} catch (\Exception $exception) {
$logMessage = $this->throwableStorage->logThrowable($exception);
$this->logger->error($logMessage, LogEnvironment::fromMethodName(__METHOD__));
$this->addFlashMessage(
$this->getModuleLabel(
'sites.importError.body',
[htmlspecialchars($packageKey), htmlspecialchars($exception->getMessage())]
),
$this->getModuleLabel('sites.importError.title'),
Message::SEVERITY_ERROR,
[],
1412372375
);
}
$this->unsetLastVisitedNodeAndRedirect('index');
}*/

/**
* Create a new empty site.
*
Expand Down
13 changes: 11 additions & 2 deletions Neos.Neos/Classes/Domain/Service/SiteService.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Persistence\PersistenceManagerInterface;
use Neos\Flow\Security\Context as SecurityContext;
use Neos\Media\Domain\Model\Asset;
use Neos\Media\Domain\Repository\AssetCollectionRepository;
use Neos\Neos\Domain\Exception\SiteNodeNameIsAlreadyInUseByAnotherSite;
Expand Down Expand Up @@ -70,14 +71,21 @@ class SiteService
*/
protected $workspaceService;

/**
* @Flow\Inject
* @var SecurityContext
*/
protected $securityContext;

/**
* Remove given site all nodes for that site and all domains associated.
*/
public function pruneSite(Site $site): void
{
$siteServiceInternals = new SiteServiceInternals(
$this->contentRepositoryRegistry->get($site->getConfiguration()->contentRepositoryId),
$this->workspaceService
$this->workspaceService,
$this->securityContext
);

try {
Expand Down Expand Up @@ -181,7 +189,8 @@ public function createSite(

$siteServiceInternals = new SiteServiceInternals(
$this->contentRepositoryRegistry->get($site->getConfiguration()->contentRepositoryId),
$this->workspaceService
$this->workspaceService,
$this->securityContext
);
$siteServiceInternals->createSiteNodeIfNotExists($site, $nodeTypeName);

Expand Down
39 changes: 25 additions & 14 deletions Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeVariantSelectionStrategy;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\Flow\Security\Context as SecurityContext;
use Neos\Neos\Domain\Exception\SiteNodeTypeIsInvalid;
use Neos\Neos\Domain\Model\Site;
use Neos\Neos\Domain\Model\SiteNodeName;
Expand All @@ -49,6 +50,7 @@
public function __construct(
private ContentRepository $contentRepository,
private WorkspaceService $workspaceService,
private SecurityContext $securityContext
) {
$this->nodeTypeManager = $this->contentRepository->getNodeTypeManager();
$this->interDimensionalVariationGraph = $this->contentRepository->getVariationGraph();
Expand All @@ -66,9 +68,13 @@ public function removeSiteNode(SiteNodeName $siteNodeName): void
);
}

// todo only remove site node in base workspace and rebase dependant workspaces to avoid also the security hacks here.
foreach ($this->contentRepository->findWorkspaces() as $workspace) {
$contentGraph = $this->contentRepository->getContentGraph($workspace->workspaceName);
$sitesNodeAggregate = $contentGraph->findRootNodeAggregateByType(
$contentGraph = null;
$this->securityContext->withoutAuthorizationChecks(function () use (&$contentGraph, $workspace) {
$contentGraph = $this->contentRepository->getContentGraph($workspace->workspaceName);
});
$sitesNodeAggregate = $contentGraph?->findRootNodeAggregateByType(
NodeTypeNameFactory::forSites()
);
if (!$sitesNodeAggregate) {
Expand All @@ -80,12 +86,14 @@ public function removeSiteNode(SiteNodeName $siteNodeName): void
$siteNodeName->toNodeName()
);
if ($siteNodeAggregate instanceof NodeAggregate) {
$this->contentRepository->handle(RemoveNodeAggregate::create(
$workspace->workspaceName,
$siteNodeAggregate->nodeAggregateId,
$arbitraryDimensionSpacePoint,
NodeVariantSelectionStrategy::STRATEGY_ALL_VARIANTS,
));
$this->securityContext->withoutAuthorizationChecks(
fn () => $this->contentRepository->handle(RemoveNodeAggregate::create(
$workspace->workspaceName,
$siteNodeAggregate->nodeAggregateId,
$arbitraryDimensionSpacePoint,
NodeVariantSelectionStrategy::STRATEGY_ALL_VARIANTS,
))
);
}
}
}
Expand All @@ -94,12 +102,15 @@ public function createSiteNodeIfNotExists(Site $site, string $nodeTypeName): voi
{
$liveWorkspace = $this->contentRepository->findWorkspaceByName(WorkspaceName::forLive());
if ($liveWorkspace === null) {
$this->workspaceService->createRootWorkspace(
$this->contentRepository->id,
WorkspaceName::forLive(),
WorkspaceTitle::fromString('Public live workspace'),
WorkspaceDescription::empty(),
WorkspaceRoleAssignments::createForLiveWorkspace()
// CreateRootWorkspace was denied: Creation of root workspaces is currently only allowed with disabled authorization checks
$this->securityContext->withoutAuthorizationChecks(
fn () => $this->workspaceService->createRootWorkspace(
$this->contentRepository->id,
WorkspaceName::forLive(),
WorkspaceTitle::fromString('Public live workspace'),
WorkspaceDescription::empty(),
WorkspaceRoleAssignments::createForLiveWorkspace()
)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,11 @@
<h2>{neos:backend.translate(id: 'sites.new', value: 'New site', source: 'Modules')}</h2>

<div class="neos-row-fluid">
<f:form action="importSite">
<fieldset class="neos-span3">
<legend>{neos:backend.translate(id: 'sites.import', value: 'Import a site', source: 'Modules')}</legend>
<f:if condition="{sitePackages -> f:count()} > 0">
<f:then>
<div class="neos-control-group">
<label class="neos-control-label" for="site">{neos:backend.translate(id: 'sites.select', value: 'Select a site package', source: 'Modules')}</label>
<div class="neos-controls neos-select">
<f:form.select name="packageKey" options="{sitePackages}" optionLabelField="packageKey" optionValueField="packageKey" id="site" class="neos-span12" />
</div>
</div>
<f:form.submit value="{neos:backend.translate(id: 'sites.import', value: 'Import Site', source: 'Modules')}" class="neos-button neos-button-primary" />
</f:then>
<f:else>
<p>{neos:backend.translate(id: 'sites.noPackackeInfo', value: 'No site packages are available. Make sure you have an active site package.', source: 'Modules')}
</p>
</f:else>
</f:if>
</fieldset>
</f:form>

<f:form action="createSiteNode">
<fieldset class="neos-span3 neos-offset1">
<fieldset class="neos-span3">
<legend>{neos:backend.translate(id: 'sites.createBlank', value: 'Create a blank site', source: 'Modules')}</legend>
{neos:backend.translate(id: 'sites.creationContentRepository', value: 'In the content repository: "{defaultContentRepositoryForNewSites}"', source: 'Modules', arguments: {0: defaultContentRepositoryForNewSites})}

<f:if condition="{sitePackages -> f:count()} > 0">
<f:then>
<div class="neos-control-group">
Expand Down Expand Up @@ -59,6 +40,7 @@ <h2>{neos:backend.translate(id: 'sites.new', value: 'New site', source: 'Modules
</f:if>
</fieldset>
</f:form>

</div>
<div class="neos-footer">
<f:link.action action="index" class="neos-button">{neos:backend.translate(id: 'cancel', value: 'Cancel')}</f:link.action>
Expand Down
15 changes: 3 additions & 12 deletions Neos.Neos/Resources/Private/Translations/en/Modules.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,6 @@
<trans-unit id="sites.confirmDelete" xml:space="preserve">
<source>Yes, delete the site</source>
</trans-unit>
<trans-unit id="sites.import" xml:space="preserve">
<source>Import a site</source>
</trans-unit>
<trans-unit id="sites.select" xml:space="preserve">
<source>Select a site package</source>
</trans-unit>
Expand All @@ -371,6 +368,9 @@
<trans-unit id="sites.createBlank" xml:space="preserve">
<source>Create a blank site</source>
</trans-unit>
<trans-unit id="sites.creationContentRepository" xml:space="preserve">
<source>In the content repository: "{0}"</source>
</trans-unit>
<trans-unit id="sites.documentType" xml:space="preserve">
<source>Select a document nodeType</source>
</trans-unit>
Expand Down Expand Up @@ -545,15 +545,6 @@ Click on one of the nodes to only see its fallbacks and variants. Click again to
<trans-unit id="sites.update.body" xml:space="preserve">
<source>The site "{0}" has been updated.</source>
</trans-unit>
<trans-unit id="sites.theSiteHasBeenImported.body" xml:space="preserve">
<source>The site has been imported.</source>
</trans-unit>
<trans-unit id="sites.importError.title" xml:space="preserve">
<source>Import error</source>
</trans-unit>
<trans-unit id="sites.importError.body" xml:space="preserve">
<source>Error: During the import of the "Sites.xml" from the package "{0}" an exception occurred: {1}</source>
</trans-unit>
<trans-unit id="sites.siteCreationError.siteWithSiteNodeNameAlreadyExists.title" xml:space="preserve">
<source>Site creation error</source>
</trans-unit>
Expand Down

0 comments on commit 89ab5fb

Please sign in to comment.