Mecha CMS

Mecha CMS blog and documentation.

Creating a Child Page Feature

Updated: Sunday, 07 August 2016

Add child page feature in Mecha CMS with a little hack.

Update: The plugin version of this tutorial is now available for Mecha 1.1.1 and above.

I don’t add this ability as a native feature in Mecha. This modification allows you to add child pages on the available pages, so you can create a branch page after the available page. Only one branch.

// Before
http://mecha-cms.com/2016/about

// After
http://mecha-cms.com/2016/about/me
http://mecha-cms.com/2016/about/us

First, you need to create a custom field with the data like this:

TitleKeyTypeScopeValue
Parentparent_page_slugTextPage

So you will get a new field like this in the page editor. Use this field to define the page slug you want to set as the parent page:

Custom Field for Parent Page Slug

Now open engine\launch.php file through the cPanel. Copy this route, then place it after the static page route:

/**
 * Sub Static Page
 * ---------------
 *
 * [1]. parent-slug/child-slug
 *
 */

Route::accept('(:any)/(:any)', function($parent = "", $child = "") use($config) {

    // Check if parent page does not exist
    if( ! $page_parent = Get::pageAnchor($parent)) {
        Shield::abort('404-page');
    }

    // Check if child page does not exist
    if( ! $page_child = Get::page($child)) {
        Shield::abort('404-page');
    }

    // Check if custom field is not available
    if( ! isset($page_child->fields->parent_page_slug)) {
        Shield::abort('404-page');
    } else {
        // Check if custom field value != parent page slug
        if($page_child->fields->parent_page_slug != $parent) {
            Shield::abort('404-page');
        }
    }

    // Check if parent page or child page is a draft
    if($page_parent->state == 'drafted' || $page_child->state == 'drafted') {
        Shield::abort('404-page');
    }

    // Inject custom CSS data of child page if available
    Weapon::add('shell_after', function() use($page_child) {
        if(isset($page_child->css)) echo $page_child->css;
    });

    // Inject custom JavaScript data of child page if available
    Weapon::add('sword_after', function() use($page_child) {
        if(isset($page_child->js)) echo $page_child->js;
    });

    // Set the child page data
    Config::set(array(
        'page_type' => 'page',
        'page_title' => $page_child->title . $config->title_separator . $page_parent->title . $config->title_separator . $config->title,
        'page' => $page_child
    ));

    // Attach the shield
    Shield::attach('page-' . $child);

});

// Add a notice in your page manager if this page is a child page
Weapon::add('page_footer', function($page) use($config, $speak) {
    if($config->page_type == 'manager' && isset($page->fields->parent_page_slug) && trim($page->fields->parent_page_slug) !== "") {
        echo ' &middot; Child of <a href="' . $config->url . '/' . $page->fields->parent_page_slug . '">' . Get::pageAnchor($page->fields->parent_page_slug)->title . '</a> / <a href="' . $config->url . '/' . $page->fields->parent_page_slug . '/' . $page->slug . '">' . $speak->url . '</a>';
    }
}, 21);

The static page route should have a comment header like this:

/**
 * Static Page
 * -----------
 *
 * [1]. page-slug
 *
 */

Route::accept('(:any)', function($slug = "") use($config) { … });

Now look at the static page route. Copy this conditional snippet …

// Do not allow child page to be accessed directly as a normal page
if(isset($page->fields->parent_page_slug) && trim($page->fields->parent_page_slug) !== "") {
    Shield::abort('404-page');
}

… then place it after this code:

if( ! $page = Get::page($slug)) {
    Shield::abort('404-page');
}

Final results:

/**
 * Static Page
 * -----------
 *
 * [1]. page-slug
 *
 */

Route::accept('(:any)', function($slug = "") use($config) {

    if( ! $page = Get::page($slug)) {
        Shield::abort('404-page');
    }

    // Do not allow child page to be accessed directly as a normal page
    if(isset($page->fields->parent_page_slug) && trim($page->fields->parent_page_slug) !== "") {
        Shield::abort('404-page');
    }

    …
    …

});

/**
 * Sub Static Page
 * ---------------
 *
 * [1]. parent-slug/child-slug
 *
 */

Route::accept('(:any)/(:any)', function($parent = "", $child = "") use($config) {

    …
    …

});

// Add a notice in your page manager if this page is a child page
Weapon::add('page_footer', function($page) {

    …
    …

}, 21);

Done!

Lets say you have a page with slug about then want to create a child page for that page with slug me. Create a new page, fill the custom field with about, then fill the slug field with me. Complete all of your page content, then press the Publish button. Now your child page will be available at http://mecha-cms.com/2016/about/me.

Donation and Email Subscription