Processing links with Fusion, in a text edited with aloha

Hi,

I’m working on a glossar feature:
I’ve special GlossarPages that hold the Glossar entries (Headline, description, image).
It works more or less. A Link to a GlossarPage within a normal inline editable Text brings up a small css popup on mouseover.
I grab the link using pregMatch().
My Problem:
In the Backend href=“node:// …”.
In the Frontend, there is the normal uri in the href attribute.
As a work around I use the Link-Text between the opening and closing tags to search in the GlossarPages (instanceOf) title property.
So, if the link text and the title text are differen it fails.

  1. How can I get the node identifier in frontend and in backend mode out of the href attribute?

  2. To get more than one link out of the text I’ve implemented an Eel-Helper with pregMatchAll().
    Works fine, but than??
    There is no loop or “each in Fusion”. If I could handle 10 Glossar entries in a text, that would be sufficient for me.
    Do I really have to write 10 Cases, one after the other, or is there some “more elegant” way?
    Do it partly in Fluid?

  3. Is there another possibility to insert HTML-Snippets using aloha?

I hope, someone can give me a hint.

Have a nice weekend
Klaus

Hello Klaus,

Neos stores the urls for nodes in the form node://node_identifierinternally. Those urls are converted in the frontend with the ```TYPO3.Neos:ConvertUris` prototype that is applied to every inline editable property with the autogenerated fusion. (see neos-development-collection/TYPO3.Neos/Classes/TYPO3/Neos/Domain/Service/DefaultPrototypeGenerator.php at 2.3 · neos/neos-development-collection · GitHub, http://neos.readthedocs.io/en/stable/References/NeosTypoScriptReference.html#converturis)

text = ${q(node).property('text')}
text.@process.convertUris = TYPO3.Neos:ConvertUris

To answer your question. As long as your code is applied before the @process.convertUris it will see the node:// uris and can use the identifiers.

I would try to create a custom version of convertUris that is applied before the usual one an converts the the Glossary Links like you need it.

That would look like:

//define processor 
prototype(Vendor.Site:ConvertGlossaryUris) {
    @class = 'Vendor\\Site\\Fusion\\ConvertGlossaryUris'
}

// apply convertGlossaryUris before convertUris 
prototype(TYPO3.Neos.NodeTypes:Text) {
   text.@process.convertGlossaryUris = Vendor.Site:ConvertGlossaryUris
   text.@process.convertGlossaryUris.@position = 'before convertUris'
}

It still is a good idea to do actually convert those links only in the frontend. Because in the backend you want to be able to click on a linked item and edit the text. You can look at the code of convertUris as reference for that.

Not that i know of.

Regards, Martin

Hi Martin,
thanks a lot!

Hi,

I like your proposal Martin.
This way one can implement even more special processings for different link types in a consistent manner.

I started to go that way but get stucked again (in the PHP code):
There are so many factories, interfaces, contexts, workspaces, dimensions, runtime …
I saw some posts (from Martin and Dominique) and tried this or that.
In most of the cases I just get a “500” with a white page.

I already got the node identifiers of the links within the text.
For each identifier I want to:

  1. Get a node using the node id (got null).
  2. Check if it is of type GlossaryPage.
  3. If true: get the properties of that node.
  4. Build the markup for the CSS popup
  5. Replace the old link with the markup.
  6. Add a cache tag for every GlossaryPage link found to the cache of the Text content element.
    (Cound be also a tag like NodeType_GlossaryPage)

I hope someone can help me.
Klaus

Hello Klaus … i would go this way

1. Pass the reference to your site to the processor

//define processor 
prototype(Vendor.Site:ConvertGlossaryUris) {
	@class = 'Vendor\\Site\\Fusion\\ConvertGlossaryUris'
	site = ${site}
}

2. Read the node in the evaluate method of ConvertGlossaryUris

// @var NodeInterface
$site = $this->tsValue('site');

3. Find the id’s of the nodes you want to process

you have that already so i skip that

4. Use flow Query to find a node for a given id in a site

     // the flow query context is always an array
$flowQuery = new FlowQuery([$site]);
$targetNode = $flowQuery->find('#' + $nodeIdentifier)->get(0);

5. Check for the type of the target

if ($targetNode instanceof NodeInterface && 
	$targetNode->getNodeType()->getName() === 'Vendor.Site:GlossaryItem' 
)  {
	// here happens magic
}

Hint: You will have to add use statements for the full namespaces for FlowQuery and NodeInterface but in general this should do the trick. As usual beware of typos. This is untested code but i’ve done that several time that way.

Thanks very much again Martin!

I’ll have a long weekend now.
In the middle of the next week I’ll continue.
When it works like it should, I will paste the code here.

Klaus