protected function adjustShadowNodeDataForNodePublishing(NodeData $sourceNodeData, Workspace $targetWorkspace, NodeData $targetNodeData)
    {
        /** @var NodeData $sourceShadowNodeData */
        $sourceShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($sourceNodeData);
        if ($sourceShadowNodeData === null) {
            return;
        }

        // Technically this is not a shadow node
        if ($sourceShadowNodeData->isRemoved() === false) {
            return;
        }

        // There are no shadow nodes to be considered for a top-level base workspace:
        if ($targetWorkspace->getBaseWorkspace() === null) {
            $this->nodeDataRepository->remove($sourceShadowNodeData);
            return;
        }

        $nodeOnSamePathInTargetWorkspace = $this->nodeDataRepository->findOneByPath($sourceShadowNodeData->getPath(), $targetWorkspace, $sourceNodeData->getDimensionValues());
        if ($nodeOnSamePathInTargetWorkspace !== null && $nodeOnSamePathInTargetWorkspace->getWorkspace() === $targetWorkspace) {
            $this->nodeDataRepository->remove($sourceShadowNodeData);
            return;
        }

        $targetWorkspaceBase = $targetWorkspace->getBaseWorkspace();
        $nodeInTargetWorkspaceBase = $this->nodeDataRepository->findOneByIdentifier($sourceNodeData->getIdentifier(), $targetWorkspaceBase, $sourceNodeData->getDimensionValues());
        if ($nodeInTargetWorkspaceBase !== null && $nodeInTargetWorkspaceBase->getPath() === $sourceNodeData->getPath()) {
            $this->nodeDataRepository->remove($sourceShadowNodeData);
            return;
        }

        // From now on $sourceShadowNodeData is published to the target workspace:
        $sourceShadowNodeData->setMovedTo($targetNodeData);
        $sourceShadowNodeData->setWorkspace($targetWorkspace);

        if ($nodeInTargetWorkspaceBase !== null && $nodeInTargetWorkspaceBase->getPath() !== $sourceShadowNodeData->getPath()) {
            $nodeOnSamePathInTargetWorkspace = $this->nodeDataRepository->findOneByPath($nodeInTargetWorkspaceBase->getPath(), $targetWorkspace, $sourceNodeData->getDimensionValues());
            if ($nodeOnSamePathInTargetWorkspace === null || $nodeOnSamePathInTargetWorkspace->getWorkspace() !== $targetWorkspace) {
                $sourceShadowNodeData->setPath($nodeInTargetWorkspaceBase->getPath(), false);
            } else {
                // A node exists in that path, so no shadow node is needed/possible.
                $this->nodeDataRepository->remove($sourceShadowNodeData);
            }
        }

        // Check if a shadow node which has the same path, workspace and dimension values like the shadow node data we just created already exists (in the target workspace).
        // If it does, we re-use the existing node and make sure that all properties etc. are taken from the node which is being published.
        $existingShadowNodeDataInTargetWorkspace = $this->nodeDataRepository->findOneByPath($sourceShadowNodeData->getPath(), $targetWorkspace, $sourceShadowNodeData->getDimensionValues(), true);

        // findOneByPath() might return a node from a different workspace than the $targetWorkspace we specified, so we need to check that, too:
        if ($existingShadowNodeDataInTargetWorkspace !== null && $existingShadowNodeDataInTargetWorkspace->getWorkspace() === $targetWorkspace) {
            $existingShadowNodeDataInTargetWorkspace->similarize($sourceShadowNodeData);
            $existingShadowNodeDataInTargetWorkspace->setMovedTo($sourceShadowNodeData->getMovedTo());
            $existingShadowNodeDataInTargetWorkspace->setRemoved($sourceShadowNodeData->isRemoved());
            $this->nodeDataRepository->remove($sourceShadowNodeData);
        }
    }