It does not work when used in a multilingual site using entity translations - the references are out of sync, and does not sync correctly between languages.

Comments

supermoos’s picture

If someone could give me a hint at where in the code to implement this I would give it a go myself, is it in cer.crud.inc?

phenaproxima’s picture

Assigned: Unassigned » phenaproxima

I'm actually in the middle of patching (read: massively refactoring) cer.crud.inc to fix a number of issues at once - bad practice, I know, but it's tricky to fix isolated issues in the CRUD functionality with the way the code is structured right now - and this is one of them.

supermoos’s picture

That sounds great, let me know when you have something ready for testing and I will give you feedback! Any time frame on this?

phenaproxima’s picture

Should be ready within a week! :)

phenaproxima’s picture

Having written some code around this issue, I've realized this is gonna take a little more thought.

For example, if you're relating field_a to field_b, what if field_a is translatable but field_b is not? Or what if both fields are translatable in English and French, but entity_a has a reference to entity_b only in its French values? Should reciprocal references only be made within the same language? Is this something we'd want to expose to the site builder? If so, how?

supermoos, can you give me a little more information about your use case? I haven't built a site in any language except English for years (the last time I dealt with multilanguage issues, I was still using Drupal 5!), so translation is not something I give a lot of thought to on a regular basis. Any thoughts (or patches) are appreciated!

supermoos’s picture

I guess that filed_a and field_b should have as a requirement that they are both available in the same translations, for example english, german and spanish. And then the spanish field_a should update spanish field_b, but do nothing to the english and german translations. But if field_a and field_b is not available in the same languages, there cut be a message to the user about this, or just document it somewhere - i don't think there are a lot of usecases for syncing fields across different translations (because then the field should not have been made translateable in the first place). So only same language reciprocal references would be my suggestion.

My use case is simple:
I have a two nodes:
a Tour-node type
and a Media-node type

Tours can reference many Media-nodes
and Media-nodes can have an "Included in these tours" field which can reference many tours.
Both node types are available in any number of languages, but always the same amount, so it could be English, German, Spanish or English, German, Russian but never English, German, Spanish in Tour-nodes and then English, German, Russian on Media-nodes.

The only problem with syncing I can see is that if a translation hasn't been created for the referenced node:
Example:
English tour references russian-only Media (ie. the Media hasn't yet had a russian translation added to it) - but this could be solved by simply filtering the widget-supplied available node references by what translations they are available in.

phenaproxima’s picture

I agree that cross-language references are an edge case, but I tend to be quite paranoid about what clients may eventually want :)

In that vein, I was thinking that maybe CER should only support same-language reciprocal references out of the box, but include an easy way to extend its behavior in case something more exotic is needed.

I've been toying with the idea of wrapping CER's core functionality in a handler object that can test/create/delete reciprocal references. Then, if a developer needed to fulfill some sort of bizarre request relating to corresponding references (across different languages, for example!) they could simply extend the base handler. Not only would this be more consistent with the way that Entity Reference itself works, it would ease the port to Drupal 8, which is object-oriented pretty much from top to bottom. Any thoughts on this approach would be most welcome.

For the time being, though, just to get a patch up in here, I'm changing cer.crud.inc so that it just dumbly loops through every language on the fields that it processes. (The existing code base is hard-coded to work with the LANGUAGE_NONE values only.)

supermoos’s picture

I haven't had a chance to work with Drupal 8 yet, so I wouldn't know about that - but it sounds like a good idea.

And the dumb patch loop should be fine for a start, if others need to improve then at least they have this thread as a reference point.

phenaproxima’s picture

Patched in http://drupal.org/node/1971250 (wherein I submitted a patch that encapsulates CER's CRUD functionality in a handler object. I'm overzealous, I confess).

The handler I wrote does what I said in #7 - it deals with multiple languages, if not very intelligently. Give it a shot, and let me know if this helps with your issue!

phenaproxima’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Status: Active » Needs review

The patch I mentioned in #9 has been committed into the 2.x branch, so this should be fixed in that branch now. Please use git to get a copy of it for review.

supermoos’s picture

It does not seem to sync entity references correctly, I have a node (id 1714) which in it's danish version has a reference to 1713 - but the 1713 (danish version) doesn't get updated about the fact that 1714 references it.

phenaproxima’s picture

Status: Needs review » Needs work

EDIT: Never mind. Will fix!

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new12.98 KB

Here's a new patch for this. It significantly changes the CerHandler class and "bakes in" multi-language support, implementing the following logic, in terms of the use case from #6:

You have two node types, Media and Tour. Media has field_related_tour, which is an unlimited entity reference to Tour nodes, and Tour has field_related_media, which is an unlimited entity reference to Media nodes. Both fields are translateable, and you have English, Spanish and German enabled.

Let's say you create a new Media node (node 100), set its native language to French, and give it a reference to Tour node 55, which has English as its native language (presumably, in a real use case, you'd reference a French node and not an English one, but for illustrative purposes let's say you're a sloppy admin and don't know any better).

You will end up with this:

$media_node->field_related_tour['fr'][0]['target_id'] == 55;
$tour_node->field_related_media['fr'][0]['target_id'] == 100;

This will be the case even though $tour_node->language == 'en'. This is how D7's native field translation works; when viewing $tour_node in English, you should not see the reference to $media_node.

In other words, CER will try to put the reference on the same field language values as the referenced entity's native language. If the referenced entity is 'und' or doesn't support translation (or the other field doesn't support the referenced entity's language), the reference will go into 'und' by default.

Does this make sense? Please let me know if it works for you.

supermoos’s picture

Sorry for the delayed reply, haven't had time too test it before now.

It somewhat works, but when I delete a Tour reference on a danish Media translation it doesn't update the corresponding Media reference on the danish Tour translation. Maybe we could connect directly via skype or similar, then I could give you access to my setup?

phenaproxima’s picture

Status: Needs review » Needs work

Let me try and reproduce it on my end, and if I need access to your setup I will ping you via your contact form. Thanks for testing it out, supermoos; your help is much appreciated!

anou’s picture

Hello,
Wanted to test the patch but it doesn't apply to latest dev...

error: patch failed: handler.inc:140
error: handler.inc: patch does not apply

Correct me if I'm wrong ?

phenaproxima’s picture

I'm in the process of writing some tests around this functionality, then addressing what supermoos said in #14 - so the patch isn't going to apply against dev at the moment. A re-roll is coming!

socialnicheguru’s picture

no longer applies cleanly.

Hunk #1 succeeded at 50 (offset -20 lines).
Hunk #2 succeeded at 60 (offset -20 lines).
Hunk #3 succeeded at 79 (offset -20 lines).
Hunk #4 succeeded at 120 with fuzz 1 (offset -20 lines).
Hunk #5 succeeded at 128 with fuzz 1 (offset -20 lines).
Hunk #6 succeeded at 138 (offset -20 lines).
Hunk #7 succeeded at 207 (offset -19 lines).
Hunk #8 succeeded at 247 (offset -19 lines).
Hunk #9 succeeded at 255 (offset -19 lines).
Hunk #10 succeeded at 279 (offset -11 lines).
Hunk #11 FAILED at 323.
Hunk #12 FAILED at 347.
Hunk #13 succeeded at 367 (offset -8 lines).
Hunk #14 succeeded at 384 (offset -8 lines).
Hunk #15 succeeded at 394 (offset -8 lines).
Hunk #16 succeeded at 424 (offset -8 lines).
2 out of 16 hunks FAILED -- saving rejects to file handler.inc.rej

phenaproxima’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new11 KB

Re-rolled the patch against the latest 2.x-dev.

rcodina’s picture

Is this fixed on 3.x-dev? I have 7.x-3.0-alpha7+17-dev and I think it stills fails. Patch should be rerolled.

rcodina’s picture

Status: Needs review » Needs work

Patch on #19 applies to latest 2.x-dev but it's broken:

PHP Fatal error: Declaration of CerHandler::reference() must be compatible with CerHandlerInterface::reference($entity, $language = NULL) in cer/handler.inc on line 157

Could someone reroll patch for latest 2.x-dev?

james.williams’s picture

StatusFileSize
new11.01 KB

Here's a fixed version of the patch, which just fixes that interface incompatibility. Note that this is still for 7.x-2.x though, not 7.x-3.x

james.williams’s picture

Status: Needs work » Needs review
StatusFileSize
new15.07 KB

That previous patch from #22, which was just a very basic fix for the fatal error that #19 caused, still has huge functional problems. For example, removing a reference in one language value in a field, will remove the reference across all language values on the referenced entity. This new patch resolves that and similar issues by doing all operations per-language where possible, whilst also just loading & saving any entity once that is referenced across multiple languages.

james.williams’s picture

StatusFileSize
new15.08 KB

Gosh, that patch in #23 completely broke on creating new entities, sorry! /me tries again :-)

james.williams’s picture

Status: Needs review » Needs work

Okay, found another issue: if a translation is deleted, the reference on the referencing entity is not removed. That would currently only happen if the whole referenced entity was deleted, not just a translation.

The patch is otherwise working well for our client.