diff --git a/Classes/DataSource/NodeTypeDataSource.php b/Classes/DataSource/NodeTypeDataSource.php index 54d616d..f35d29c 100644 --- a/Classes/DataSource/NodeTypeDataSource.php +++ b/Classes/DataSource/NodeTypeDataSource.php @@ -3,40 +3,62 @@ namespace CodeQ\MonocleRenderer\DataSource; +use Neos\ContentRepository\Core\NodeType\NodeTypeNames; +use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter; +use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria; +use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; -use Neos\ContentRepository\Domain\Model\NodeInterface; +use Neos\Neos\Domain\Model\Site; +use Neos\Neos\Domain\Repository\SiteRepository; use Neos\Neos\Service\DataSource\AbstractDataSource; use Sitegeist\Monocle\Fusion\FusionService; use Sitegeist\Monocle\Service\ConfigurationService; class NodeTypeDataSource extends AbstractDataSource { - /** - * @var string - */ static protected $identifier = 'codeq-monoclerenderer-nodetype'; - /** - * @Flow\Inject - * @var FusionService - */ - protected $fusionService; + #[Flow\Inject] + protected FusionService $fusionService; - /** - * @Flow\Inject - * @var ConfigurationService - */ - protected $configurationService; + #[Flow\Inject] + protected ConfigurationService $configurationService; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + + #[Flow\Inject] + protected SiteRepository $siteRepository; /** - * @param NodeInterface|null $node - * @param array $arguments - * + * @param Node|null $node + * @param array $arguments * @return array + * @throws \Neos\Neos\Domain\Exception */ - public function getData(NodeInterface $node = null, array $arguments = []): array + public function getData(Node $node = null, array $arguments = []): array { - $sitePackageKey = $node->getContext()->getCurrentSite()->getSiteResourcesPackageKey(); + if ($node === null) { + return []; + } + + $contentSubgraph = $this->contentRepositoryRegistry->subgraphForNode($node); + $siteNode = $contentSubgraph->findClosestNode( + $node->aggregateId, + FindClosestNodeFilter::create( + NodeTypeCriteria::createWithAllowedNodeTypeNames( + NodeTypeNames::fromStringArray(['Neos.Neos:Site'])) + ) + ); + + if ($siteNode === null) { + return []; + } + + /** @var Site $site */ + $site = $this->siteRepository->findByNodeName($siteNode->name)->getFirst(); + $sitePackageKey = $site->getSiteResourcesPackageKey(); $data = []; foreach($this->getStyleguideObjects($sitePackageKey) as $prototypeName => $styleguideObject) { @@ -51,14 +73,13 @@ public function getData(NodeInterface $node = null, array $arguments = []): arra } /** - * @param $sitePackageKey - * @param $styleguideObject + * @param string $sitePackageKey * @return array * @throws \Neos\Neos\Domain\Exception */ - protected function getStyleguideObjects($sitePackageKey): array + protected function getStyleguideObjects(string $sitePackageKey): array { - $fusionAst = $this->fusionService->getMergedFusionObjectTreeForSitePackage($sitePackageKey); + $fusionAst = $this->fusionService->getFusionConfigurationForPackageKey($sitePackageKey); $styleguideObjects = $this->fusionService->getStyleguideObjectsFromFusionAst($fusionAst); $prototypeStructures = $this->configurationService->getSiteConfiguration($sitePackageKey, 'ui.structure'); @@ -72,7 +93,7 @@ protected function getStyleguideObjects($sitePackageKey): array foreach ($hiddenPrototypeNamePatterns as $pattern) { $styleguideObjects = array_filter( $styleguideObjects, - function ($prototypeName) use ($pattern, $alwaysShowPrototypes) { + static function ($prototypeName) use ($pattern, $alwaysShowPrototypes) { if (in_array($prototypeName, $alwaysShowPrototypes, true)) { return true; } @@ -88,11 +109,11 @@ function ($prototypeName) use ($pattern, $alwaysShowPrototypes) { /** * Find the matching structure for a prototype * - * @param $prototypeStructures - * @param $prototypeName + * @param array $prototypeStructures + * @param string $prototypeName * @return array */ - protected function getStructureForPrototypeName($prototypeStructures, $prototypeName) + protected function getStructureForPrototypeName(array $prototypeStructures, string $prototypeName): array { foreach ($prototypeStructures as $structure) { if (preg_match(sprintf('!%s!', $structure['match']), $prototypeName)) { diff --git a/Configuration/NodeTypes.Content.PrototypeRendererNode.yaml b/Configuration/NodeTypes.Content.PrototypeRendererNode.yaml index 8156227..201f4cb 100644 --- a/Configuration/NodeTypes.Content.PrototypeRendererNode.yaml +++ b/Configuration/NodeTypes.Content.PrototypeRendererNode.yaml @@ -4,13 +4,13 @@ 'Neos.Neos:Content': true ui: label: i18n - icon: 'icon-code' + icon: icon-code position: 900 inspector: groups: prototype: label: i18n - icon: 'icon-cogs' + icon: icon-cogs position: 10 creationDialog: elements: @@ -18,11 +18,11 @@ type: string ui: label: i18n - editor: 'Content/Inspector/Editors/SelectBoxEditor' + editor: Content/Inspector/Editors/SelectBoxEditor editorOptions: - dataSourceIdentifier: 'codeq-monoclerenderer-nodetype' + dataSourceIdentifier: codeq-monoclerenderer-nodetype validation: - 'Neos.Neos/Validation/NotEmptyValidator': [] + Neos.Neos/Validation/NotEmptyValidator: { } options: template: properties: @@ -37,11 +37,11 @@ inspector: group: prototype position: 100 - editor: 'Content/Inspector/Editors/SelectBoxEditor' + editor: Content/Inspector/Editors/SelectBoxEditor editorOptions: - dataSourceIdentifier: 'codeq-monoclerenderer-nodetype' + dataSourceIdentifier: codeq-monoclerenderer-nodetype validation: - 'Neos.Neos/Validation/NotEmptyValidator': [] + Neos.Neos/Validation/NotEmptyValidator: { } useStyleguideProps: type: boolean defaultValue: true @@ -61,7 +61,7 @@ group: prototype hidden: 'ClientEval:node.properties.useStyleguideProps ? true : false' position: 300 - editor: 'Neos.Neos/Inspector/Editors/CodeEditor' + editor: Neos.Neos/Inspector/Editors/CodeEditor editorOptions: buttonLabel: i18n - highlightingMode: 'text/json' + highlightingMode: text/json diff --git a/Configuration/Policy.yaml b/Configuration/Policy.yaml index cd61a8c..7a9516f 100644 --- a/Configuration/Policy.yaml +++ b/Configuration/Policy.yaml @@ -1,56 +1,51 @@ -# restrict creation and editing of `CodeQ.MonocleRenderer:Content.PrototypeRendererNode` nodetype to non-admins -privilegeTargets: - 'Neos\ContentRepository\Security\Authorization\Privilege\Node\CreateNodePrivilege': - 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode': - label: 'Create a new PrototypeRendererNode' - matcher: 'createdNodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' - 'Neos\ContentRepository\Security\Authorization\Privilege\Node\EditNodePrivilege': - 'CodeQ.MonocleRenderer:EditPrototypeRendererNode': - label: 'Edit a PrototypeRendererNode' - matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' - 'Neos\ContentRepository\Security\Authorization\Privilege\Node\RemoveNodePrivilege': - 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode': - label: 'Remove a PrototypeRendererNode' - matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' - 'Neos\ContentRepository\Security\Authorization\Privilege\Node\EditNodePropertyPrivilege': - 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty': - label: 'Edit a PrototypeRendererNode property' - matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' - -roles: - ## - # By default this role is abstract, feel free to use it however you want. - # This role is considered public API - ## - 'CodeQ.MonocleRenderer:PrototypeRendererNodeEditor': - abstract: true - label: 'Prototype Renderer Node Editor' - description: 'A user with this role is able to render any Prototype as content node.' - privileges: - - - privilegeTarget: 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty' - permission: GRANT - - 'Neos.Neos:Administrator': - privileges: - - - privilegeTarget: 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode' - permission: GRANT - - - privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty' - permission: GRANT +--- +# TODO re-enable as soon as new privilege targets for neos 9 are clarified +#privilegeTargets: +# Neos\ContentRepository\Security\Authorization\Privilege\Node\CreateNodePrivilege: +# 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode': +# label: 'Create a new PrototypeRendererNode' +# matcher: 'createdNodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' +# Neos\ContentRepository\Security\Authorization\Privilege\Node\EditNodePrivilege: +# 'CodeQ.MonocleRenderer:EditPrototypeRendererNode': +# label: 'Edit a PrototypeRendererNode' +# matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' +# Neos\ContentRepository\Security\Authorization\Privilege\Node\RemoveNodePrivilege: +# 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode': +# label: 'Remove a PrototypeRendererNode' +# matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' +# Neos\ContentRepository\Security\Authorization\Privilege\Node\EditNodePropertyPrivilege: +# 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty': +# label: 'Edit a PrototypeRendererNode property' +# matcher: 'nodeIsOfType("CodeQ.MonocleRenderer:Content.PrototypeRendererNode")' +#roles: +# 'CodeQ.MonocleRenderer:PrototypeRendererNodeEditor': +# abstract: true +# label: 'Prototype Renderer Node Editor' +# description: 'A user with this role is able to render any Prototype as content node.' +# privileges: +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty' +# permission: GRANT +# 'Neos.Neos:Administrator': +# privileges: +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:CreatePrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:RemovePrototypeRendererNode' +# permission: GRANT +# - +# privilegeTarget: 'CodeQ.MonocleRenderer:EditPrototypeRendererNodeProperty' +# permission: GRANT diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index b7f8d84..b69dfb1 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -1,4 +1,3 @@ - Neos: Neos: fusion: @@ -10,4 +9,3 @@ Neos: CodeQ.MonocleRenderer: - 'Fusion/*' - 'NodeTypes/*' - diff --git a/Resources/Private/Fusion/Content/PrototypeRendererNode/MonocleRendererNode.fusion b/Resources/Private/Fusion/Content/PrototypeRendererNode/MonocleRendererNode.fusion index 281acb1..1f98a70 100644 --- a/Resources/Private/Fusion/Content/PrototypeRendererNode/MonocleRendererNode.fusion +++ b/Resources/Private/Fusion/Content/PrototypeRendererNode/MonocleRendererNode.fusion @@ -7,7 +7,7 @@ prototype(CodeQ.MonocleRenderer:Content.MonocleRendererNode) < prototype(Neos.Ne renderer = Neos.Fusion:Case { noPrototypeName { - condition = ${!prototypeName && node.context.inBackend} + condition = ${!prototypeName && renderingMode.isEdit} renderer = CodeQ.PrototypeRendererNode:Content.PrototypeRendererNode.ErrorMessage { name = 'noPrototypeNameNotice' } @@ -22,7 +22,7 @@ prototype(CodeQ.MonocleRenderer:Content.MonocleRendererNode) < prototype(Neos.Ne } } jsonIsInvalid { - condition = ${Type.getType(prototypeProps) != 'array' && node.context.inBackend} + condition = ${Type.getType(prototypeProps) != 'array' && renderingMode.isEdit} renderer = CodeQ.PrototypeRendererNode:Content.PrototypeRendererNode.ErrorMessage { name = 'jsonIsInvalidNotice' } @@ -37,7 +37,7 @@ prototype(CodeQ.MonocleRenderer:Content.MonocleRendererNode) < prototype(Neos.Ne } } prototypeDoesNotExist { - condition = ${node.context.inBackend} + condition = ${renderingMode.isEdit} renderer = CodeQ.PrototypeRendererNode:Content.PrototypeRendererNode.ErrorMessage { name = 'prototypeDoesNotExistNotice' } diff --git a/composer.json b/composer.json index b509f2d..ea96afc 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,10 @@ "license": "MIT", "keywords": ["flow", "neos", "fusion", "html"], "require": { - "neos/neos": "~3.2 || ~4.0 || ~5.0 || ~7.0 || ~8.0 || dev-master", - "neos/fusion-afx": "^1.0 || ~7.0 || ~8.0 || dev-master", - "flowpack/nodetemplates": "~1.0 || dev-master", - "sitegeist/monocle": "^7.5 || dev-master" + "neos/neos": "~3.2 || ~4.0 || ~5.0 || ~7.0 || ~8.0 || ~9.0 || dev-master", + "neos/fusion-afx": "^1.0 || ~7.0 || ~8.0 || ~9.0 || dev-master", + "flowpack/nodetemplates": "~1.0 || dev-neos9 || dev-master", + "sitegeist/monocle": "^7.5 || dev-neos-9 || dev-master" }, "authors": [ {