Skip to content

Commit

Permalink
Merge branch 'main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
dlubitz authored Nov 12, 2024
2 parents eeb237b + 3c8438d commit 7960ab4
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 4,505 deletions.
111 changes: 111 additions & 0 deletions Classes/CommandHook/UniqueIdentifierCommandHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

namespace Neos\Form\Builder\CommandHook;

use Neos\ContentRepository\Core\CommandHandler\CommandHookInterface;
use Neos\ContentRepository\Core\CommandHandler\CommandInterface;
use Neos\ContentRepository\Core\Feature\NodeCreation\Command\CreateNodeAggregateWithNode;
use Neos\ContentRepository\Core\Feature\NodeModification\Command\SetNodeProperties;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
use Neos\ContentRepository\Core\NodeType\NodeTypeNames;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueEquals;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\PropertyName;

class UniqueIdentifierCommandHook implements CommandHookInterface
{
const NEOS_FORM_BUILDER_NODE_BASED_FORM = 'Neos.Form.Builder:NodeBasedForm';
const NEOS_FORM_BUILDER_IDENTIFIER_MIXIN = 'Neos.Form.Builder:IdentifierMixin';

public function __construct(
protected ContentGraphReadModelInterface $contentGraphReadModel,
protected NodeTypeManager $nodeTypeMananger
) {
}

public function onBeforeHandle(CommandInterface $command): CommandInterface
{
return match (true) {
$command instanceof SetNodeProperties => $this->handleSetNodeProperties($command),
$command instanceof CreateNodeAggregateWithNode => $this->handleCreateNodeAggregateWithNode($command),
default => $command
};
}

private function handleSetNodeProperties(SetNodeProperties $command): CommandInterface
{
if (isset($command->propertyValues->values['identifier'])) {
$contentGraph = $this->contentGraphReadModel->getContentGraph($command->workspaceName);
$subgraph = $contentGraph->getSubgraph($command->originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions());
$node = $subgraph->findNodeById($command->nodeAggregateId);
if ($node === null || !$this->nodeTypeMananger->getNodeType($node->nodeTypeName)->isOfType(NodeTypeName::fromString(self::NEOS_FORM_BUILDER_IDENTIFIER_MIXIN))) {
return $command;
}
$identifier = $this->findUniqueIdentifier($subgraph, $command->nodeAggregateId, $command->propertyValues->values['identifier']);
return SetNodeProperties::create(
$command->workspaceName,
$command->nodeAggregateId,
$command->originDimensionSpacePoint,
$command->propertyValues->withValue('identifier', $identifier),
);
}
return $command;
}

private function handleCreateNodeAggregateWithNode(CreateNodeAggregateWithNode $command): CommandInterface
{
if (isset($command->initialPropertyValues->values['identifier'])) {
$contentGraph = $this->contentGraphReadModel->getContentGraph($command->workspaceName);
$subgraph = $contentGraph->getSubgraph($command->originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions());

$identifier = $this->findUniqueIdentifier($subgraph, $command->nodeAggregateId, $command->initialPropertyValues->values['identifier']);
$command = $command->withInitialPropertyValues(
$command->initialPropertyValues->withValue('identifier', $identifier)
);
}

return $command;
}

private function findUniqueIdentifier(ContentSubgraphInterface $subgraph, NodeAggregateId $currentNodeAggregateId, string $identifier): string
{
$form = $subgraph->findClosestNode(
$currentNodeAggregateId,
FindClosestNodeFilter::create(
NodeTypeCriteria::createWithAllowedNodeTypeNames(
NodeTypeNames::with(NodeTypeName::fromString(self::NEOS_FORM_BUILDER_NODE_BASED_FORM)),
)
)
);

$uniqueIdentifier = null;
$possibleIdentifier = $identifier;
$i = 1;
while ($uniqueIdentifier === null) {
$descendants = $subgraph->findDescendantNodes(
$form->aggregateId,
FindDescendantNodesFilter::create(
nodeTypes: NodeTypeCriteria::createWithAllowedNodeTypeNames(
NodeTypeNames::with(NodeTypeName::fromString(self::NEOS_FORM_BUILDER_IDENTIFIER_MIXIN)),
),
propertyValue: PropertyValueEquals::create(PropertyName::fromString('identifier'), $possibleIdentifier, false),
)
);

if ($descendants->count() === 0
|| $descendants->count() === 1 && $descendants->first()->aggregateId->equals($currentNodeAggregateId)) {
$uniqueIdentifier = $possibleIdentifier;
} else {
$possibleIdentifier = $identifier . '-' . $i++;
}
}
return $uniqueIdentifier;
}
}
18 changes: 18 additions & 0 deletions Classes/CommandHook/UniqueIdentifierCommandHookFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Neos\Form\Builder\CommandHook;

use Neos\ContentRepository\Core\CommandHandler\CommandHookInterface;
use Neos\ContentRepository\Core\Factory\CommandHookFactoryInterface;
use Neos\ContentRepository\Core\Factory\CommandHooksFactoryDependencies;

class UniqueIdentifierCommandHookFactory implements CommandHookFactoryInterface
{
public function build(CommandHooksFactoryDependencies $commandHooksFactoryDependencies): CommandHookInterface
{
return new UniqueIdentifierCommandHook(
$commandHooksFactoryDependencies->contentGraphReadModel,
$commandHooksFactoryDependencies->nodeTypeManager
);
}
}
4 changes: 3 additions & 1 deletion Classes/Fusion/FormElementWrappingImplementation.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public function evaluate()
}
if (!$renderable->getRootForm()->hasPageWithIndex(1)) {
$furtherPages = $subgraph->findNodeByPath(NodeName::fromString('furtherPages'), $node->aggregateId);
$output = $output . $this->wrapNode($subgraph, $furtherPages, '', $fusionPath . '/furtherPages');
if ($furtherPagesNode !== null) {
$output = $output . $this->wrapNode($subgraph, $furtherPages, '', $fusionPath . '/furtherPages');
}
}
return $output;
}
Expand Down
7 changes: 7 additions & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,10 @@ Neos:
javascript:
"Neos.Form.Builder:PlaceholderInsert":
resource: '${"resource://Neos.Form.Builder/Public/JavaScript/PlaceholderInsert/Plugin.js"}'

ContentRepositoryRegistry:
presets:
'default':
commandHooks:
'UniqueIdentifierCommandHookFactory':
factoryObjectName: Neos\Form\Builder\CommandHook\UniqueIdentifierCommandHookFactory
1 change: 1 addition & 0 deletions Resources/Private/PlaceholderInsert/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
22 changes: 22 additions & 0 deletions Resources/Private/PlaceholderInsert/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const esbuild = require('esbuild');
const extensibilityMap = require('@neos-project/neos-ui-extensibility/extensibilityMap.json');
const isWatch = process.argv.includes('--watch');

/** @type {import("esbuild").BuildOptions} */
const options = {
logLevel: "info",
bundle: true,
minify: true,
target: "es2020",
sourcemap: 'linked',
entryPoints: { Plugin: 'src/index.js' },
loader: { '.js': 'tsx' },
alias: extensibilityMap,
outdir: "../../Public/JavaScript/PlaceholderInsert",
}

if (isWatch) {
esbuild.context(options).then((ctx) => ctx.watch())
} else {
esbuild.build(options)
}
10 changes: 4 additions & 6 deletions Resources/Private/PlaceholderInsert/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
"license": "MIT",
"private": true,
"scripts": {
"build": "neos-react-scripts build",
"watch": "neos-react-scripts watch"
"build": "node build.js",
"watch": "node build.js --watch"
},
"devDependencies": {
"@neos-project/neos-ui-extensibility-webpack-adapter": "*"
},
"neos": {
"buildTargetDirectory": "../../Public/JavaScript/PlaceholderInsert"
"@neos-project/neos-ui-extensibility": "^8.3",
"esbuild": "^0.17.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { connect } from "react-redux";
import { SelectBox } from "@neos-project/react-ui-components";
import React, { PureComponent } from "react";
import { neos } from "@neos-project/neos-ui-decorators";
import { $transform } from "plow-js";
import { selectors } from "@neos-project/neos-ui-redux-store";

export const parentNodeContextPath = contextPath => {
Expand All @@ -21,9 +20,9 @@ export const parentNodeContextPath = contextPath => {
};

@connect(
$transform({
nodesByContextPath: selectors.CR.Nodes.nodesByContextPathSelector,
focusedNode: selectors.CR.Nodes.focusedSelector
state => ({
nodesByContextPath: selectors.CR.Nodes.nodesByContextPathSelector(state),
focusedNode: selectors.CR.Nodes.focusedSelector(state)
})
)
@neos(globalRegistry => ({
Expand Down
13 changes: 9 additions & 4 deletions Resources/Private/PlaceholderInsert/src/manifest.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import manifest from "@neos-project/neos-ui-extensibility";
import PlaceholderInsertDropdown from "./PlaceholderInsertDropdown";
import placeholderInsertPlugin from "./placeholderInsertPlugin";
import { $add, $get } from "plow-js";

const addPlugin = (Plugin, isEnabled) => (ckEditorConfiguration, options) => {
if (!isEnabled || isEnabled(options.editorOptions, options)) {
ckEditorConfiguration.plugins = ckEditorConfiguration.plugins || [];
return $add("plugins", Plugin, ckEditorConfiguration);
return {
...ckEditorConfiguration,
plugins: [
...(ckEditorConfiguration.plugins ?? []),
Plugin
]
};
}
return ckEditorConfiguration;
};
Expand All @@ -17,12 +22,12 @@ manifest("Neos.Form.Builder:PlaceholderInsert", {}, globalRegistry => {
.get("richtextToolbar");
richtextToolbar.set("placeholderInsertt", {
component: PlaceholderInsertDropdown,
isVisible: $get("formatting.placeholderInsert")
isVisible: editorOptions => editorOptions?.formatting?.placeholderInsert
});

const config = globalRegistry.get("ckEditor5").get("config");
config.set(
"placeholderInsert",
addPlugin(placeholderInsertPlugin, $get("formatting.placeholderInsert"))
addPlugin(placeholderInsertPlugin, editorOptions => editorOptions?.formatting?.placeholderInsert)
);
});
Loading

0 comments on commit 7960ab4

Please sign in to comment.