Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contao 5.3 - introduce support for nested elements #51

Open
dennisbohn opened this issue Feb 27, 2024 · 4 comments
Open

Contao 5.3 - introduce support for nested elements #51

dennisbohn opened this issue Feb 27, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@dennisbohn
Copy link
Contributor

dennisbohn commented Feb 27, 2024

When an element group is included in a node and I want to edit the child elements, I currently get an error message.

image

Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException:
Node of folder type cannot have content elements

  at vendor/symfony/security-http/Firewall/ExceptionListener.php:136
  at Symfony\Component\Security\Http\Firewall\ExceptionListener->handleAccessDeniedException(object(ExceptionEvent), object(AccessDeniedException))
     (vendor/symfony/security-http/Firewall/ExceptionListener.php:103)
  at Symfony\Component\Security\Http\Firewall\ExceptionListener->onKernelException(object(ExceptionEvent), 'kernel.exception', object(TraceableEventDispatcher))
     (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:116)
  at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(ExceptionEvent), 'kernel.exception', object(TraceableEventDispatcher))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:220)
  at Symfony\Component\EventDispatcher\EventDispatcher->callListeners(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.exception', object(ExceptionEvent))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:56)
  at Symfony\Component\EventDispatcher\EventDispatcher->dispatch(object(ExceptionEvent), 'kernel.exception')
     (vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:139)
  at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(object(ExceptionEvent), 'kernel.exception')
     (vendor/symfony/http-kernel/HttpKernel.php:239)
  at Symfony\Component\HttpKernel\HttpKernel->handleThrowable(object(AccessDeniedException), object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:91)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:197)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:44)

If I comment out lines 71 - 73 in the "ContentListener.php", I can edit the entries.

if (!$type || NodeModel::TYPE_FOLDER === $type) {
throw new AccessDeniedException('Node of folder type cannot have content elements');
}

@dennisbohn dennisbohn changed the title Contao 5.3 - Fehler bei Elementgruppe im Backend Contao 5.3 Fehler bei Elementgruppe im Backend Feb 27, 2024
@aschempp
Copy link
Member

@leofeyer @ausi any idea why this is happening?

@ausi
Copy link

ausi commented Feb 28, 2024

I guess this is caused by $nodeId = $dc->id; on line 63 as $dc->id refers to the ID of the content element and not the node.

@Toflar
Copy link
Member

Toflar commented Feb 28, 2024

Yeah, this extension is not compatible with nested elements at the moment. Simple as that. I'll tag this as a feature because we'll have to introduce support for them, in whichever way we'll do that.

@Toflar Toflar added the enhancement New feature or request label Feb 28, 2024
@Toflar Toflar changed the title Contao 5.3 Fehler bei Elementgruppe im Backend Contao 5.3 - introduce support for nested elements Feb 28, 2024
@dennisbohn
Copy link
Contributor Author

dennisbohn commented Feb 28, 2024

This fix worked for me.

main...dennisbohn:contao-node:main

The ContentListener.php class contains an additional method to iterate through content elements.

    private function findNodeIdByContentId($contentId): int
    {
        $pid = $contentId;
        $ptable = 'tl_content';

        // Recursive node id finder
        while ($ptable === 'tl_content') {
            list($pid, $ptable) = $this->db->fetchNumeric('SELECT pid, ptable FROM tl_content WHERE id=?', [$pid]);
        }

        return $pid;
    }

The onLoadCallback method has been changed to the new method.

    public function onLoadCallback(DataContainer $dc): void
    {
        switch (Input::get('act')) {
            case 'edit':
            case 'delete':
            case 'show':
            case 'copy':
            case 'copyAll':
            case 'cut':
            case 'cutAll':
                $nodeId = $this->findNodeIdByContentId($dc->id);
                break;

            case 'paste':
                if ('create' === Input::get('mode')) {
                    $nodeId = $dc->id;
                } else {
                    $nodeId = $this->findNodeIdByContentId($dc->id);
                }
                break;

            case 'create':
                // Nested element
                if (Input::get('ptable') === 'tl_content') {
                    $nodeId = $this->findNodeIdByContentId(Input::get('pid'));
                } else {
                    $nodeId = $dc->id;
                }
                break;

            default:
                // Ajax requests such as toggle
                if (Input::get('field') && ($id = Input::get('cid') ?: Input::get('id'))) {
                    $nodeId = $this->findNodeIdByContentId($id);
                // Nested element
                } else if (Input::get('ptable') === 'tl_content') {
                    $nodeId = $this->findNodeIdByContentId($dc->id);
                } else {
                    $nodeId = $dc->id;
                }
                break;
        }

        $type = $this->db->fetchOne('SELECT type FROM tl_node WHERE id=?', [$nodeId]);

        // Throw an exception if the node is not present or is of a folder type
        if (!$type || NodeModel::TYPE_FOLDER === $type) {
            throw new AccessDeniedException('Node of folder type cannot have content elements');
        }

        $this->checkPermissions((int) $nodeId);
    }

Create, copy, edit, delete, moving, info and toggle works fine inside and outside the element group. Nested element groups are also possible. But it feels that it needs some more testing. I'm not sure what all needs to be taken into account when it comes to ajax requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants