stephpy/timeline-bundle

[2.0] Twig components

Closed this issue · 21 comments

With 2.0, subject is the only one mandatory component, you can add other component as you want.

BTW, there's an issue on twig rendering.

{{ timeline_component_render(action,'subject') }}

{{ timeline_component_render(action, 'directComplement') }}

Will not work, because directComplement block is not defined, we have to do that:

{% block directComplement_component %}
{% spaceless %}
    {% set type = type|default('verb') %}
    {{ block('action_component') }}
{% endspaceless %}
{% endblock %}

{% for action in timeline %}
    {% timeline_action_theme action _self %}

    {{ timeline_component_render(action,'subject') }}

    {{ timeline_component_render(action, 'directComplement') }}
{% endfor %}

Component rendering system is awesome, no problem about it. Just, could it be easier and return a $object->__toString() if block is unknown ? or the text if it's a text component ?

ping @brentc

And is it possible to apply a theme for a collection of actions ? instead of redefine theme for each actions ?

Let me get back to you about this tomorrow.

Thank you ;)

I believe the original syntax is {{ timeline_component_render(action, 'direct_complement') }}, following the concept of underscores-for-options, camelCaseForCode, and also because it makes the block names follow the twig convention.

If you're planning on using camelCased component names, you'll need to either

  1. Change the component block names to use camel cased names
  2. CamelCase-to-underscore the component name when determining the block to render.

With regards to themeing a collection, it might be possible to check if action parameter is checked if it's a collection, and if so, iterate through the collection and theme each element...

I can submit something later this week that does that.

That's not the main issue i see, in 1.x, components was subject, directComplement, indirectComplement, BTW, we had theses components defined on HighcoTimelineBundle:Action:component.html.twig.

So, in 1.x if you render a component DirectComplement, it'll make a __toString of value if a block theme isn't defined.

On 2.x, subject is defined HighcoTimelineBundle:Action:component.html.twig but not others. You'll have to create a new block for each component even if you just want to make a __toString. I guess return a __toString of value could be a good solution if a block theme is not found.

I would suggest that, although subject is the only required component, the bundle continue to provide basic blocks for direct and indirect components, as they did in 1.x. to lessen development startup.

Yes, it could be a solution. Return a __toString or text of Component would be a good solution too ? No ?

This can be worked around by adding action_component as the last-level block to try rendering.

I believe if you change TimlineExtension:L182 from:

$types = array($component);

To:

$types = array('action', $component);

You will get that fallback.

Ok, i'll give a try to this solution asap, thanks.

This way when rendering a component it will try, in this order:

_model_class_componentName
_model_class_default
componentName_component
action_component

You might want to make 'action' an invalid component name…

Yes, you are right.

And just to be clear, adding action_component as the last out block will provide the __toString or text value you were talking about based on how getComponentVariables works. :)

Added on 0bbbfb8

At this moment, if component is named action ... it'll not fallback to __toString.

Thanks.

Added some comments to 0bbbfb8

azr commented

Hi,

I'm not sure if these upgrades are available yet but I got some problems :

With the default template : {{ timeline_component_render(timeline, 'subject') }} - {{ timeline_component_render(timeline, 'verb') }} I get

<span class='subject'></span> - <span class='verb'></span>

For every action it seems.
I inserted a var_dump($this->varStack[$rendering]) in https://github.com/stephpy/TimelineBundle/blob/master/Twig/Extension/TimelineExtension.php#L224 :

array
  'variables' => 
    array
      'value' => null
      'model' => string 'MG\UserBundle\Entity\User' (length=25)
      'id' => 
        array
          0 => int 25
      'text' => null
      'normalized_model' => string 'mg_userbundle_entity_user' (length=25)
      'type' => string 'subject' (length=7)
      'action' => 
        object(MG\TimelineBundle\Entity\Action)[1522]
          protected 'id' => int 22
          protected 'actionComponents' => 
            object(Doctrine\ORM\PersistentCollection)[1561]
              ...
          protected 'timelines' => 
            object(Doctrine\ORM\PersistentCollection)[1531]
              ...
          protected 'verb' => string 'create' (length=6)
          protected 'statusCurrent' => string 'published' (length=9)
          protected 'statusWanted' => string 'frozen' (length=6)
          protected 'duplicateKey' => null
          protected 'duplicatePriority' => null
          protected 'duplicated' => boolean false
          protected 'createdAt' => 
            object(DateTime)[1461]
              ...
  'types' => 
    array
      0 => string 'subject' (length=7)
      1 => string '_mg_userbundle_entity_user_default' (length=34)
      2 => string '_mg_userbundle_entity_user_subject' (length=34)
      3 => string 'action' (length=6)

Also it seems like my default user component (_mg_userbundle_entity_user_default_component) is not taken into consideration unless I comment this condition :https://github.com/stephpy/TimelineBundle/blob/master/Twig/Extension/TimelineExtension.php#L214

May be the condition should be added before so the order is kept ? ( we have to remember the loop after is reverted)

Hi, i fixed the order of rendering theme.

I don't understand your first request.

azr commented

Okay awesome :D

Woops, may be that was not clear... Sorry about that.

It's just that I'd like to print for example my user's username in my twig template, and in that case it's the subject so in the template I do {{ timeline_component_render(action, 'subject') }}.

But at that point I don't know how to get my user.

The Twig locals are the same as the 'variables' of the var_dump up there.

I assumed my user would be located inside value ( that is always null ) but I'm also no sure if this feature is over or not...

That's why all the questions :)

Hi,

You can do:

{% set user = action.getComponent('subject').data %}

Be careful, getComponent can return a text component action.getComponent('foo').isText() or an object (in your use case).

I hope i'm clear :)

If the user return null, it's due to the dataHydrator which is not activated or cannot fetch the user from database.

To make DataHydrator works with the locator orm or odm. You have to define in component:

model= *EntityModel* -> example: Acme\UserBundle\Entity\User
identifier=*id* -> it will be serialized automatically to works with composite keys.
azr commented

Okay awesome yes I thought that the DataHydrator came in the default configuration.

And also I did $subject = $actionManager->findOrCreateComponent( get_class( $user ), array( $user->getId() ) ); < the user was not hydrated that way :)

Dumb mistakes sorry sorry !

Thanks, All fixed now :D

No problem ;)