It would be nice if you could extend the option translation= to not only allow language codes but also an asterisk, like translation="*". The asterisk then means: use the language code of the embedding node. So if the current node is of language code "de", the asterisk is replaced by "de" then.

You could say that a node is unlikely to change its language and therefor the asterisk is not necessary. But if a node gets translated, the translator should only translate content and leave the (linodef) tags as they are whenever possible. So, after the embedding node gets translated, and the embedded node, too, the reference gets correctly updated. Thus the German node embeds German content, the English node embeds English content with identical linodef-tags.

In _linodef_find_nodesnfields it can easily be checked (insert something like the following after line 198 or 199)

  $language = ($language = '*') ? $node->translation->language : $language;

Would this be possible?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Roi Danton’s picture

Title: Extend option "translation=" » Extend option translation so the language of the embedding node can be used automatically

Good idea. However

  1. The $node object your code snippet uses is the embedded and not the embedding node
  2. Normally asterix means 'all' of something or '0 - ∞'. Maybe someone knows a better character for using a certain property of the current context? Or using option 'translation' without a value for selecting the node language might even be the simplest way for the user? But then the validation and retrieve code will get unnecessarily complex. So I'm fine with asterix if no better idea appears.

While (2) is minor we need a solution for (1) to get the current node object. It is likely very simple but it is too late for me to find the required function right now.

Pepe Roni’s picture

Title: Extend option translation so the language of the embedding node can be used automatically » Define joker character to use value from "this" node

I would like to extend my prior request, and possibly make it easier for you to implement it:

Not only translation=value but any value could be taken from current node. Perhaps you can define the character tilde (~) as such a character. Tilde must not be enclosed in quotes, otherwise it would be taken ("heeded") as is. Thus the following would be possible:

[#1234,language=~] means: [#1234,language="de"] if the embedding node language is "de"

[#~:field_attached_image:0] would refer to the first attached image of this node.

The charm of this approach is: you can apply the filter for tilde when the node is saved as this properties are not likely to change unless you save the node again. But linodef would then be a 2 pass filter: the first pass to replace ~ on node save, the second pass to embed the fields on node display.

My request is for comfort and usability reasons. If this function is not available, you can not preview a new node when embedding images from the current node (it currently has no node id!). Also when translating nodes the node id changes and you have to change the node id in the linodef tag.

I have added a suggestion how to easily embed an imagefield with linodef in #335191: CCK fields formatting (support Image- and Filefield)

Roi Danton’s picture

Thanks, this suggestion sounds very good.

But linodef would then be a 2 pass filter: the first pass to replace ~ on node save, the second pass to embed the fields on node display. [...] you can not preview a new node when embedding images from the current node (it currently has no node id!)

I see. So you don't have to edit the node again to embed the image fields of this node.

Also when translating nodes the node id changes and you have to change the node id in the linodef tag.

When replacing tilde on save (what a filter should not do though) this function does not help here since when you translate the node you still have to change the node ID in the tag. So the tilde should be replaced on filtering and not saving. hook_filter() does not provide information about the node using the filter (current node/"this" node) but arg()/menu_get_object() can be used. However this has a major downside. It does not work when the node is used in views/panels (similar problem to buildmodes).

So before starting to work on this we have to find a way to retrieve the object the filter is applied on. Or a workaround for views, e.g. similar to the way I'm using for views in taglists.

radj’s picture

+1

Very nice idea. I don't want to have to submit the node before I can use linodef.

What if we left out the node ID to refer to "this" node instead (as a suggestion to the format)?
[:field_name:multi_value_number]

Roi Danton’s picture

@Format: [#any_character] is recognized as comment so a joker char, e.g. [#~], is fine for an automatic replacement. Well, the for the short syntax [#:content] seems fine, too (using "[#:" to detect that syntax). But this is easy to change and could be discussed later.

I don't like to do a replacement of ~ with the node ID on node save/presave (lets call it "nodeapi solution"). Yes, it solves the problem with embedding fields of a new node - though I'm not sure if this will work when previewing since in that step no node ID is present - but:

  • the joker character would be useable only once - after saving the node it is replaced by the node ID
  • therefore translation="~" and possible other use cases (e.g. for view arguments) wouldn't work

Investigating of a filter api solution would be worth the headache. So the joker character is saved with the node and is replaced on the fly when filtering.

Summary:
Nodeapi: no performance hit, implementation known, can be used only once
Filter api: slight performance hit (depends on determination of the current node), way of implementation not known, can be used as often as wanted (e.g. copy and paste the text in a different node without having to adjust Linodef tags that embeds fields of the current node - similar to the translation feature requested by druppi)

Pepe Roni’s picture

When I wrote "when the node is saved" I didn't mean to "burn it into the source text". Am I wrong but isn't there a "raw" version of the body text and a filtered version of the text, at least for filters that can be applied on node save (no dynmic text independent from this node)? Other filters like linodef can be applied on node display only.

So a filter for #~ and option="~" can be applied "on node save" (not burned in into the source text!), thus the rest of the linodef filter can do its work on node display?

Roi Danton’s picture

Version: 6.x-1.0-rc3 » 6.x-1.0-rc5

Indeed you are correct. Besides using hook_nodeapi (insert/update or presave/validate) hook_view might also work. There the substituted joker won't be saved at all.

Maybe with nodeapi->validate it is possible to embed fields from a new node that isn't saved in the db yet when previewing (if the node object already contains the attached field content).

Roi Danton’s picture

Am I wrong but isn't there a "raw" version of the body text and a filtered version of the text, at least for filters that can be applied on node save (no dynmic text independent from this node)?

No, only body and teaser are saved in separated columns in the node_revision table. Filtered node content is only saved in cache if the filter allows caching. But since nodeapi provides altering when viewing the node this might not be a problem for using the nodeapi approach.

Roi Danton’s picture

Status: Active » Needs work
FileSize
2.7 KB

Current research on nodeapi:

  • load: viewing yes, previewing yes, editing no, translating no (the joker is substituted like when viewing)
  • prepare: viewing no, previewing yes, editing no, translating no (substituted)
  • view/alter: doesn't work at all since content is already filtered

I've done a workaround for "load" by excluding edit (node/NID/edit) and add-urls (node/add) by using arg() arg(0) == 'node' && (arg(2) == 'edit' || arg(1) == 'add'). This might not work when a module is altering the edit node paths (url aliases are not affected) - however no popular module does this (if you know one then let me know, please). Also the replacement when previewing doesn't work.

So the only downside of this approach is the lost substitution when previewing:

  • load default: viewing yes, previewing yes, editing no (substitution), translating no (substitution)
  • load exclusion: viewing yes, previewing no, editing yes (no substitution), translating yes (no substitution)

The attached patch replaces node IDs [#~] and language translation="~". The functionality can be expanded.

Pepe Roni’s picture

FileSize
46.48 KB

Thank you, it works well in teaser and full view!

But in preview mode the full node preview looks odd (see the attached screenshot). Here is an example of the body text:

[#~:field_image:0]
Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
[#~:field_image:1]

I have added an image field to this node type with multiple values.

Pepe Roni’s picture

by the way, why does linodef not depend on filter module?

Roi Danton’s picture

But in preview mode the full node preview looks odd (see the attached screenshot)

In preview the linodef nodeapi hook is not executed and therefore the "~" is not replaced. It seems as if another filter is removing the tilde. Please provide a list of the filters you are using.

by the way, why does linodef not depend on filter module?

Thanks, added dependency.

Pepe Roni’s picture

My filter config is a s follows:

  1. html-filter (escape all html)
  2. linodef
  3. texy

And, yes, you're right. It was the texy module, that scrambled the output (though there is no documented feature for a single ~). It works nice, if the linodef tag is not at the very beginning of the text. If it can happen in this circumstances (preview), it may also happen, if texy was evaluated before linodef (and then in node full view!)

I have changed ~ to # in the linodef.module and it works all as desired (like [##:field_inline_image_left:0]). Thus # is the better choice than ~. If I can change this character, what about a configuration option to let the admin decide which character to use as joker character?

Happy New Year!

Roi Danton’s picture

Happy New Year! :)

In the new patch I implemented joker replacement also when previewing (based on path). That way other filters won't interfere since the joker is replaced in the prepare filter step (before processing filters).

Using "#" seems to be more convenient than "~". I've changed that. And an admin definable joker character is a meaningful feature, will add that later

The next step is to make tags working for fields of new nodes without node ID. I assume that the node object contains all the fields when previewing. Atm I be afraid that I can't use the existing replace functions (in linodef-filter.inc) without changing their structure at a whole (reading an object instead db records). I think I have to write new functions for this purpose.

Pepe Roni’s picture

Thanks for the patch. I tested it and it replaces the joker for saved nodes in preview mode as you described.

But your approach is not correct :(

For saved nodes you display the saved values of the currently edited node in preview mode, not the edited values. Have a look at this scenario:

A node has an attached field and the user changed the value of this field. The field value will be embedded by linodef. If you preview the node, the old value will be displayed and not the changed value. The user will be confused: I changed the value and the old value is displayed in preview mode. What did I make wrong?

So, even in edit mode the preview has to be handled like it was added. You can't rely on node id in edit mode! So it is better to let the linodef tags as is than show false replacements.

Roi Danton’s picture

I see. The preview for new nodes will use the current node object (instead of a saved node). The same technique will fit for previewing of existing nodes. Thanks for pointing out!

Roi Danton’s picture

In views the nodeapi hooks are not called for every loaded node. So in some fields of the view the joker works and in some not. It seems we have to rethink the nodeapi approach and investigate why views doesn't use hook_nodeapi for each node: This seems to be intentionally for performance reasons, e.g. #178153: hook_nodeapi 'view/alter' not called for list and table view.

Roi Danton’s picture

hook_nodeapi is not invoked at field views at all. I'm searching for a view function/hook that allows retrieving the corresponding node object of the displayed field. Maybe this also could fix the buildmode detection within views.

Roi Danton’s picture

This patch supports views and uses the current node object when previewing/adding a new node.

Pepe Roni’s picture

Thanks,

tested with [##], [##:field_image] and [##:field_computed_field_not_stored_in_database]. Works like a charm, except for the latter :(

But I think that's not a linodef problem but a cck problem. The computed field seems to be evaluated on node load only and does not exist (or contains "old" value) in preview mode.

Perhaps you do have a solution for this?

Roi Danton’s picture

Thanks for testing! :)
In another issue there was also a problem with computed fields i think (can't find it yet) where the value was not stored in database. For preview I use the node object but the computed field isn't even there. I need time to look into that problem. Perhaps the computed field project needs a patch. ;)

Pepe Roni’s picture

In another issue there was also a problem with computed fields i think (can't find it yet) where the value was not stored in database.

Stop seeking: it was #664912: Taglist could not be saved and usage of option content/contentvalue., the issue you just have closed ;)

Roi Danton’s picture

Status: Needs work » Needs review

Thanks for linking, couldn't remember. I tested it and could reproduce the problem with computed fields [cf] not stored in db [nsid]. However in #21 my statement was wrong. The node object of the current loaded node when using the joker includes the cfnsid value. I don't know yet why this isn't part of the object when just using node_load. Maybe there is an additional CCK function that needs to be called.

But this problem isn't related to joker and likely deserves an own issue. If no other problems are detected I'll commit the changes this week.

Roi Danton’s picture

My test above was erroneous. The values of computed fields without storage in db do work for me in all cases (preview, view node, views, views only with fields). I've tried the tags embedded with joker and id, embedded in same node and in other nodes. Can you verify that computed field no db values do not work?

EDIT: Ah, you mean the computed field values don't get updated when previewing? This is related exclusively to computed field indeed and should be fixed there.

Pepe Roni’s picture

I do not agree with you. It may be no problem to solve within linodef, but it is a problem that arises in linodef. And it is a problem with joker character (as it does not arise without joker).

The reason:

When a node is saved, the computed value before save is shown in preview, if the value is new, an error is displayed instead. So, if you do not use the joker character, you always refer to saved nodes and all values are shown correctly in preview mode.

My suggestion:

Perhaps you should somehow do something like "sanitize" instead of "load"? I found that word in computed_field.module in function computed_field_field, line 178, in conjunction with the comment "compute field for node previews". But I can imagine you have found this yourself already ;)

Roi Danton’s picture

the computed value before save is shown in preview, if the value is new, an error is displayed instead.

Ah, this I could reproduce. I have a computed_field that uses the value from another field. If that other field has no value an error is returned - as it should be.

And it is a problem with joker character (as it does not arise without joker)

No, the error message appears when using the normal id (and the computed field has no value), too.

But did I understand the problem you are referring to correctly? Btw, I'm online at Drupal irc (RoiDanton). There such issues can be solved faster. :)

@Hook_field: Unfortunately this is just for creating new fields. Something like hook_nodeapi fields don't have (hook_nodeapi is also dropped in D7 for good reason ;) ).

Pepe Roni’s picture

Can't use IRC currently (I'm sitting in a train with bad connection).

Of course, if there is no value an error occurs.

Scenario:

add a computed field to a node type (simple: reproducing node title), not stored in db.

add a node of this type. reference this field in the body text of this node. preview: field has no content. Save the node.

edit node. preview. field is embedded correctly (shows title text). change title, preview. Field is embedded with its old title value :(

With computed field there exists a special action "sanitize" designed for node previews as described above.

Roi Danton’s picture

Status: Needs review » Needs work

The problem is hook_field is called after hook_nodeapi (load, validates) that creates the node object:
1. node:load
2. node:validate -> object is retrieved
3. field -> computed field is updated
4. filter -> computed field is embedded with object from step 2
5. node:view

So the node object doesn't include the updated computed value done in computed_field_field/_computed_field_compute_value. Calling _computed_field_compute_value in the filter as mentioned in IRC might be a solution but I'm looking if there is a better, more simpler way (e.g. retrieving the object in hook_field).

Btw, 'sanitize' is a common operation for all fields.

Roi Danton’s picture

Status: Needs work » Needs review
FileSize
15.06 KB

There was no other solution but to include hook_field of computed field into linodef. I had a little trouble to fix the problem when creating new nodes since the computed field without stored db values is not part of that node object when the filter is invoked. However I could solve that by including a new check with content_fields().
Added admin option to set another joker character. Limited to one character for aesthetic reasons (though technically the number of characters for the joker is not limited).

Please test if everything works now.

The last lines of the patch are minor documentation fixes, some are not directly related to this issue.

Pepe Roni’s picture

YESSSS!

This works with changed values in computed fields in preview mode!

Roi Danton’s picture

Status: Needs review » Fixed

Thanks for testing! Committed.

Roi Danton’s picture

Version: 6.x-1.0-rc5 » 6.x-1.x-dev
Status: Fixed » Needs work

When working with views (e.g. editing a view and try to preview it) I get this warning message: "warning: Cannot modify header information - headers already sent by (output started at /www/htdocs/w007f3dd/drupal/sites/all/modules/contrib/linodef/linodef.module:188)". Can someone confirm this (using dev release)?

Roi Danton’s picture

Status: Needs work » Fixed

Nevermind, this was due to a Debug print output in my testscript. I've updated the view hook slightly to make it more safe against potentially errors.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.