How to override Admin controller or action


#1

Hello

I’m using 5.x version of PIMCore and would like to know if it is possible to override an admin controller or action.

This is the action I need to override

vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/DataObjectController -> saveAction

Please, let me know.
Thanks!


#2

Since the Controller is registered as Service, you could either create a service.yml (or xml, or php, what you prefer) and change the identifier Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController to your overriding controller, or you create a CompilerPass, get the Definition and change the class.


#3

Hello @dpfaffenbauer

we’re trying something similar like @alexdrupal

  1. We created a DataObjectController in our Bundle which extends the original Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController Controller

  2. We defined the following in our services.yml (in PimcoreModBundle/Resources/config/services.yml

    services:
        Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController:
            class: PimcoreModBundle\Controller\DataObjectController

For a simple test, we doesn’t define or override any method, just a replacement of the original Controller. If we reload Pimcore Admin UI we get instantly the following error message:

Message: Controller "PimcoreModBundle\Controller\DataObjectController::treeGetChildsByIdAction()" 
requires that you provide a value for the "$eventDispatcher" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.

So it looks like the dependency injection (of the EventDispatcherInterface) doesn’t work anymore.

Could you please provide some help or an example of how to override a method inside a Pimcore Controller (especially the DataObjectController).

We also tried to create a CompilerPass and switch the definitions, but the error is the same…

public function process(ContainerBuilder $container)
    {
        $controllerDefinition = $container->getDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController");
        $container->setDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController", new ChildDefinition(PimcoreModBundle\Controller\DataObjectController::class));
    }

Any help would be very appreciated! :slight_smile:


#4

you are on the right path with the compiler pass, its just not 100% right yet, try it like this:

public function process(ContainerBuilder $container)
{
    $controllerDefinition = $container->getDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController");
    
    $controllerDefinition->setClass(PimcoreModBundle\Controller\DataObjectController::class);
    
    $container->setDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController", $controllerDefinition);
}

#5

Wow, very cool for this quick answer!

But it doesn’t work, the error message is the same :frowning:

Our Custom Controller looks exactly like this:

namespace PimcoreModBundle\Controller;

class DataObjectController extends \Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController
{
    // Nothing here
}

Edit

It’s funny… if we add only this method to our (empty) Controller, the error is gone:

/**
 * @Route("tree-get-childs-by-id")
 * @Method({"GET"})
 *
 * @param Request $request
 * @param EventDispatcherInterface $eventDispatcher
 *
 * @return JsonResponse
 */
public function treeGetChildsByIdAction(Request $request, EventDispatcherInterface $eventDispatcher = null)
{
    if ($eventDispatcher === null) {
        $eventDispatcher = $this->container->get('event_dispatcher');
    }

    return parent::treeGetChildsByIdAction($request, $eventDispatcher);
}

But this leads into the next strange problem, because every other method inside the parent Controller would get the same error… always if the EventDispatcherInterface is an argument


#6

how does the autoload service configuration look for your bundle? Guess thats the issue


#7

This is our whole PimcoreModBundle/Resources/config/services.yml file:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    PimcoreModBundle\Controller\:
        resource: '../../Controller'
        public: true
        tags: ['controller.service_arguments']

… nothing else, in no other file.

EDIT

If we try to add a new answer, we got the message from the forum We're sorry, but new users are temporarily limited to 3 replies in the same topic.

Can anyone allow us to add more answers :smiley:


EDIT 2
This is what we tried to answer :smiley:

Hmmm we removed the Controller part, but this didn’t helped. Additionally we moved the Controller into a subfolder, but same error message.

To summarize what we exactly did:

Created a CompilerPass

class DataObjectPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $controllerDefinition = $container->getDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController");
        $controllerDefinition->setClass(DataObjectController::class);
        $container->setDefinition("Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController", $controllerDefinition);
    }
}

Added the CompilerPass inside the PimcoreModBundle Class

public function build(ContainerBuilder $container)
{
    $container->addCompilerPass(new DataObjectPass());
}

Our services.yml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

Our Controller which should replace the original \Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController

namespace PimcoreModBundle\Controller\Admin;


use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class DataObjectController extends \Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController
{
  // No method defined, completely empty class
}

Thanks a bunch for your help!!


#8

yep, and thats the issue. Either remove the Controller part or move your controller to a subdirectory.


#9

Hi guys,
I am not able figure out the final working solution to this. Could you please share it?
Thanks!


#10

Hi @mertaivan,

we would share our solution, but unfortunately it isn’t working yet.
In our last post is every line of code our bundle contains. We still hope for some help from @dpfaffenbauer

When there is a working solution we’ll share the bundle here, promised :wink:


#11

did you try to clear the cache?


#12

Hi @dpfaffenbauer

Clearing cache didn’t work for me and I am still getting

Message: Controller “AppBundle\Controller\DataObjectController::treeGetChildsByIdAction()” requires that you provide a value for the “$eventDispatcher” argument.

Thanks


#13

Cache clearing also isn’t working for us.
@dpfaffenbauer did you try our bundle (which I’ve uploaded for you)?


#14

will test your bundle and publish it here later today.


#15

there you go guys, both of you owe me a beer now, this took way longer than expected… had to debug symfony in order to understand how autowiring works. :stuck_out_tongue:

PimcoreModBundle.zip (5.0 KB)

the bundle now uses configuration to overwrite controllers, simply add following to your config.yml

pimcore_mod:
    admin_controllers:
        Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController: AppBundle\Controller\Admin\DataObjectController

example controller:

<?php

namespace AppBundle\Controller\Admin;

use Pimcore\Bundle\AdminBundle\Controller\Admin\DataObjectController as BaseDataObjectController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class DataObjectController extends BaseDataObjectController
{
    public function treeGetChildsByIdAction(Request $request, EventDispatcherInterface $eventDispatcher = null)
    {
        $result = parent::treeGetChildsByIdAction($request, $eventDispatcher);

        if ($result instanceof JsonResponse) {
            $json = $result->getContent();
            $json = json_decode($json, true);

            $json['blub'] = 'blab';

            return new JsonResponse($json);
        }

        return $result;
    }

}

#16

You’re indeed a master, @dpfaffenbauer. I have no idea what you’re doing there (I am just getting started with Symfony because of Pimcore) but it works - I changed above in the same manner for AppBundle.
Thanks a lot and ask me for a beer when you’re in Prague :).


#17

:wink:

Sure I will come back to Prague one day :wink: I will come back to your offer.


#18

Yeah! Finally it’s working !
Great, thank you very much for your help.

If you ever come to cologne, you will get beer :wink:


#19

I will come back to your offer as well :wink: