Simplify extension for SilverStripe hides children pages in the SiteTree / TreeView

Simplify is an extension for the popular SilverStripe Content Management System (CMS). Its purpose is to simplify the use of the admin interface by allowing fine-grained permissions as to which users should be allowed to see which options.

The latest version of Simplify as of this writing was the Git revision b3a3b821 from November 22, 2013. The docs marked this version as compatible with SilverStripe 3.0, ie. it was not explicitly tagged for version 3.1.

As far as I can tell so far, it basically works with one exception. If you’re at the “Pages” view, there’s two buttons in the upper right corner to switch between a tree view and a list view. The tree view already existed in SilverStripe 2.x and was part of the navigation bar to the left. The list view is new in SilverStripe 3.x and intended to be more suitable for large collections of pages through using a GridField component with pagination.

Now the Simplify extension can be used to hide certain pages in the tree view, but the way it currently does this leads to the effect that with SilverStripe 3.1 children pages may be hidden, rendering the holder classes unable to expand. In the example screenshot below, the arrows next to the red marker used to be hidden:

SilverStripe TreeView

To understand this, we have to dive a bit into SilverStripe internals.

The Hierarchy class is a DataExtension that hooks onto SilverStripe’s Page class, providing a method markingClasses() which is responsible for eg. adding markers such as “Draft” behind the page’s name.

Now Simplify implements a SimplifyDataObjectDecorator class that is also an DataExtension that gets hooked up to Page. In order to implement the page hiding functionality it provides its own markingClasses() method, thus replacing Hierarchy‘s implementation. Because the original code was still needed, the author copied it into his own method, augmenting it with his own additions.

This worked fine as long as the original Hierarchy class’ behavior did not change but it did so with SilverStripe 3.1 (eg. there is now a new numChildrenMethod that gets called to determine whether a page has children pages or not), thus causing the effect described above.

I could have just copied the updated code from the Hierarchy class again but then it would always be a cats-and-mice game whenever a new SilverStripe version comes out. So instead, I wrote a patch that makes SimplifyDataObjectDecorator‘s markingClasses() method call Hierarchy‘s implementation first and uses its results as basis for adding its own stuff.

Turns out, this wasn’t so easy, because to make it clear, I wanted an extension’s method to call another active extensions’s method. One might assume that, because the “other” extension (in my case Hierarchy) was also extending the underlying Page object, I could just call $this->owner->markingClasses() but actually this caused my Apache instances to silently segfault for one reason or another. Even funnier:

method_exists($this->owner, 'markingClasses') == false

So on the one hand PHP thinks there is no method markingClasses, on other hand if I try to call it it doesn’t report a “Call to undefined method” error ?! (This is with PHP 5.6.1, for those who are curious).

I also could not just call Hierarchy::markingClasses() because it is not a static method. Instead you have to do this:

$hierarchyExtension = $this->owner->getExtensionInstance('Hierarchy');
$classes = $hierarchyExtension->markingClasses();

That is, I get a reference to the existing extension class I’m interested in (Hierarchy) and before I call its method, I explicitly set its owner to my $this->owner. The latter is required because otherwise the called methods will not work correctly. This principle should be applicable to other extensions and use cases as well, thereby hopefully proving useful to “stack” extensions onto each other.

To close, here’s the pull request with this patch for the Simplify module.

Leave a comment