Hi. This is my first try to submit a bug to Drupal, so please forgive me if i'm not doing in the right way.

I've just added a new field to my content type. this is a commerce_price field (so, maybe this can be a problem of that module too) and also i choose "Read-only" as widget.

Trying to add a node of this type i get a notice in my screen reading

Notice: String offset cast occurred en _field_invoke_multiple() (line 322 of [...]/modules/field/field.attach.inc).

Line reads like

$language = !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];

I used dpm for debugging and found that indeed ($options['language'] ) is not an array but an string ('und') in this case.

I modified that line adding to check if that $options['language'] is an array and that solved my problem. I'll submit the patch asap for your review.

As said, sorry if i'm not doing right.

Comments

crevillo’s picture

Sorry. Let me add that the notice only appearing with php 5.4.

crevillo’s picture

StatusFileSize
new1002 bytes

Attached patch for your review

crevillo’s picture

Status: Active » Needs review
Anonymous’s picture

Version: 7.x-dev » 8.x-dev
Issue tags: +Needs backport to D7

Does this issue exist for D8. PHP 5.4 isn't recommended at this time.

crevillo’s picture

Haven't tested D8 yet sorry. Feel free to close the issue if php5.4 is not the right choice for D7 then

krabbe’s picture

Patch #2 worked for me in 7.16

parrapa’s picture

Patch worked successfully in 7.17. Thank you!

Anonymous’s picture

Issue tags: -Needs backport to D7

#2: string-offset-cast-1824820-2.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Needs backport to D7

The last submitted patch, string-offset-cast-1824820-2.patch, failed testing.

pere orga’s picture

The patch should be updated for Drupal 8

(It's the workflow to fix bugs that happen in both 7 and 8 versions)

crevillo’s picture

excuse me, but as said, i'm a bit newbie with this... do you mean i should provide a patch for d8 too?
Thanks.

rbayliss’s picture

Welcome crevillo. Yes, it's standard policy to fix things in the development version (Drupal 8) first, then backport to the current version (Drupal 7). If you can provide a patch for Drupal 8 that would be great. Thanks!

pere orga’s picture

Yes, and this is why the current patch cannot be applied: it's a D7 patch and the issue is now marked for 8.x-dev.

crevillo’s picture

ok. i see. sorry about the missunderstanding. i'll try to provide a d8 patch.

crevillo’s picture

StatusFileSize
new1020 bytes

here's d8 patch for review

crevillo’s picture

Status: Needs work » Needs review
pere orga’s picture

Status: Needs review » Needs work

I think the patch is wrong.

If $options is not an array, then $langcode is set to $options['langcode'], which does not exist.

crevillo’s picture

But, as far i can see, $options should be always an array.
at the begining of the function we have

// Merge default options.
  $default_options = array(
    'default' => FALSE,
    'deleted' => FALSE,
    'langcode' => NULL,
  );
  $options += $default_options;

$options is not re-assigned anymore in the function. so, it seems to me that $options will be always an array...

Please correct me if i'm wrong.

Anyway, it seems patch failed, so i'm digging on it.

pere orga’s picture

Status: Needs review » Needs work

Ok, I assumed that $options may not be an array because what your patch does is check if it's an array.
Maybe you wanted to put:
is_array($options['langcode'])
instead of:
is_array($options)
?

crevillo’s picture

Status: Needs work » Needs review
StatusFileSize
new1.01 KB

ok to that. you're right.
attaching new patch

crevillo’s picture

Status: Needs work » Needs review

I run test locally and fails throwing some warnings at line Drupal\translation_entity\EntityTranslationController->entityFormAlter().

Warning thrown reads

Illegal string offset '#multilingual'

it's this piece of code

if ($language_widget) {
  $form_langcode['#multilingual'] = TRUE;
}

In my opinion, warning is thrown because in some cases $form_langcode is an string and not array.
Any recomendations on how to deal with this?
Thanks

pere orga’s picture

Seems like test's fault ?

if ($language_widget && is_array($form_langcode)) {
...
crevillo’s picture

StatusFileSize
new1.7 KB

yep. seems so. attached new patch for review
thanks for your help.

pere orga’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.

crevillo’s picture

Cool. Let me know if you need something more on my side.
Thanks for your help.

yched’s picture

Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

Hard to say for sure, but this very much looks like some contrib module doing something wrong, which then triggers errors down the line in a core function. The core policy is to not add opportunistic validity checks to swallow errors coming from contrib.

In order to get anything done here, precise (and if possible simple) steps to reproduce the bug should be provided.
Does this happen on a Drupal Commerce site ? Is it based on Commerce Kickstart ?
If so, I'd suggest moving the issue over there so that their team can try to refine this.

Anonymous’s picture

Status: Postponed (maintainer needs more info) » Needs work

Why is the EntityTranslationController part of the patch needed?

I understand the field.attach.inc piece: @yched, the fact that the code is already giving "$options['langcode']" as a value lends to the fact that this is a core issue and needs resolved by "is_array($options['langcode'])".

swentel’s picture

Status: Needs work » Postponed (maintainer needs more info)

We still don't know where this is coming from, so keeping the status.

yched’s picture

So, looking at this a little closer :
_field_invoke_multiple() accepts $options['langcode'] ($options['language'] in D7) either as a langcode or as a 2-level array of langcodes keyed by entity id and field name.
Contrary to what I wrote in #26, It might well be true that the current check is a bit sloppy on that side - using isset($options['langcode'][$id]) to determine whether $options['langcode'] is one form or the other.

Still, we'd really need some detailed steps to reproduce to determine what's happening exactly, and add a proper test in our test suite so that this doesn't happen again.

crevillo’s picture

Hi all
@yched: i understand the policy of nor modifying drupal core if not entirely necessary.
As said in the intro, issue appeared just after adding a commerce_price field to a existing content type. So indeed, yes. Drupal Commerce is being used in my site.

Anyway, and not being a Drupal expert at all, i think @earnie is right too.
Let me remember that no error appeared. not even a warning. it was just a notice and it was only when i switched from php 5.3 to php 5.4.

Other than that, the question it's if there is some documentation or some place where drupal tell developers that $options['language'] MUST be always an array.

And, as far i can see in the inline doc for the method this is not the case.
http://drupalcode.org/project/drupal.git/blob/HEAD:/core/modules/field/f...

@param $options
...
- langcode: A language code <strong>or</strong> an array of arrays of language codes keyed

So, or is the key here. Drupal Code, at this point, is "allowing" other to provide that $options['language'] as a lang code (string) or as an array.

As $options['language'] CAN BE sometimes a string, it's normal we can get a notice when why try $options['language'][$id] we ge the notice.

So, i still think patch should be in the drupal core. If not, you should warn all developers and update the documentation.

Thank you!.

yched’s picture

Crosspost :-) See my #29.

crevillo’s picture

yep, you were quicking.
trying to reproducing so you can test it in your side.
Thanks

Anonymous’s picture

Ok, however, it doesn't matter where it is coming from. As mentioned in #1 this is an issue for PHP 5.4 which seems to be a bug in that version of PHP. The empty() should be enough for this and we tend not to work around buggy PHP either.

However 5.4.0 has this change for empty:

5.4.0 Checking non-numeric offsets of strings returns TRUE.

Example #2 empty() on String Offsets
PHP 5.4 changes how empty() behaves when passed string offsets.
$expected_array_got_string = 'somestring';
var_dump(empty($expected_array_got_string['some_key']));
var_dump(empty($expected_array_got_string[0]));
var_dump(empty($expected_array_got_string['0']));
var_dump(empty($expected_array_got_string[0.5]));
var_dump(empty($expected_array_got_string['0.5']));
var_dump(empty($expected_array_got_string['0 Mostel']));

Output of the above example in PHP 5.3:
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
Output of the above example in PHP 5.4:
bool(true)
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)



Does this change cause a need for change in this scenario?

Anonymous’s picture

I created #1850770: PHP 5.4.0 change for empty() may require changes in Drupal. for consideration of all of Drupal code based on my discovery of the change for empty().

crevillo’s picture

here is a "similar" case to reproduce the notice. please test this in a php 5.4 install

error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
$id = null;
$options = array( 'language' => 'und' );
$language = !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
var_dump( $language );

$id = true;
$options = array( 'language' => 'und' );
$language = !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
var_dump($language);

The result i get is

Notice: String offset cast occurred in /var/www/string-offset.php on line 5 string(1) "u"
Notice: String offset cast occurred in /var/www/string-offset.php on line 10 string(1) "n"

Tested in a 5.3 install and no notices at all.

Admiting is quite strange and probably coming from a contrib module, now i'm searching where that $id it's null or bool.

bluesky_still’s picture

Status: Postponed (maintainer needs more info) » Needs review
Issue tags: -Needs backport to D7
jmaties’s picture

Issue tags: +Needs backport to D7

#2: string-offset-cast-1824820-2.patch queued for re-testing.

7wonders’s picture

cross post to http://drupal.org/node/1900456 where I just posted this bug with some perhaps helpful debug info.

Tinnka’s picture

Version: 7.x-dev » 7.7
Issue tags: -Needs backport to D7

Patch worked successfully in 7.17 (Commerce Kickstart). Thank you!

pere orga’s picture

Version: 7.7 » 7.x-dev
Issue tags: +Needs backport to D7

Ok @Tinnka but please don't change this as we still need that tag, and the version the patches are applied to is 'dev'

zkday’s picture

This patch at http://drupal.org/node/1824820#comment-6746564 also working with 7.x-dev.
Thanks. :)

crevillo’s picture

you're welcome. so, can i say this is my first contrib to drupal core? :)

13rac1’s picture

I'm using EntityWrapper to programmatically create a node. I confirm this notice occurs in PHP 5.4, but not in PHP 5.3.

yoroy’s picture

StatusFileSize
new47.9 KB

I run into this notice when using the Automatic Nodetitles module.

When I leave the Pattern for the title empty, no notice.
When I insert a token for a field of the content type to be used as the title, I get the notice.

On D7, PHP 5.4.4

*Edit* and: no issues when using PHP 5.3.14

aspilicious’s picture

Anything I can do to move this forward? Client project with auto nodetitle is affected.

yched’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs backport to D7

Right, sorry for the delay :-(
Thanks a lot @earline for the explanations in #33, makes total sense.
Patch #2 is the correct fix, then.

Doesn't need to be fixed in D8, _field_invoke_multiple() is gone. and D8's EntityNG + Entity translation API makes the corresponding code completely different and not affected by this.

David_Rothstein’s picture

Version: 7.x-dev » 8.x-dev
Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs backport to D7

In Drupal 8 I see the following code in field_invoke_method_multiple():

  $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];

Are we sure Drupal 8 isn't affected?

And could this use a test?

matsbla’s picture

Doesn't patch #2 hack the core? Should I do it or wait for this to be ported to a new version of D7 core?
Any progress on this issue? If this is fixed, why not simply commit it?

siliconmind’s picture

siliconmind’s picture

Priority: Normal » Major

It seems that the problem is caused by line 303 that calls entity_extract_ids for a node that has not been saved yet. Such node has it's nid set to NULL. Hence the $id in line 303 is also set to NULL.

// Determine the list of instances to iterate on.
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

Now take a look at this:

$options['language'] = 'und';

// For PHP < 5.4 
print empty($options['language'][NULL]); // silently prints 'u'.

// For PHP >= 5.4
print empty($options['language'][NULL]); // raises a notice AND prints 'u'.

This is new for PHP 5.4

The problem is not the fact that $options['language'] is not always an array, but the way the check is performed. Current code clearly allows $options['language'] to be a string, so the patch from #2 is not a hack and should be applied.

dlu’s picture

Do we need to add tags for STR and tests to this? Are they blocking this issue?

pdcarto’s picture

I'm totally not an expert on automated patch testing, but it looks to me like field.test has unit tests that should catch any problems with this patch. And the patch passed testing. Am I missing something?

dema501’s picture

According #50

I've changed

$langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];
to
$langcode = $id != NULL &&  !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];

And alert is gone.

NaX’s picture

I have been able to trace this problem from a contrib module to core and it looks like SiliconMind in #50 is correct about entity_extract_ids().

I am currently setting up a Commerce site running PHP5.4 and that the inline_entity_form module is previewing an entity before it is saved with an ID so the ID is returned as NULL when creating new product variants.

I was able to work around the problem by overriding the theme function theme_inline_entity_form_entity_table($variables) and added the following.

  // Build an array of entity rows for the table.
  $rows = array();
  foreach (element_children($form) as $key) {    
    $entity = $form[$key]['#entity'];
    
+    // Workaround for core bug #1824820
+    // entity_extract_ids returns null when entity does not exist and _field_invoke_multiple tries to 
+    // check options for null key index for language that throws a notice.
+    $info = entity_get_info($entity_type);    
+    $entity->{$info['entity keys']['id']} = 0;
+    $entity->language = array(0 => $entity->language);
    
    list($entity_id) = entity_extract_ids($entity_type, $entity);        
    // Many field formatters (such as the ones for files and images) need
    // certain data that might be missing on unsaved entities because the field
    // load hooks haven't run yet. Because of that, those hooks are invoked
    // explicitly. This is the same trick used by node_preview().
    if ($form[$key]['#needs_save']) {
      _field_invoke_multiple('load', $entity_type, array($entity_id => $entity));
    }

This make the language options index an array rather than a string and by making the ID property on the entity object a ZERO it is easily to reference in the options array.

I hope that makes sense and is helpful.

muriqui’s picture

Title: String offset cast occurred en _field_invoke_multiple() (line 322 of [..]/modules/field/field.attach.inc » String offset cast notice in field_invoke_method_multiple()
Priority: Major » Normal
Issue summary: View changes
StatusFileSize
new887 bytes

I think #50 is right on. Like yoroy's #44, I ran into this with the Automatic Node Title module. If I set the node title to use a field token and then create a new node, the result is that this method gets called with an unsaved entity. Thus, the $id value is NULL, and the !empty($options['langcode'][$id]) check produces the "string offset cast" notice. Adding a !empty($id) condition to that statement fixes the problem. See attached patch.

Also: updating the issue title to reflect the D8 function name and downgrading priority to normal (since this is only a PHP notice message, not a warning or error).

muriqui’s picture

And for those of us encountering this issue on D7, here's the backported patch.

drupov’s picture

Patch from #56 worked for my d7 installation. Thanks!

drupov’s picture

The problem persists with drupal's update to 7.25. Patch from #56 solves that too.

schifazl’s picture

I confirm that patch from #56 works in Drupal 7.25

NaX’s picture

Status: Needs review » Reviewed & tested by the community

Thanks to muriqui we now have a Drupal 7 and 8 patch that is confirmed to work.

swentel’s picture

Status: Reviewed & tested by the community » Needs work

Field language system has been reworked completely in D8 - this patch probably became redundant for D8.

NaX’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review
shahidbscs’s picture

#56 work for me on D7, thank you

mariacha1’s picture

Status: Needs review » Reviewed & tested by the community

Looks good in D7.26. I say it's ready to be committed.

phizes’s picture

StatusFileSize
new985 bytes

Re-upload of #56 to go through testing for D7.

miromarchi’s picture

#65 worked for me in my D7 panopoly-based distro.

I had the notice using rules with a content type which title is managed by auto_nodetitle.

Thanks

cyberschorsch’s picture

#65 takes care of this issue and works

heddn’s picture

yched’s picture

Yes, that API has been completely revamped in D8, iterating on fields and handling of field translation has nothing in common with D7 anymore.

kolafson’s picture

#65 worked for me as well

drupov’s picture

#65 works for me also.

nikolay shapovalov’s picture

#65 works for me also.

pimok3000’s picture

# 65 works well on D 7.26

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 65: string-offset-cast-1824820-65-D7.patch, failed testing.

maximpodorov’s picture

Status: Needs work » Needs review
maximpodorov’s picture

maximpodorov’s picture

Status: Needs review » Reviewed & tested by the community

The patch was tested without errors! It fixes the problem - no notices.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 65: string-offset-cast-1824820-65-D7.patch, failed testing.

maximpodorov’s picture

Status: Needs work » Needs review
maximpodorov’s picture

Status: Needs review » Reviewed & tested by the community

All tests are passed again.

cameron prince’s picture

#65 works well with current release version of D7.

adevms’s picture

#65 is working for D7.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 65: string-offset-cast-1824820-65-D7.patch, failed testing.

maximpodorov’s picture

Status: Needs work » Needs review
maximpodorov’s picture

Status: Needs review » Reviewed & tested by the community

All tests are passed again.

David_Rothstein’s picture

Status: Reviewed & tested by the community » Needs review

The original RTBC patch was #2 (which looks good to me), but this was changed in recent patches without much explanation. If the bug is that the code treats $options['language'] as an array even when it's not, why would we only fix this when $id is NULL (rather than actually checking that it's an array like #2 did)?

I guess we can live without tests if this is an obscure bug (and was presumably fixed as a side effect in Drupal 8 without any tests)...

heddn’s picture

Status: Needs review » Reviewed & tested by the community

Due to the way that empty() functions in PHP 5.4, simply checking for is_array isn't sufficient. Checking for empty on $id is important. It could be an array but the warning still displays. #1824820-35: String offset cast notice in field_invoke_method_multiple() does a good job explaining.

pkiff’s picture

For those wondering if the patch in #65 works with the field.attach.inc file included with Drupal 7.28, it does. There were no changes in field.attach.inc between 7.27 and 7.28, so you can use the same patch on 7.28.

drupov’s picture

Yes, I can confirm that the patch works also on 7.28

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 65: string-offset-cast-1824820-65-D7.patch, failed testing.

David_Rothstein’s picture

Status: Needs work » Needs review

OK, I read #35 again but I'm still not getting it. Can someone explain what I'm missing?

  1. The bug occurs when code tries to access $options['language'][$id] but $options['language'] isn't an array.
  2. #35 contains two examples of the problem, one where $id is NULL and one where $id is TRUE.
  3. The approach in #2 checks is_array($options['language']) before trying to access $options['language'][$id] and therefore should catch all cases, including the two above.
  4. The approach in #65 checks !empty($id) before trying to access $options['language'][$id] and therefore only catches one of those two cases (when $id is NULL). When $id evaluates to TRUE there will still be PHP notices.

So why isn't #2 the correct approach?

crevillo’s picture

Hi there.

David, what you say in #91 is exactly what i thought in doing #2

Further more, please remember that documentation for that function seems to allow other modules to provide that langcode without being an array.

http://cgit.drupalcode.org/drupal/tree/modules/field/field.attach.inc?h=...

it says

- 'language': A language code or an array of language codes keyed by field
* name. It will be used to narrow down to a single value the available
* languages to act on.

I cannot see what is the problem with #2 either...

siliconmind’s picture

Status: Needs review » Reviewed & tested by the community

So, can we finally make this RTBC?

siliconmind’s picture

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 65: string-offset-cast-1824820-65-D7.patch, failed testing.

David_Rothstein’s picture

David_Rothstein’s picture

Status: Needs work » Needs review

Which patch are you saying should be RTBC?

yched’s picture

Patch #2 should be RTBC.

a.milkovsky’s picture

StatusFileSize
new983 bytes

Re-rolled patch #65 without extra brackets

pkiff’s picture

It will be confusing for new people arriving at this thread to figure out which patch is recommended by the community now. The patch in #2? Or #65, or now #99? I understood that the consensus was building for recommending the patch in #2 because it covers the more potential instances of the problem, as explained by David_Rothstein in post #91 above. Is that right?

skwashd’s picture

@pkiff, the consensus of those in the know is that #2 be applied. It still applies cleanly and the tests pass.

gabrielmachadosantos’s picture

Status: Needs review » Reviewed & tested by the community

Patch #2 should be RTBC. Applied the patch and tested.

manuelBS’s picture

For me patch 2 as well as 99 work.

danreb’s picture

Patch #2 works for me too - PHP 5.4 issue
Thanks

daniel kulbe’s picture

Nice - patch#2 worked for me too. Thanks a lot!

pjcdawkins’s picture

I'm also using the patch in #2

heddn’s picture

siliconmind’s picture

Can we finally commit this? Please, the patch is ready for over a year now.

mr.alinaki’s picture

Patch from #2 is worked for me. Got this error when work with field collections and now it's gone!

coatezy’s picture

I would also like to see this patch committed.

miromarchi’s picture

I was used to use patch in #65, but I switched to patch in #2 too, and it's working perfectly.

dcam’s picture

Issue tags: -RTBC

Removing unnecessary tag.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 99: empty-languaage-id-1824820-99-D7.patch, failed testing.

schifazl’s picture

#87 says that what was done in patch #2 isn't sufficient, so it should be used patch #65, others say that patch #2 should be used... So which patch should I apply, waiting for the official commit?

Thanks.

pkiff’s picture

Patch #2 is currently the recommended patch. The comments in #87 are based on a misunderstanding of how #2 addresses the root problem of the bug, and this is explained in post #91 by David_Rothstein. The person who posted #87 (heddn), subsequently posted an endorsement of the patch in #2 (see #108).

And in #100 above, I asked the same question as you, and the answer then also recommended the patch in #2.

schifazl’s picture

Thanks! There was so much confusion that even reading the thread two times I was still puzzled.

I'm hopefully waiting for a quick commit!

Status: Needs work » Needs review
dcam’s picture

Status: Needs review » Reviewed & tested by the community
dcam’s picture

Please note I have no opinion on which patch is correct. I was simply resetting in bulk the multitude of RTBC issues which failed last week due to a problem with Testbot.

webadpro’s picture

When will this be commited?

Patch #2 seems to work.

giupenni’s picture

Patch #2 work fine.

Feral’s picture

Works nicely with D7, thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 99: empty-languaage-id-1824820-99-D7.patch, failed testing.

Status: Needs work » Needs review

schifazl’s picture

Status: Needs review » Reviewed & tested by the community

Patch #2 passed (again) the test, it's the recommended patch and works fine for everyone, I think that it should be RTBC (again).

jwilson3’s picture

Agreed. RTBC++. Patch in #2 solved my problem (getting this error on node/add/typename).

Håvard’s picture

Patch in #2 works like a charm and fixed an issue I had width validation of a date field and date popup-calendar.

mglaman’s picture

This is required when using Behat testing and the Drupal Extension to provide custom field values.

David_Rothstein’s picture

Status: Reviewed & tested by the community » Fixed

Committed #2 to 7.x - thanks!

And thanks for all the testing, etc., to verify that the fix is working correctly.

  • David_Rothstein committed 2a4f67c on 7.x
    Issue #1824820 by crevillo, muriqui, a.milkovsky, Phizes: Fixed String...

Status: Fixed » Needs work

The last submitted patch, 99: empty-languaage-id-1824820-99-D7.patch, failed testing.

David_Rothstein’s picture

Status: Needs work » Fixed

Hm...

Status: Fixed » Closed (fixed)

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