When attempting to display a second level Web Links group, i.e. picked from the breadcrumb, the following notice is thrown:

Notice: Undefined offset: 0 in weblinks_get_tree() (line 1131 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module).

The notice is thrown when checking the current term for a parent term:

  $new_tree[$tid] = $term;
  $new_tree[$tid]->children = array();
  if (isset($term->parents)) {
    if ($term->parents[0] != 0) {
      foreach ($term->parents as $parent) {
        if (isset($new_tree[$parent])) {
          $new_tree[$parent]->children[] = $tid;
        }
      }
    }
  }

Either the if statement 'if ($term->parents[0] != 0)' has to be safeguarded or the logic needs to be changed not assuming offset '0' to be first element of array $new_tree.

Comments

GStegemann’s picture

I think safeguarding the 'if' statement is the correct fix. Patch uploaded.

GStegemann’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 1: 2197719_1.undefined_offset_0_in_weblinks_get_tree.patch, failed testing.

GStegemann’s picture

Status: Needs work » Needs review
jonathan1055’s picture

a second level Web Links group

Do you mean a nested group, ie one taxonomy vocab within another? Or is it a term which has another term as parent?

GStegemann’s picture

Second case: a term which has another term as parent. But in Web Links terminology spoken: nested 'groups'.

Assuming you have the following you have selected a nested weblinks the breadcrumb may look like the following:

Web Links» Automatisierungstechnik | FactoryLink | Authorisierung

Then, when you click on the weblinks next to the left from the last one the notice is thrown.

jonathan1055’s picture

Thanks for the explanation. Interesting, I could not replicate this error. I started with the default empty weblinks group, added a term and a weblink in it. Then added another term as a subgroup, and added a link. Both items in the breadcrumb have the form /weblinks/n where n is the group vid. Neither of the links created the error. I even added a sub-sub-group and that still did not produce the error. Obviously I am doing something different to you. I think we need to know exactly how to replicate, so that we are sure we fix it in the correct way.

GStegemann’s picture

I can reproduce the error all the time. I have attached two screen shots showing the used Web Links vocabulary and when the PHP notice is thrown.

To reproduce the error the just attempt to view the "middle" group, here url /weblinks/256. Then the if statetment 'if ($term->parents[0] != 0) {' throws the notice because there is no offset '0' in the array $term-parents. In that context the set offset is 256, the term id of the "middle" group. I think that is also the reason why the "first" term in this array is checked to be non zero.

However, the links within this group will be displayed correctly.

jonathan1055’s picture

StatusFileSize
new56.17 KB
new153.18 KB

Yes, that is what I had, and did not get the error. Obviously there is a problem, as shown by your screenshots, but for the benefit of our understanding, I'd like to know what is going on before we simply remove the e-notice.

My taxonomy looks like

I added the following code to a hook_form_alter to display the term id and parent in the table

  // Display the term id when viewing a taxonomy
  if ($form['#form_id'] == 'taxonomy_overview_terms') {
    foreach ($form as $key => $item) {
      if (substr($key, 0, 4) == 'tid:') {
        dd($item, $key);
        $form[$key]['view']['#title'] .= ' (term ' . $item['#term']['tid'] . ', parent ' . $item['#term']['parent'] . ')';
      }
    }
  }

Then on viewing a link in the third group, to display the breadcrumbs, I have

On clicking the middle link, there is no error and I get the following debug from weblinks_get_tree()

-- weblinks_get_tree --
$term: stdClass Object
(
    [tid] => 10
    [vid] => 4
    [name] => Henry the Green Engine
    [description] => 
    [format] => filtered_html
    [weight] => 0
    [vocabulary_machine_name] => weblinks
    [depth] => 0
)

$term: stdClass Object
(
    [tid] => 12
    [vid] => 4
    [name] => Edward the Blue Engine
    [description] => 
    [format] => filtered_html
    [weight] => 0
    [depth] => 1
    [parents] => Array
        (
            [0] => 10
        )
)

So what we need to find out is how this differs from what you have.

GStegemann’s picture

StatusFileSize
new27.72 KB
new25.44 KB

Here are my debug results:

and in uploaded weblinks_terms_drupal_debug.txt.

jonathan1055’s picture

Thanks. I also had a dd() in weblinks_get_tree around line 1120. Can you add it, then click the middle breadcrumb link (or whatever one produces the error) and upload the .txt

  $new_tree = array();
  foreach ($tree as $term) {
    dd($term, '$term');
GStegemann’s picture

StatusFileSize
new1.88 KB

Here is the output of dd() in weblinks_get_tree, file weblinks_get_tree_drupal_debug.txt.

jonathan1055’s picture

The differences between your array and mine (ignoring rdf which I deleted) is that you have these extra items

[language] => und
[i18n_tsid] => 0
[metatags] => Array
        (
        )
[parents] => Array
        (
            [255] => 255
        )
[guid] => http://www.igs.ld/cm7/en/taxonomy/term/256

In my output, there is no 'parents' key at all for the term clicked on - we only get that for the child terms later in the process. Are we certain that your 'parents' item is actually a weblinks item? Maybe we have a clash of key names here - has one of your other modules created this item?

jonathan1055’s picture

StatusFileSize
new4.72 KB

Here's a version of weblinks_get_tree with more debug. This should show us what is happening

GStegemann’s picture

StatusFileSize
new12.64 KB

Yes, there is another vocabulary called 'Tags', machine name 'vocabulary_2', which also a term 'FactoryLink' with termid '233'.

OK, I have replaced weblinks_get_tree with your debug version and re-run the tests. See uploaded debug file.

jonathan1055’s picture

Status: Needs review » Needs work
StatusFileSize
new6.43 KB

We never did resolve this. Attached is a replacement for weblinks_get_tree() for the latest 7.x code, with debug using dd() as before. Can you paste this into your clean 7.x weblinks.module and post back the output?

Looking back to #13 I think that the extra 'parents' property you get is created in taxonomy_term_load() so I have added extra debug at that point.

I think that we could be wrong to use isset to protect the if ($term->parents[0] != 0) line, it might be correct to get the actual key used, or use array_shift or array_keys to get the first value without assuming they key is 0. But until we know where that spurious value comes from we should not simply make the error go away.

If neither you nor I can understand the weblinks code, then we must work at it, because if we don't then no one else will be able to follow it either ;-)

GStegemann’s picture

StatusFileSize
new10.93 KB

Here are my first results. Taxonomy is the same as used in earlier tests.

Are we certain that your 'parents' item is actually a weblinks item? Maybe we have a clash of key names here - has one of your other modules created this item?

Sure, that might be a key name clash. But how can I discover that?

jonathan1055’s picture

Thanks for the debug. I will work through it and compare to mine.

To discover the key name clash, maybe you could search your site's codebase for the keywords metatags, parents, guid which you get from taxonomy_term_load(256) and I do not. See what modules it finds, then disable those and re-run the debug to see if we get a different result.

GStegemann’s picture

StatusFileSize
new26.66 KB

I found the interfering module. The key name 'parents' is also used by "Taxonomy import/export via XML", https://www.drupal.org/project/taxonomy_xml.

After disabling the module the error has gone.

But who is wrong now? Web Links or Taxonmy XML? Maybe our error is related to #1835898: RDF import not recreating hierarchy.

jonathan1055’s picture

StatusFileSize
new6.87 KB

Ah Ha! Now we know where the extra 'parents' property comes from, it is in taxonomy_xml's hook_taxonomy_term_load. We can solve the problem properly, but first I had to work out what weblinks_get_tree() is doing:

Weblinks_get_tree() gets the tree from supplied $parent id, via $tree = taxonomy_get_tree(_weblinks_get_vocid(), $parent); This will return an array of term objects below the requested $parent id. Each object has a 'parents' property which is the array '0' => term id. If taxonomy module does not exist then we do not have a tree but a simple unclassified list, plus maybe unpublished too.

Next, if the requested $parent is not the top level '0' we add the actual term for $parent into the top of the $tree, shifting the depth down for all items already recovered. The $parent item is extracted via $parent_term = taxonomy_term_load($parent) and this does NOT normally have a 'parents' key. However, module Taxonomy_xml adds a 'parents' key with values 'term' => term, not '0' => term like the lower levels.

Later in weblinks_get_tree we want to create a 'children' array by taking data from the 'parents' property of each term. Weblinks assumes that if 'parents' exist then the (first) key will be '0'. This is true for all the children terms but for the top-level term there is no 'parents'. All fine.

However, when module taxonomy_xml exists, it's own hook_taxonomy_term_load adds a 'parents' property, keyed with the term id, not '0'. So when we try to build the 'children' array we also process it for the top-level term and the code fails because there is no '0' key.

To solve this we could manipulate the returned array to cater for zero and non-zero keys in the parents property. But a much simpler correction is not to call taxonomy_term_load at all, but call taxonomy_get_tree starting from the parent of the requested term. This avoids the fuss of having to insert the parent term at the top and shift all the depths down by one.

Attached is another weblinks_get_tree with the new code in addition to the old, so you can compare the final $tree and we shall see that the error will not be created. Can you test this as before, with taxonomy_xml enabled, and send back the debug.

jonathan1055’s picture

I've done some further testing and we do need to keep the original call to taxonomy_term_load(). Otherwise the requested $parent term is not inserted if that is a real top-level term.

So an option (1) would be to simply unset 'parents' from the obejct returned by taxonomy_term_load() so that any hook invocations of this do not the property which the core function does not add. That might be the easiest to understand for code maintainers later.

Another solution (2) would be to code round the extra 'parents' array we were not expecting, and not make assumptions about the keys just look at the values.

I presume that the final structure of the returned tree should be the same as we had in D6, and the same as in D7 if there are no other hook implementations altering it. This means no 'parents' item for the top term returned. If this is the case then option (1) is the best.

I've downloaded taxonomy_xml so I can replicate the problem you get.

jonathan1055’s picture

Status: Needs work » Needs review
StatusFileSize
new6.32 KB
new1.71 KB

Here is the final debug version (but only if you really want to try it) and a real patch to test. I have added several comments as the original was a little obscure in what it was doing. The actual code changes are:

  1. Unset 'parents' after running taxonomy_term_load.
  2. Remove the explicit test for if ($term->parents[0] != 0) as this can be checked within the foreach loop.
  3. The input parameter $parent was being re-used (overwritten) by $parent in this foreach loop, so I have renamed this one $tid_parent, i.e the term id of the parent.

I've tested with multiple terms in the hierarchy, single terms, starting at the top level, starting at the lowest level, with and without taxonomy_xml, and running without the taxonomy module. All seems OK. Patch against alpha1+13.

GStegemann’s picture

Many thanks for your indepth analysis, detailed descriptions and patch.

Sure, I will try to run your latest debug version, maybe tomorrow or on Monday.

GStegemann’s picture

StatusFileSize
new42.6 KB

I've re-tested this issue against the debug version of weblinks_get_tree from comment #22. My results are attached. So far the patch looks OK.

jonathan1055’s picture

That's great. Can you re-enable your Taxonomy_xml module and just try the middle term weblinks/256 as that was the actual original cause of the problem. If that works then I think we've solved it.

GStegemann’s picture

StatusFileSize
new31.1 KB

Sorry. Thanks for reminding me to re-run the test with Taxonomy XML enabled. The debug log is attached.

Yes, I agree. The issue is solved now.

GStegemann’s picture

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

I ran a second test, in just supplying a not existing parent ID, like 300. Then several notices are thrown in several functions:

Notice: Undefined property: stdClass::$tid in weblinks_get_tree() (line 1103 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 5 elements)
  
Notice: Undefined property: stdClass::$tid in weblinks_get_tree() (line 1147 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 5 elements)
  
Notice: Undefined property: stdClass::$name in weblinks_get_tree() (line 1159 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 5 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_format_group() (line 994 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 5 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_links() (line 1375 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 6 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_links() (line 1379 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 6 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_links() (line 1382 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 6 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_links() (line 1392 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 6 elements)
  
Notice: Undefined property: stdClass::$tid in _weblinks_format_group() (line 1004 of /var/www/html/cm7/sites/all/modules/weblinks/weblinks.module). =>... (Array, 5 elements)

Note: referenced line numbers based on debug version weblinks_get_tree.

Should this case/code be safeguarded as well?

    $tid = $term->tid;
    // If we are too deep already, or the term should be hidden from the main
    // links page, skip the whole term.
    $show_this_term = variable_get('weblinks_page_' . $tid, TRUE);

When you attempt the same with an alphanumeric parent ID/group ID, like www.example.com/weblinks/bumper an applicable error message w/o any notices is displayed: 'Invalid group requested (bumper)'.

  • jonathan1055 committed 188d6d1 on 7.x-1.x
    Issue #2197719 by GStegemann, jonathan1055: Undefined offset: 0 in...
jonathan1055’s picture

I did not see your final comment before I did the commit. But, anyway what we have changed is still fine.

Yes, it might be nicer to protect those warnings. I guess they could be produced if some hard-coded link in a page referred to a web link group which has since been deleted by the admin. I'll look at that.

GStegemann’s picture

But, anyway what we have changed is still fine.

Yes, of course.

Thanks for looking into the 'invalid group' issue.

jonathan1055’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.2 KB

It was nice and simple to fix, with no extra function calls, just checking the result returned from taxonomy_term_load(). I tidied up some of the comments which were repeating themselves.

Patch is on top of the commit above, but the -dev release on the front page has not been refreshed yet. However, on https://www.drupal.org/node/870844 it has been refreshed to alpha1+14

GStegemann’s picture

Status: Needs review » Reviewed & tested by the community

Tested and works.

BTW: I had to apply the patch. The tar file was not up-to-date yet.

  • jonathan1055 committed 43ff0cf on 7.x-1.x
    Issue #2197719 by GStegemann, jonathan1055: Undefined offset: 0 in...
jonathan1055’s picture

Status: Reviewed & tested by the community » Fixed

I took the opportunity in this second commit to also fix all of the coder review warnings within _weblinks_get_tree(). I think it is worth doing things like when it's appropriate and when they do not obscure the actual code fix being discussed. Also if the extra changes are kept within the function already being altered then this is unlikely to increase the number of other patches that might have to be re-rolled.

Just for the record, the stats before were:

1 projects, 22 files, 131 normal warnings, 64 minor warnings


Stats after:

1 projects, 22 files, 124 normal warnings, 64 minor warnings


Thank you for all your testing! It's great to get this issue fixed.

GStegemann’s picture

Regarding coder reviews: that's OK.

And thank you for sorting this out.

Status: Fixed » Closed (fixed)

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