One Resource and Children missing from Resource Tree

Hi all,

I have a site in development with around 60 resources.

One resource, “Get Involved” - and its four children - do not appear in the MODX Resource Tree.

I can find them by searching MODX and they all show up in the Batcher extra.

I can see each resource in the database and I’ve checked each attribute - I can’t see anything unusual about any of them.

Get Involved has a parent “0” - similar to About and Contact etc.

I can edit the resources fine using the MODX search - but I need them to show in the tree.

I don’t currently employ any Resource Groups and the pages all have a context_key of “web”.

Any thoughts much appreciated.

Chris

MODX 2.8.3 | PHP 8.0

It looks like the resource/getNodes processor is used to query the nodes for the tree.

In the query it filters the resources based on the columns show_in_tree (= true), context_key and parent. The code also checks for the ‘list’ policy.

There isn’t much more that I can determine from a quick glance at the code.
Do you have a weird value for the system setting tree_root_id?

Thanks @halftrainedharry

show_in_tree and context_key look OK to me:

tree_root_id is set to 0

I just tried changing the parent to 15 via the database.

When I do that, the Get Involved page and its children appear in the About (15) node.

Changing it back to 0 - they vanish again.

OK … some more info …

If I place the Get Involved page in another node it shows fine.

If I then drag it onto the Website container, it appears at the bottom of the resources list.

I can refresh the page and it sticks! So all good.

But … if I then drag the Get Involved page to place it further up the list in the tree - then refresh the page - it vanishes.

So I think the issue is to do with the re-ordering of the Resource tree.

Also - it seems this is true of any resource.

If I drag it to re-order the Resource tree - that resource will disappear on next refresh.

Apologies for flooding my own post!

I’ve now managed to make this happen on another site - although it’s much less predictable.

But I persisted - and moving Resources around in the tree - they do eventually disappear.

That’s all very weird and I have no idea what could cause this.

Can you somehow isolate the conditions when it happens?

  • Do both your sites use PHP 8?
  • Are there any extras on both your sites that may interfere? Maybe “Collections”?

Both are on PHP 8.

I suspect “Articles” might be the culprit.

@halftrainedharry I’m going to message you a video of the behaviour.

I’ve seen something like this when moving things around by dragging and dropping them in the tree. Resources can end up with an invalid parent, or resources can end up being each other’s parent. If something goes wrong when MODX tries to traverse the tree, things can disappear.

That led me to create SiteCheck, which checks for the following (and a lot more):

  • Resources with invalid parents
  • Resources with invalid Templates
  • Resources with empty aliases
  • Resources with duplicate aliases in the same Context
  • Resources with frozen, empty URIs
  • Resources with duplicate URIs in the same Context
  • Resources with duplicate pagetitles in the same Context
  • Resources with invalid class keys
  • Resources with invalid Contexts
  • Resources where context_key doesn’t match parent’s

I also wrote this post many years ago about Articles disappearing.

I was able to reproduce the problem with an ArticlesContainer in the resource tree.

The problem is connected to the way the _loadCollectionInstance function of the class modAccessibleObject works:

If $obj->isLazy() is true, then the object/resource is added to the collection without a key:

$objCollection[]= $obj;

If $obj->isLazy() is false however, the object/resource is added to the collection with the ID as the key:

$objCollection[$pkval]= $obj;

As isLazy() is true for all the normal resources, and false for ArticlesContainers, this can create the situation, that an item in $objCollection gets overwritten.

Say your ArticlesContainers has the ID = 6. If by the time the ArticlesContainer is processed, there have already been 7 or more normal resources added to the $objCollection, then an assigment to $objCollection[6] overwrites the stored resource (and that resource won’t show up in the resource tree).

Very nice sleuthing! :sunglasses:

@halftrainedharry thanks for confirming & investigating. Such an unusual issue.

I’m going to drop the Articles extra which I’d been thinking of doing anyway as it happens.

@bobray thanks as always for your input :+1:

@halftrainedharry Do you think this issue is related to PHP 8?

I’ve been using Articles for many years (I think with about 300 articles) and haven’t had an Article resource disappear since I wrote that post in 2013, though I don’t think I’m running PHP 8.

No, I ran PHP 7.2 when reproducing the issue.
It also seems to be a very old bug. There is an open issues on github from 2013 that describes the same problem.

It’s not an Article resource that disappears. It’s a normal MODX resource, that has the same parent as an ArticlesContainer resource that may disappear (under certain circumstances).

What you described in your post from 2013 is a different problem.


I believe, it is a bug in the MODx core that can occur, if getCollection() is called for a mixture of lazy and non-lazy objects.

The resource/getNodes processor only queries a subset of the modResource columns, so the normal MODX resources are lazy, but the class “ArticlesContainer” overrides the isLazy() function and always returns false.

Thanks. The anomalies I observed which led me to write SiteCheck all resulted from dragging and dropping resources in the tree. Does that fit with what you found?

I think, this case is somewhat different from the things you check with SiteCheck.
In this case the values in the database are not per se wrong, there is just a bug when querying them with getCollection().

Basically what’s happening is the following:
If the “ArticlesContainer” has an ID of 2 and there are 2 + 1 (or more) resources with a lower value of menuindex, then the resource at position 2 + 1 gets overwritten.

$a = array();
$a[] = 'Resource A'; //key is 0
$a[] = 'Resource B'; //key is 1
$a[] = 'Resource C'; //key is 2
$a[2] = 'ArticlesContainer'; //key is ID (=2) -> overwrites 'Resource C' in the array

The reordering of resources in the tree just sets the menuindex value, that determines what resource is at position 2 + 1.


If there are multiple “ArticlesContainer” resources in the same tree-node, then things get even more unpredictable. Let’s say you have 2 ArticlesContainers with the IDs 20 and 21:

$a = array();
$a[] = 'Resource A'; //key is 0
$a[] = 'Resource B'; //key is 1
$a[20] = 'ArticlesContainer (20)'; //key is ID (=20)
$a[] = 'Resource C'; //key is 21(!)
$a[21] = 'ArticlesContainer (21)'; //key is ID (=21) -> overwrites 'Resource C' in the array

Ah. So at Bob’s Guides, where my Articles container has an ID around 300, and I have well over 300 resources, I probably have a resource that never shows up in the tree, but with so many resources, I’ve never noticed that.

Do you have a suggested fix that doesn’t break Articles?

That’s unlikely.
For that to happen, your 300+ resources had to be in the same tree-node (same value for parent) as your ArticlesContainer resource and placed above it.

If you have only one ArticlesContainer resource with a high ID value, you should be fine.

Unfortunately I don’t see an easy fix.

I think the classes ArticlesContainer and Article probably need a proper implementation of the isLazy() function instead of just always returning false.