stephpy/timeline-bundle

Weird issue rendering subject when doing $actionManager->findOrCreateComponent in subrequest

Closed this issue · 10 comments

I have a timeline page in a base template. The base template also does sub-request e.g. to render notification counts for example:

{% render "FooSiteBundle:Bar:notificationCount" %}

Everything works fine rendering the timeline untill I do $actionManager->findOrCreateComponent in one of the sub-request of my base template.

My controller looks like this

        $securityContext = $this->get('security.context');
        $user = $securityContext->getToken()->getUser();

        if ($securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {

            $obs = $this->getTimeLineEntries(1, 10);
            //..log $obs
            return $this->render('FooSiteBundle:Default:wall.html.twig', array('entries' => $obs));

        }

When I log $obs, I can see the subject is properly hydrated, but in my twig template {{ timeline.subject.data }} is empty.

I'm not sure if this is a twig bug or if there's something up with the timeline. What I do know is that when I remove $actionManager->findOrCreateComponent from the sub-request, {{ timeline.subject.data }} is not empty..

Any clues?

Hi,

$action->findOrCreateComponent(..); // return a Component

And {{ timeline.subject }} returns a component, {{ timeline.subject.data }} returns the entities related (via doctrine hydrator). In controller, data is hydrated on subject component ?

In twig, it should be really simple, {{ timeline.subject.data }} is equal to {{ $action->getSubject()->getData() }}

$action->getSubject()->getData() is hydrated in the controller bu in the template timeline.subject.datais not..

Wow ... indeed it's weird.

If i understand, the issue is when you call ``$actionManager->findOrCreateComponent` on a component which has data already loaded. It is ?

If it's, findOrCreateComponent must have a pool of component already loaded to fix this issue.

Twig data are rendered at the end, it seems than calling $actionManager->findOrCreateComponent is clearing data of your component. Can you confirm that ?

It is getting weirder:

Suppose we have three timeline entries:

User1 | created_event | X
User2 | created_event | Y
User1 | created_event | Z

Now in my sub-request controller:


public function notificationCountAction() {

        $securityContext = $this->get('security.context');
        $user = $securityContext->getToken()->getUser();

        $actionManager = $this->get('spy_timeline.action_manager');
        $subject = $actionManager->findOrCreateComponent('Foo\Bundle\SiteBundle\Entity\User', User1);

        ...
    }

When I do findOrCreateComponent for User1, than User1 is not hydrated in the template, but user 2 is. When I do findOrcreateComponent for User2, thans User2 is not hydrated in the template, but User1 is.

This sounds like what you're describing

Ok, I see. I cannot investigate on it right now, i'll look at this as soon as possible. It may be difficult :\

Allright thanks!

Imo we should have a components container where we'll try to get components before calling storage (as a pool system).

@thomask you can fix it by using listener instead of data hydrator:

 orm:
            post_load_listener:   true

It should fix your issue. This issue is really difficult to fix with only data hydrator. This can impact on number of sql queries but sometimes they are less queries with listener ;)

Listener:

Get the reference of the entity and add it to component (on post load, if entity is already loaded, does not make a sql query).

DataHydrator:

Group queries to make 1 query by entity (if action check for User 3, and an other one check for User 4, only one query will be done ...). Problem, in your case, if you get a component from database and don't re apply DataHydrator filter it'll loose the data :(

Try with post_load_listener solution, it should fix your issue. At this moment, i don't see how to fix this issue via the data hydrator, very difficult ...

Alright thanks!