This is a relatively easy problem to grasp, even though it's a bit strange to explain.

In element_children() we have code like the following:

  foreach ($elements as $key => $value) {
    if ($key[0] !== '#') {
      ...
    }
  }

Now this can cause a problem if $key is an empty string, which is common when you want to have something like "Select..." as the first option, which will trigger the "Required" error if the user doesn't choose an option. In other words, a form like this will cause an error:

$form['radios'] = array(
  '#type' => 'radios',
  '#options' => array(
    '' => t('Select...'),
    'one' => t('Option one'),
  ),
);

This throws the following PHP warning:

Error message
Notice: Uninitialized string offset: 0 in element_children() (line 5284 of /Users/nate/Sites/drupal7/includes/common.inc).

The simple fix here is we just check that $key has at least one character before trying to check the first character.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Status: Needs review » Needs work

The last submitted patch, empty_radio_option.patch, failed testing.

moonray’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
481 bytes

Rerolled the patch. Tested it to work.

Jacine’s picture

Status: Reviewed & tested by the community » Needs review

Subscribe. Need this for Skinr :(

moonray’s picture

FileSize
659 bytes

Re-re-rolling. Hoping the test bot will like it.

moonray’s picture

FileSize
659 bytes

OK, lets try that again with a patch that won't break drupal (oops).

sociotech’s picture

Third time's a charm! No more errors. Thumbs up and RTBC.

Jacine’s picture

Status: Needs review » Reviewed & tested by the community

Same here. Marking RTBC.

quicksketch’s picture

Thanks moonray! I should've rerolled this after it failed to apply. :-(

Moonray's #5 is identical to my original patch, just it has the file path correct for common.inc. As such I know that it works and prevents the PHP warning correctly. RTBC + 1.

webchick’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Sorry, but we need tests for tweaky esoteric bugs like this.

quicksketch’s picture

Status: Needs work » Needs review

Really? This is a PHP programming mistake. Clearly all strings aren't always longer than 1 character. It's equivalent to an isset($variable) versus an implied $variable.

moonray’s picture

I second what quicksketch said in #10. There's no way to really write a test for a programming mistake like this.

Jacine’s picture

Status: Needs review » Reviewed & tested by the community

Ok, let's try again.

Melissamcewen’s picture

The patch is working for me. Thanks!

sociotech’s picture

Patch applied cleanly, resolved uninitialized string offset errors when using Skinr. RTBC +1

chx’s picture

Status: Reviewed & tested by the community » Needs work

ABSOLUTELY NOT! if ($key === '' || $key[0] !== '#') { is the correct fix. Empty string is a perfect child it's not a property.

quicksketch’s picture

Status: Needs work » Reviewed & tested by the community

Doh. Chx is totally right (and webchick too), since the fact is that this patch is the opposite of the correct thing.

quicksketch’s picture

Status: Reviewed & tested by the community » Needs work
Melissamcewen’s picture

Status: Needs work » Needs review
FileSize
655 bytes

Here is a patch based on chx's wisdom

casey’s picture

Status: Needs review » Reviewed & tested by the community

per #15

webchick’s picture

Status: Reviewed & tested by the community » Needs work

Hit this with Flag: #874292: Notice: Uninitialized string offset: 0 in element_children() Which I assume is why Nate wanted this fixed. ;)

Anyone up for writing that test? The code is practically written for you in the OP. We just need a select/radios element with a "" option in one of the forms in the form test. Just viewing the form's enough to trigger this issue.

ekes’s picture

Assigned: Unassigned » ekes

Looking at test; and it only makes sense to test radio fapi display / validation generally - as is done for checkbox. Related issues spotted so far:-

And for present 'desired' behaviour. #621366: Enforce comformance to W3C recommendations on radio buttons? is not implemented.

However it's probably easiest to do this in stages; so small test to cover this first, and notes.

ekes’s picture

Assigned: ekes » Unassigned

Oh wow.. posted that the wrong issue :) Well not the one I started working on.
But it's good to have all of them collected together

ekes’s picture

Patch from #18 with added simpletests starting on #21

ekes’s picture

Status: Needs work » Needs review
floretan’s picture

@ekes has been faster than me, but I'm not sure we need so much details in the test. We already have the "Form element validation" tests that test a bunch of stuff with different element types and options. Simply adding an option with an empty key throws a warning, which is solved by this patch. Note that only elements of type "radios" throw errors, but I'm also adding an option with an empty key to the select tests for completeness.

salvis’s picture

Status: Needs review » Needs work
+++ includes/common.inc	27 Aug 2010 15:20:38 -0000
@@ -5528,7 +5528,7 @@ function element_children(&$elements, $s
+    if ($key === '' || $key[0] !== '#') {

$key can also be a numeric index.

I think the proper condition is

    if (is_int($key) || $key === '' || $key[0] !== '#') {

What about NULL? Would be weird, but is it illegal? Test for empty()? That would also cover $key===''.

salvis’s picture

Status: Needs work » Needs review

I'm sorry for having derailed this. I thought I had a case of notices tracked back to this code and integer $keys, but now I cannot reproduce it anymore.

So, please ignore my #26 above.

The fix is fine, but I can't say how much testing is needed.

webchick’s picture

Status: Needs review » Fixed

Yep, #25 looks like exactly what I had in mind.

Committed to HEAD. Thanks!

Status: Fixed » Closed (fixed)
Issue tags: -Needs tests

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