Hide pagetype from create dropdown

Hide a page from the CMS create dropdown

The reason to remove a certain pagetype from the CMS create dropdown can be divers: to prevent certain groups of users from adding certain pages (or editing, publishing or deleting them), to allow the creation of certain pagetypes for specific parents only, or to just eliminate certain pagetypes entirely. Below are a number of ways to influence the create-dropdown. There is a seperate article on the use of permissions and in there halfway you'll find a solution to set from mysite/_config.php what pages are available for which users...

1. Allowed children

The $allowed_children array can be set within a page class to tell the CMS which pagetypes are allowed as children for this pagetype. All other pagetypes are removed from the dropdown. For example within a ProductHolder class:

// allow ProductPages and all its extensions
$allowed_children = array('ProductPage');
// allow only ProductPages, excluding its extensions
$allowed_children = array('*ProductPage');

Note: this will not remove ProductPages that have already created prior to these settings. They can still be saved and/or published.

2. Can be root

The allowed children setting might give you a way to limit the pagetypes that can be created as childpages, but that won't work for the root of the site. Setting the static $can_be_root variable to false for a certain pagetype will exclude it from the create dropdown in the root.

// this pagetype cannot be created in the site root:
static $can_be_root = false;

Note: again this will not remove ProductPages already existing in the root. They can still be saved and/or published.

3. Extend allowedChildren()

The SiteTree method allowedChildren(), that returns the final array of classnames that is used to build the create dropdown, can be extended to remove a pagetype from the dropdown. In this example the ProductPage is removed for every Parent type except the ProductHolder. In the Page class:

function allowedChildren() {

    $pageTypes = parent::allowedChildren();

    // Remove ProductPages for every parentpage except the ProductHolder
    if ($this->ClassName != 'ProductHolder' && is_array($pageTypes)) {
        array_splice($pageTypes, array_search('ProjectPage', $pageTypes), 1);
    }
    return $pageTypes;
}

Note: this will not affect the create Dropdown for the root of the website - but this can be remedied by setting $can_be_root = false; in the ProjectPage class itself...

4. Restrict the user

If you want to remove pagetypes from the create dropdown for certain users only, use the canCreate(), canEdit() and canDelete() methods to determine what a user can or cannot do with a specific pagetype:

class ProductPage extends Page {

    function canCreate($member= null)
        return false;
    }
    ...

The method above will effectively remove the ProductPage pagetype from the create dropdown - and no-one will ever be able to create a page of this type again. A much more flexible way to do this, is by using permissions:

User access to the CMS using permissions

There are other ways...

There are other ways to hide a pagetype from the pagetype-dropdowns in the CMS, preventing the user from creating a new instance of this particular pagetype in the CMS. But beware: use the following examples only for pagetypes that will never be created in the cms. Pages created earlier will not be hidden or removed from the SiteTree. If you then save/publish existing pages, you'll have to select a new pagetype in the Behaviour|Page type dropdown first, or else the CMS will pick the pagetype in the top of the list, since the original is no longer available.

5. Use HiddenClass

The HiddenClass is meant to remove PageTypes from the create dropdown, but not its extensions. The idea is that you might want to create a certain base class and then create different extended pagetypes from it - but not have the baseclass appear in the dropdown:

class MyBaseClass extends Page implements HiddenClass {
	...
}

Note: unfortunately HiddenClass is just an empty class... The SiteTree method getClassDropdown() that creates the options for the dropdown, only checks if the class is implemented, nothing else. So it cannot be tweaked/extended to do any extra checks...

6. Hide ancestor

Fairly equal - but not the same. Setting $hide_ancestor to true for a certain pagetype will remove its direct ancestor from the create dropdown. So if you were to customize the ProductPage, you could extend it to create a CustomProductPage and then hide the original ProductPage. This would keep your code backwards compatible, in that if you remove the CustomProductPage from code, the original version will automatically become available again:

class CustomProductPage extends ProductPage {
	static $hide_ancestor = 'ProductPage';
}

7. hide ancestor - hide self

The combination of $hide_ancestor and HiddenClassprovides a sneaky way to remove a core SilverStripe pagetype like VirtualPage from the create dropdown: extend it, remove the ancestor, then implement HiddenClass to remove the newly created extension as well...

$hide_ancestor is a somewhat obscure addition to SilverStripe, that is used (only) in the static page_type_classes() method within the SiteTree class. It is used to remove a class from the list of classes that build up the dropdown. It is quite easy to misuse, because there is no checking whether the class to remove is a valid ancestor. It'll just remove any pagetype you select. You could even create some dummy pagetype only for the purpose of removing another and then hiding itself:

class RemoveThisPage extends Page implements HiddenClass {
   static $hide_ancestor = 'VirtualPage';
}

So now they are both gone. Just make sure you have no instances of these classes in your SiteTree. No connection whatsoever, and it will work, as long as you /dev/build/?flush=1...

8. manipulate onBeforeWrite()

This trick can be used if you don't care if the user creates a certain pagetype from anywhere on the website, as long as they all end up as a child of a certain page once they are saved. It's a bit crude, but in certain situations I found it working quite well. So ignore if you will, but for me, I still want to log this :-)

function onBeforeWrite(){
	$this->ParentID = 17;
	parent::onBeforeWrite();
}

Comments

Het versturen van reacties is uitgeschakeld.

RSS feed voor reacties op deze pagina