lokomotivan
10/17/2017 - 12:12 PM

Processwire Module Blueprint

Processwire Module Blueprint

<?php
/**
*   Delete templates, fieldgroups, pages....
*   here we will be deleting everything we created on install.
*
*   Note that we need to delete this things in this order becose all this elements are inner dependent and related,
*   and we want to avoid all posible errors. 
*   
*   1. Pages
*   2. Fieldgroups
*   3. Templates
*   4. Fields
*
*/


//----------------------------------------------------------------------
//  1. PAGES
//----------------------------------------------------------------------
// get pages in trash - note has_parent=2 "2" is trash ID
$pages_in_trash = $this->pages->find("template=events|event|events-widget, has_parent=2, include=all");
// get rest of the pages
$pages_to_del   = $this->pages->find("template=events|event|events-widget, include=all");
// delete trashed
foreach($pages_in_trash as $p) {
    if($p && $p != '') {
        wire('pages')->delete($p, true);
    }
}
// delete rest of pages
foreach($pages_to_del as $p) {
    if($p && $p != '') {
        wire('pages')->delete($p, true);
    }
}


//----------------------------------------------------------------------
//  2. TEMPLATES
//----------------------------------------------------------------------
// templates array - all the template names we need to delete
$templates_arr = array("events", "event", "events-widget");
// run array true the loop and delete them all
foreach($templates_arr as $item) {
    // get tempaltes
    $t = wire('templates')->get($item);
    // if template exists
    if($t && $t != '') {
        // if template is not assigned to any page
        if ($t->getNumPages() > 0) {
            throw new WireException("Can't uninstall because template been used by some pages.");
        }else {
            wire('templates')->delete($t);
        }
    }
}

//----------------------------------------------------------------------
//  3. FIELDGROUPS
//----------------------------------------------------------------------
// fieldgroup array. We can use templates array above, but for example let's run this using another array...
$fg_arr = array("eveents", "event", "events-widget");
foreach($fg_arr as $item) {
    $fg = wire('fieldgroups')->get($item);
    if($fg && $fg != '') {
        wire('fieldgroups')->delete($fg);
    }
}

//----------------------------------------------------------------------
//  Delete content_source page
//----------------------------------------------------------------------
$cs_p = wire('pages')->get("/system/options/content-source/events/");
if($cs_p && $cs_p != '') {
    wire('pages')->delete($cs_p, true);
}
<?php
/**
*   Admin Markup!
*   this is where we write and include main module page markup
*
*/

// _actions.php contain all page actions we need: Delete,  Hide/Unhide, Publish/Unpublish, Clone...
include_once("./_actions.php");
// in _selector.php we define main page selector to find out pages
include_once("./_selector.php");
// toolbar
include_once("./_toolbar.php");
// add new buttons
include_once("./_buttons.php");
// quick settings
include_once("./_modal-settings.php");

$table = "
    <table class='uk-table uk-table-small uk-table-middle uk-table-striped'>
        <thead>
            <tr>
                <th>Thumb</th>
                <th>Name</th>
                <th>Created / Modified</th>
                <th class='uk-text-right'>Actions</th>
            </tr>
        </thead>
        <tbody>
";

foreach($items as $item) {

    // Model Thumb
    if($item->images->count > 0) {
        $thumb = "<img class='uk-border-circle' src='{$item->images->first->size(50, 50, "north")->url}' />";
    }else {
        $thumb = '';
    }

    // dates
    $created = date('M d Y',$item->created);
    $modified = date('M d Y H i',$item->modified);

    // hidden-unpublished classes
    $class = '';
    $hidden_class = '';
    $unpublished_class = '';
    $trashed_class = '';
    if($item->isHidden()) {
        $class .= 'ivm-is-hidden';
        $hidden_class .= 'ivm-is-hidden';
    }elseif($item->isUnpublished()) {
        $class .= ' ivm-is-unpublished';
        $unpublished_class .= 'ivm-is-unpublished';
    }elseif($item->isTrash()) {
        $class .= 'ivm-is-trashed';
        $trashed_class .= 'ivm-is-trashed';
    }

    $table .= "<tr class='$class' uk-toggle='mode:hover; cls: ivm-hover'>";

        // thumb
        $table .= "<td class='uk-table-shrink'>
            <span class='ivm-hover-thumb'>$thumb</span>
        </td>";

        // Title
        // its very important not to change edit url, it should be relative and start with "edit/?id="
        $table .= "
            <td>
                <h4 class='uk-margin-remove'>
                    <a class='{$class}' href='edit/?id={$item->id}&back_url=$url_segment'>{$item->title}</a>
                </h4>
                <div class='uk-text-meta'>/{$item->name}/</div>
            </td>
        ";

        // Meta
        $table .= "<td class='uk-text-meta'>Created: {$created} <br /> Modified: {$modified}</td>";

        //----------------------------------------------------------------------
        //  Quick Actions
        //----------------------------------------------------------------------
            include("./_qa.php");
            $table .= $qa;
        //----------------------------------------------------------------------
        //  Quick Actions End
        //----------------------------------------------------------------------

    $table .= "</tr>";

}


$table .= "</tbody></table>";

/*
 *  Final Markup
 *
 */
$markup = $buttons;
$markup .= '<section id="ivm-module">';
    $markup .= $alert;
    $markup .= $toolbar;
    if($items && $items != '') {
        $markup .= $table;
    }else {
        $markup .= "<div class='uk-padding uk-h3'>No items to display</div>";
    }
    $markup .= "<div class='uk-margin-medium-top'>$pagination</div>";
    $markup .= $modal_settings;
$markup .= "</section>";
<?php
/**
*   Install
*   1. Fields
*   2. Fieldgroups
*   3. Tempaltes
*   4. Pages
*
*/

// include_once("./_fields.php");
include_once("./_fieldgroups.php");
include_once("./_templates.php");
include_once("./_pages.php");
<?php
/**
*   Toolbar
*
*
*/

// sorting options
$sorting_options = array(
    '-created' => 'Latest',
    'created' => 'Oldest',
    '-modified' => 'Modified',
    'title' => 'A-Z',
    '-title' => 'Z-A'
);

// limit options
$limit_options = array(
    '5'  => '5',
    '10' => '10',
    '20' => '20',
    '30' => '30',
    '50' => '50'
);

// status options
$status_options = array(
    'active' => 'Active',
    'hidden' => 'Hidden',
    'unpublished' => 'Unpublished',
    'trash' => 'Trashed'
);

/*
*   Define form action, where form will be submited?
*   Form usually always submits data on same page, but we wont to check for url segments.
*   We want form to be submited on the exact page we are currently eg: example/page2
*
*/
$formAction = './';
if($url_segment && $url_segment != '') {
    $formAction = $moduleURL.$url_segment;
}

/*
*   Toobar markup
*
*/
$toolbar = "
    <div class='ivm-toolbar uk-background-muted uk-padding-small'>
        <form action='$formAction' method='get'>
            <div class='uk-grid-small uk-grid'>
";

                // Status Select
                $toolbar .= '<div class="uk-width-auto@m">';
                    $toolbar .= "<select class='uk-select' name='status' onchange='this.form.submit()'>";
                        $toolbar .= "<option value=''>- Status -</option>";
                        foreach($status_options as $option => $label) {
                            if(isset($_GET['status']) && $_GET['status'] == $option) {
                                $toolbar .= "<option value='$option' selected>$label</option>";
                            }else {
                                $toolbar .= "<option value='$option'>$label</option>";
                            }
                        }
                    $toolbar .= "</select>";
                $toolbar .= '</div>';

                // Search
                $toolbar .= "
                    <div class='uk-width-expand@m'>
                        <div class='ivm-search'><input class='uk-input' type='text' name='q' value='{$this->input->get->q}' placeholder='Search by title' /></div>
                    </div>
                ";

                // LIMIT
                $toolbar .= '<div class="uk-width-small@m">';
                    $toolbar .= "<select class='uk-select' name='limit' onchange='this.form.submit()'>";
                        $toolbar .= "<option value=''>- Display -</option>";
                        foreach($limit_options as $option => $label) {
                            if(isset($_GET['limit']) && $_GET['limit'] == $option) {
                                $toolbar .= "<option value='$option' selected>$label</option>";
                            }else {
                                $toolbar .= "<option value='$option'>$label</option>";
                            }
                        }
                    $toolbar .= "</select>";
                $toolbar .= '</div>';

                // SORT
                $toolbar .= '<div class="uk-width-small@m">';
                    $toolbar .= "<select class='uk-select' name='sort' onchange='this.form.submit()'>";
                        $toolbar .= "<option value=''>- Sort -</option>";
                        foreach($sorting_options as $option => $label) {
                            if(isset($_GET['sort']) && $_GET['sort'] == $option) {
                                $toolbar .= "<option value='$option' selected>$label</option>";
                            }else {
                                $toolbar .= "<option value='$option'>$label</option>";
                            }
                        }
                    $toolbar .= "</select>";
                $toolbar .= '</div>';

$toolbar .= "
            </div>
        </form>
    </div>
";
<?php
/*
*   Check for GET variables and put them to whitelist so they
*   can be available on url segments and pagination.
*
*/

// get limit for another module settins
$limit = $this->modules->get('PwthemesBlueprint')->admin_limit;
if(isset($_GET['limit']) && $_GET['limit'] != '') {
    $limit = $_GET['limit'];
    $this->input->whitelist('limit', $limit);
}

$sort = 'sort';
if(isset($_GET['sort']) && $_GET['sort'] != '') {
    $sort = $_GET['sort'];
    $this->input->whitelist('sort', $sort);
}

// Include all by default
$status = 'status!=trash,include=all,';
// if active leave status selector empty
if(isset($_GET['status']) && $_GET['status'] == 'active') {
    $status = "";
}
// if status is set add status selector
elseif(isset($_GET['status']) && $_GET['status'] != '') {
    $get_status = $_GET['status'];
    $this->input->whitelist('status', $get_status);
    $status = "status=$get_status,";
}

/**
 *  Selector Start
 */
$selector = "template=some_template, {$status} limit={$limit}, sort={$sort}";

// check for aditional GET avriables and update selector
if(isset($_GET['q']) && $_GET['q'] != '') {
    $q = $this->input->get->q;
    $this->input->whitelist('q', $q);
    $selector .= ", title*=$q";
}

// find pages
$items = $this->pages->find($selector);

// render pagination results
$pagination = $items->renderPager();
<?php
/**
*
*   Quick Action Markrup
*
*
*/

if($item->isTrash()) {
    $qa = "<td class='ivm-quick-actions uk-text-right'>";
        $qa .= "
        <a href='?action=restore&id={$item->id}&back_url=$url_segment' title='Restore' uk-tooltip>
            <span class='fa fa-undo'></span>
        </a>";
        // Copy & delete
        $qa .= "
            <a href='?action=perm_delete&id={$item->id}&back_url=$url_segment' title='Delete' uk-tooltip>
                <span class='fa fa-trash'></span>
            </a>
        ";
    $qa .= "</td>";
}else {
    $qa = "<td class='ivm-quick-actions uk-text-right'>";
        // publish
        if($item->isUnpublished()) {
            $qa .= "
            <a class='$unpublished_class' href='?action=publish&id={$item->id}&back_url=$url_segment' class='$unpublished_class' title='Publish' uk-tooltip>
                <span class='fa fa-ban'></span>
            </a>";
        }else {
            $qa .= "
            <a href='?action=publish&id={$item->id}&back_url=$url_segment' class='$unpublished_class' title='Unpublish' uk-tooltip>
                <span class='fa fa-check'></span>
            </a>";
        }

        // hide
        if($item->isHidden()) {
            $qa .= "
            <a class='$hidden_class' href='?action=hide&id={$item->id}&back_url=$url_segment' title='Unhide' uk-tooltip>
                <span class='fa fa-ban'></span>
            </a>";
        }else {
            $qa .= "
            <a class='$hidden_class' href='?action=hide&id={$item->id}&back_url=$url_segment' title='Hide' uk-tooltip>
                <span class='fa fa-eye'></span>
            </a>";
        }

        // Copy & delete
        $qa .= "
            <a class='qa-copy' href='?action=clone&id={$item->id}&back_url=$url_segment' title='Clone' uk-tooltip>
                <span class='fa fa-copy'></span>
            </a>

            <a class='qa-del' href='?action=delete&id={$item->id}&back_url=$url_segment' title='Delete' uk-tooltip>
                <span class='fa fa-trash'></span>
            </a>
        ";
    $qa .= "</td>";
}
<?php

$admin_limit = $this->modules->get("PwthemesBlog")->admin_limit;
$front_end_limit = $this->modules->get("PwthemesBlog")->limit;
$comments_option = $this->modules->get("PwthemesBlog")->enable_comments;

if($comments_option == '1') {
    $comments_enabled = "selected";
    $comments_disabled = "";
}else {
    $comments_enabled = "";
    $comments_disabled = "selected";
}

//----------------------------------------------------------------------
//	Modal Header
//----------------------------------------------------------------------
$modal_settings = "
<div id='settings-modal' uk-modal='center: true; bg-close: false'>
<div class='uk-modal-dialog'>
<form action='./' class='uk-form-horizontal' method='post'>
    <div class='uk-modal-header uk-text-center uk-background-primary uk-light'>

        <h3 class=''><span class='fa fa-cog'></span> Quick Settings</h3>

    </div>
<div class='uk-modal-body'>
";

//----------------------------------------------------------------------
//	Modal Body - Form Fields
//----------------------------------------------------------------------

$modal_settings .= "
    <div class=''uk-margin'>
        <label class='uk-form-label'>Posts per page (Admin)</label>
        <div class='uk-form-controls'>
            <input class='uk-input' type='text' name='admin_limit' value='$admin_limit' />
        </div>
    </div>
";

$modal_settings .= "
    <div class='uk-margin'>
         <label class='uk-form-label'>Posts per page (Front-End)</label>
        <div class='uk-form-controls'>
            <input class='uk-input' type='text' name='front_end_limit' value='$front_end_limit' />
        </div>
    </div>
";

$modal_settings .= "
    <div class='uk-margin'>
        <label class='uk-form-label'>Comments</label>
        <div class='uk-form-controls'>
            <select class='uk-select nice-select' name='comments'>
            <option value='1' $comments_enabled>Enabled</option>
                <option value='0' $comments_disabled>Disabled</option>
            </select>
        </div>
    </div>
";

//----------------------------------------------------------------------
//	Modal Footer
//----------------------------------------------------------------------
$modal_settings .= "
</div>
<div class='uk-modal-footer uk-text-center uk-background-muted'>

    <button class='uk-modal-close uk-button uk-button-default' type='button'>Cencel</button>
    <input class='uk-button uk-button-primary' type='submit' name='save_settings' value='Save Settings' />

</div>
</form>
</div>
</div>
";

//----------------------------------------------------------------------
//	Process
//----------------------------------------------------------------------

if($this->input->post->save_settings) {

    $admin_limit        = $this->sanitizer->text($this->input->post->admin_limit);
    $front_end_limit    = $this->sanitizer->text($this->input->post->front_end_limit);
    $comments           = $this->sanitizer->text($this->input->post->comments);

    $old_data = wire('modules')->getModuleConfigData('PwthemesBlog');
    $new_data = array(
        'admin_limit' => $admin_limit,
        'limit' => $front_end_limit,
        'enable_comments' => $comments
    );
    $data = array_merge($old_data, $new_data);
    $module = 'PwthemesBlog';
    wire('modules')->saveModuleConfigData($module, $data);

    // set sesion vars
    $_SESSION['status'] = "success";
    $_SESSION['note'] = "Settings Saved";

    $moduleURL = wire('config')->urls->admin.self::MODULE_URL;
    header("Location: {$moduleURL}");
    exit();

}
<?php
/**
 *   Buttons
 *
*/

$parent_ID  = wire('pages')->get('template=some_template')->id;

// add new buttons
$buttons = "<div class='ivm-admin-buttons'>";
    $buttons .= "
        <a class='uk-button uk-button-primary' href='{$adminURL}page/add/?parent_id={$parent_ID}&new_back=1'>
            <span class='fa fa-plus'></span> Add New
        </a>
    ";
    if($this->user->hasRole('superuser')) {
        $buttons .= "
            <a title='Module Settings' uk-tooltip class='uk-button uk-button-default uk-float-right' href='{$adminURL}module/edit?name={$this->className()}&collapse_info=1'>
                <span class='fa fa-wrench'></span>
            </a>
        ";
    }
    $buttons .= "
        <a title='Main Page Edit' uk-tooltip class='uk-button uk-button-default uk-float-right' href='{$adminURL}page/edit/?id={$parent_ID}'>
            <span class='fa fa-pencil'></span>
        </a>
    ";
$buttons .= "</div>";
<?php
$alert = '';

if(isset($_SESSION['note'])) {
    //$alert .= "<div class='ivm-alert ivm-alert-{$_SESSION['status']}'><i class='fa fa-info'></i> {$_SESSION['note']}</div>";
    $alert = "<script>";
    $alert .= "$(document).ready(function() {";
    $alert .= "UIkit.notification({";
    $alert .= "message: '{$_SESSION['note']}',";
    $alert .= "status: '{$_SESSION['status']}',";
    $alert .= "pos: 'top-center',";
    $alert .= "timeout: 3000";
    $alert .= "});";
    $alert .= "});";
    $alert .= "</script>";
    unset($_SESSION['status']);
    unset($_SESSION['note']);
}
<?php
/**
 *  Module Blueprint Actions
 *
 *  @author Ivan Milincic <lokomotivan@gmail.com>
 *  @copyright 2017 Ivan Milincic
 *
*/

// Delete
if(isset($_GET['action']) && $_GET['action'] == 'delete') {

    $backURL = $_GET['back_url'];

    $itemID = $_GET['id'];

    $blog_post = wire('pages')->get("id=$itemID");
    $blog_post->trash();

    // set sesion vars
    $_SESSION['status'] = "danger";
    $_SESSION['note'] = "\"$blog_post->title\" has been moved to trash!";
    
    header("Location: {$moduleURL}{$backURL}");
    exit();

}

// Hide/Unhide
if(isset($_GET['action']) && $_GET['action'] == 'hide') {

    $backURL = $_GET['back_url'];

    $itemID = $_GET['id'];
    $blog_post = wire('pages')->get("id=$itemID");

    if($blog_post->hasStatus('hidden')) {
        // Edit Page
        $blog_post->of(false);
        $blog_post->removeStatus('hidden');
        $blog_post->save();
        $blog_post->of(true);
        // set sesion var
        $_SESSION['status'] = "success";
        $_SESSION['note'] = "\"$blog_post->title\" is no longer hidden!";

    }else {
        // Edit Page
        $blog_post->of(false);
        $blog_post->status('hidden');
        $blog_post->save();
        $blog_post->of(true);
        // set sesion var
        $_SESSION['status'] = "warning";
        $_SESSION['note'] = "\"$blog_post->title\" has been hidden!";
    }

    // redirect
    header("Location: {$moduleURL}{$backURL}");
    exit();

}

// Publish/Unpublish
if(isset($_GET['action']) && $_GET['action'] == 'publish') {

    $backURL = $_GET['back_url'];

    $itemID = $_GET['id'];
    $blog_post = wire('pages')->get("id=$itemID");

    if($blog_post->isUnpublished()) {
        // Edit Page
        $blog_post->of(false);
        $blog_post->removeStatus('unpublished');
        $blog_post->save();
        $blog_post->of(true);
        // set sesion var
        $_SESSION['status'] = "success";
        $_SESSION['note'] = "\"$blog_post->title\" is now published!";

    }else {
        // Edit Page
        $blog_post->of(false);
        $blog_post->status('unpublished');
        $blog_post->save();
        $blog_post->of(true);
        // set sesion var
        $_SESSION['status'] = "warning";
        $_SESSION['note'] = "\"$blog_post->title\" has been unpublished!";
    }

    // redirect
    header("Location: {$moduleURL}{$backURL}");
    exit();

}

// Clone
if(isset($_GET['action']) && $_GET['action'] == 'clone') {

    $backURL = $_GET['back_url'];

    $itemID = $_GET['id'];
    $blog_post = wire('pages')->get("id=$itemID");

    $blog_post = $this->pages->clone($blog_post);

    $_SESSION['status'] = "success";
    $_SESSION['note'] = " You just cloned \"$blog_post->title\" page!";

    // redirect
    header("Location: {$moduleURL}{$backURL}");
    exit();

}


if(isset($_SESSION['note'])) {
    //$alert .= "<div class='ivm-alert ivm-alert-{$_SESSION['status']}'><i class='fa fa-info'></i> {$_SESSION['note']}</div>";
    $alert = "<script>";
    $alert .= "$(document).ready(function() {";
    $alert .= "UIkit.notification({";
    $alert .= "message: '{$_SESSION['note']}',";
    $alert .= "status: '{$_SESSION['status']}',";
    $alert .= "pos: 'top-center',";
    $alert .= "timeout: 3000";
    $alert .= "});";
    $alert .= "});";
    $alert .= "</script>";
    unset($_SESSION['status']);
    unset($_SESSION['note']);
}
<?php
/**
 *  Module Blueprint
 *
 *  @author Ivan Milincic <lokomotivan@gmail.com>
 *  @copyright 2017 Ivan Milincic
 *
 *
*/

class PwthemesBlueprint extends Process {

	const MODULE_FOLDER 		= 'kreativan-blueprint';
	const PAGE_NAME   			= 'blueprint';
	const PAGE_TITLE  			= 'Blueprint';
	const MODULE_URL    		= 'blueprint/';
	const TEMPLATE_NAME 		= 'blueprint';

	public static function getModuleInfo() {

		return array(
				'title' => 'Blueprint',
				'summary' => 'Blueprint Module with vustom UI',
				'version' => 100,
				'author' => 'Ivan Milincic',
				'icon' => 'calendar',
				'href' => 'http://modules.processwire.com/',
				// page that you want created to execute this module
				'page' => array(
					'name' => self::PAGE_NAME,
					'parent' => "/admin/",
					'title' => self::PAGE_TITLE,
					'sort' => "9",
				),
				'singular' => true, // need for Redirect
            	'autoload' => true, // need for Redirect
				'permission' => 'page-view',
			);
	}
  
    /**
     *	This is custom page inside module
     *	link to this page is adminURL/my_module/example
     */
    public function ___executeExample() {

        return "O Yeah this is awesome";

    }

    public function init() {
    parent::init(); // always remember to call the parent init

		/*
		 *	If we are creating page from custom admin page set $_SESSION['new_back'] variable
		 *  that will redirect us back to custom admin page.
		 *	Remember to add   &new_back=1   to the new page link.
		 */
		if(isset($_GET["new_back"]) && $_GET["new_back"] != '') {
			$_SESSION['new_back'] = $_GET["new_back"];
		}

		/**
		 *	Redirect After creating a new page from custom UI.
		 *	If we are creating page from custom admin page, redirect us back there, if not, go back to page tree.
		 */
		if(isset($_SESSION['new_back'])) {
			wire()->addHookBefore("ProcessPageEdit::processSaveRedirect", function(HookEvent $event) {

			    $url = $event->arguments(0);
			    $page = $event->object->getPage();

				// Save+Exit & save+publish Redirect
			    if($page->template == self::TEMPLATE_NAME && ($this->input->post('submit_save') == 'exit' || $this->input->post('submit_publish') == 'exit') ) {
					$goto = wire('config')->urls->admin . self::MODULE_URL;
					$event->arguments = array($goto);
			    }

			});
		}

    }

    /**
     * This function is executed when a page with your Process assigned is accessed.
     */
    public function ___execute() {

		// Vars
		$adminURL 			= wire('config')->urls->admin;
		$moduleURL 			= wire('config')->urls->admin . self::MODULE_URL;

		// Unset back_url.
		if(isset($_SESSION['back_url'])) {
			unset($_SESSION['back_url']);
		}
		// Unset new_back.
		if(isset($_SESSION['new_back'])) {
			unset($_SESSION['new_back']);
		}

		// Unset filters.
		if(isset($_SESSION['filters'])) {
			unset($_SESSION['filters']);
		}

		/**
		 * Save all current GET variables to $_SESSION['filters'],
		 * In redirect function we add GET vars to the redirect link 
		 * so after redirect we go back where we left off will all search filters applied
		 * 
		 */
		$filters = "";
		foreach($_GET as $key => $val) {
			$fitlers .= "&$key=$val";
		}
		$_SESSION['filters'] = $fitlers;

		/**
		 *	Get current url and it's last url segment so we can go back to the same page.
		 *  We are looking for pagination related segments like "page2, page3...".
		 *	We will be passing this segment string as a GET variable via page edit link.
		 *	Just add &back_url={$url_segment} to the edit links
		 *
		*/
		$currentURL = $_SERVER['REQUEST_URI'];
		$url_segment = explode('/', $currentURL);
		$url_segment = $url_segment[sizeof($url_segment)-1];

		/**
		 *	This is main module page markup include
		 *	All admin markup related files are locationed in "/admin folder",
		*/
		include_once("./markup/_alert.php");
		include_once("./markup/markup.php");

		// Display full markup
		return $markup;

	}
    
    /**
	 *	Page Edit.
	 *	What's going on when you edit some module related page.
     *
	 */
	public function executeEdit() {

		// Vars
		$adminURL 		= wire('config')->urls->admin;
		$moduleURL 		= wire('config')->urls->admin . self::MODULE_URL;

		// GET back_url and store it in a session
		if(isset($_GET["back_url"]) && $_GET["back_url"] != '') {
		   	$_SESSION['back_url'] = $_GET["back_url"];
		}

		// redirect after save + exit
		if( ($this->input->post('submit_save') == 'exit') || ($this->input->post('submit_publish') == 'exit')) {
			$this->input->post->submit_save = 1;
			$this->addHookAfter("Pages::saved", $this, "redirect");
		}

	    /**
		 *	Change the breadcrumbs to be something related to our custom module instead of Admin > Example > etc
		 *	We are also checking for "back_url" to include it in the link, we want to go back to where we left of, eg: example/page2
		 *	Also adds $_SESSION['filters'] get vars to the link
		 *
		 */
		if(isset($_SESSION['back_url']) && $_SESSION['back_url'] != '') {
			$this->fuel->breadcrumbs->add(new Breadcrumb($moduleURL.$_SESSION['back_url'].$_SESSION['filters'], self::PAGE_TITLE));
		}else {
			$this->fuel->breadcrumbs->add(new Breadcrumb($moduleURL.$_SESSION['filters'], self::PAGE_TITLE));
		}

		// render page edit
	    $processEdit = $this->modules->get('ProcessPageEdit');
	    return $processEdit->execute();

	}
    
    /**
	 *	This is out main redirect function.
	 *	We are using this function to redirect back to previews page on save+exit and save+publish actions
	 *
	 */
	public function redirect() {

		// Vars
		$adminURL 		= wire('config')->urls->admin;
		$moduleURL 		= wire('config')->urls->admin.self::MODULE_URL;

		// set redirect link
		$goto = $moduleURL;

		/**
		 *	Check if "back_url" is set to include it to redirect link.
		 *	When we save+exit page we want to go back where we left of eg: example/page2
		 */
		if(isset($_SESSION['back_url']) && $_SESSION['back_url'] != '') {
			$goto .= $_SESSION['back_url'];
		}

		if(isset($_SESSION['filters']) && $_SESSION['filters'] != '') {
			$goto .= $_SESSION['filters'];
		}

		// redirect
		wire("session")->redirect($goto);

	}
    
    /**
	 * Called only when your module is installed
	 *
	 */
	public function ___install() {
		parent::___install(); // always remember to call parent method

		/**
		 *	Everything we need to install is located in "./install" folder,
		 *	and all parts are included in this main install.php file
		 */
		include_once('./install/install.php');

		/**
		 *	Page-reference field restrictions.
		 *	Has to be done after creating needed templates.
		 */
		$f_edit = wire('fields')->get('example_field'); // field name
		$f_edit->parent_id = wire('pages')->get('template=some_parent_template')->id; // set parent template of pages we want
		$f_edit->template_id = wire('templates')->get('some_template')->id; // set template of the pages we want
		$f_edit->save();

		/**
		 *	Here we copy all template files and folder requierd for front-end.
		 *	All files and folders are located in "./front-end" folder,
		 *	so we copy everything from there to "site/templates/"
		 */
		/*********************************************************************************/
		$path_from = $this->config->paths->siteModules.$this->className().'/front-end/';
		$path_to = $this->config->paths->templates;
		$this->files->copy($path_from.$file, $path_to);
		/*********************************************************************************/

		/**
		 *	Set admin page icon for reno template
		 */
		$old_data = wire('modules')->getModuleConfigData('AdminThemeReno');
		$new_data = array('main-menu' => 'fa-sitemap');
		$data = array_merge($old_data, $new_data);
		$module = 'AdminThemeReno';
		wire('modules')->saveModuleConfigData($module, $data);

	}
    
    /**
	 * Called only when your module is uninstalled
	 *
	 */
	public function ___uninstall() {

		/**
		 *	Everything we need to uninstall: fields, fieldgroups, templates, pages...
		 *	are locaten and included in "./install/uninstall.php" file.
		 *	Note that we are deleting everything we installed, all the work done with this module will be gone,
		 *	so user should be worned before taking this action.
		 *
		 */
		include_once('./install/uninstall.php');

		$admin = wire("pages")->get('id=2')->name;
		$admin_page_to_del = "/{$admin}/".self::MODULE_URL;

		// Delete main module page
		$ap_del = wire('pages')->get($admin_page_to_del);
		if($ap_del && $ap_del != '') {
			wire('pages')->delete($ap_del, true);
		}


		/**
		 *	Deliting all the fiels related to front-end.
		 *	This will delete all the front-end template files and folders we copied during install process.
		 *
		 */
		/*********************************************************************************/
			$subfolder = $this->config->paths->templates . "subfolder_name"; // subfodler in "/site/templates/subfolder_name"
			$temp_path = $this->config->paths->templates;
			//
			$del_files = array('example1.php', 'example2.php', 'example3.php', 'example4.php'); // files in "/site/templates/" root to be deleted
			foreach($del_files as $del_file) {
				if(file_exists($temp_path.$del_file)) {
					unlink($temp_path.$del_file);
				}
			}
			// delete subfolder
			function Delete($subfolder) {
			    if (is_dir($subfolder) === true) {
			        $files = array_diff(scandir($subfolder), array('.', '..'));
			        foreach ($files as $file) {
			            Delete(realpath($subfolder) . '/' . $file);
			        }
			        return rmdir($subfolder);
				}elseif (is_file($subfolder) === true) {
			        return unlink($subfolder);
			    }
			    return false;
			}
			echo Delete($subfolder);
		/*********************************************************************************/

	}
    
}    
<?php
/**
 *  Module Blueprint Config
 *
 *  @author Ivan Milincic <lokomotivan@gmail.com>
 *  @copyright 2017 Ivan Milincic
 *
 *
*/

class PwthemesBlueprintConfig extends ModuleConfig {

	public function __construct() {

		$this->add(array(

			/**
			 *	get all available templates
			 *  and create templates options array
			*/
			$templatesArr = array();
			foreach($this->templates as $tmp) {
				$templatesArr["$tmp"] = $tmp->name;
			}

			// Templates
			array(
				'name' => 'templates_option',
				'type' => 'AsmSelect',
				'label' => "Templates",
				'options' => $templatesArr,
				'value' => '0', // default value
				'optionColumns' => 1,
				'columnWidth' => '100%',
				'collapsed' => '2',
			),

			// Text
			array(
				'name' => 'limit',
				'type' => 'text',
				'label' => $this->_('Number of post per page on front end.'),
				'value' => '10',
				'columnWidth' => '100%',
			),

			// options
			array(
				'name' => 'enable_comments',
				'type' => 'radios',
				'label' => $this->_('Enable Comments'),
				'options' => array(
					// options array of value => label
					'1' => $this->_('Yes'),
					'no' => $this->_('No'),
					),
				'value' => '1', // default value
				'optionColumns' => 1,
				'columnWidth' => '100%',
			),

		));
	}
}