Fusion processors and context

Hey I am struggling with fusion contexts and I hope someone can help to clear things up.

Have a look at the following example:

prototype(Neos.Neos:Page) {
    test1 = Neos.Fusion:Value {
        value = 'Test1: data'
        extension = '-extension'

        value.@process.addExtension = ${value + this.extension}
    }

    test2 = Neos.Fusion:Value {
        value = Neos.Fusion:Tag {
            content = 'Test2: data'
        }
        extension = '-extension'

        value.@process.addExtension = ${value + this.extension}
    }

    test3 = Neos.Fusion:Value {
        value = Neos.Fusion:Tag {
            content = 'Test3: data'
        }
        @context.extension = '-extension'

        value.@process.addExtension = ${value + extension}
    }
}

Which produces the following output:

Test1: data-extension
<div>Test2: data</div>
<div>Test3: data</div>-extension

The extension variable in Test2 is not available in the processor - why?

In my understanding, the tag prototype in test2 is evaluated to string, thats why I can extend it with the “+” operator. But it also seems, that it somehow opens a new context and a @context is needed to access the extension variable.

Looking at the implementation, this seems to be hard-coded to the last evaluated context object (https://github.com/neos/typoscript/blob/master/Classes/Core/Runtime.php#L844).
So in the second example this refers to the Neos.Fusion:Tag.

This would work, but I don’t think that it’s a good idea:

# ...
    test2 = Neos.Fusion:Value {
        value = Neos.Fusion:Tag {
            content = 'Test2: data'
            extension = '-extension'
        }

        value.@process.addExtension = ${value + this.extension}
    }
# ...

Probably going the @context path is the way to go, and hopefully Fusion will get some better way to define a custom “API” at some point

Thanks @bwaidelich for the clarification, but I really think its confusing.

  1. You exactly need to know of which kind a value is, which you try to extend. Sometimes it works sometimes not (without any error feedback)
  2. I thought it is a good idea to be saving with @context variables to keep the context as slim as possible - I hope the people don’t use context variables just “to be save”.

Indeed

I don’t think that you keep it any slimmer by using this really :wink:
Also, the @context is used for a lot of stuff already (e.g. to store the current node).

My problem with it is that it’s currently not really possible to separate private, public and “augmented” API so naming clashes are likely – but that’s the same with this.

It’s all about the nesting level.

“this” works always, as long as you are reading and accessing from the same nesting level.

This way you don’t have to try & error

Having played around with context variables in the last week a lot, your examples seem completely logical for me:

  1. Example
    It works, because this.extension is inside the scope (inside Neos.Fusion:Value object).

  2. Example
    It does not work, because this.extension is not available inside the scope (inside Neos.Fusion:Tag object).

  3. Example
    It works, because you made a context variable for the extension and don’t try to use this.extension, but the context variable extension, which is available in the inner scope (inside Neos.Fusion:Tag).

To clarify that for your 2nd example: This …

test2 = Neos.Fusion:Value {
    value = Neos.Fusion:Tag {
        content = 'Test2: data'
    }
    extension = '-extension'

    value.@process.addExtension = ${value + this.extension}
}

… while looking like you try to add the extension in the outer scope (you are not!), is the same as …

test2 = Neos.Fusion:Value {
    value = Neos.Fusion:Tag {
        content = 'Test2: data'
        @process.addExtension = ${value + this.extension}
    }
    extension = '-extension'
}

… which clearly shows you are out of the scope for extension. Bear in mind: the two “value” objects/variables are not the same, which is confusing, but totally up to you :wink: Inside a processor, the original value is always in the value variable and has nothing to to with your outer “value” object of type Neos.Fusion:Tag.