Create your first module

Creating a module is very simple:

First of all, you will need to think about the name of your module then create a new folder with the module's name inside the Module folder.

Let's assume that you want to create a blog module, so let's create the Blog folder inside Module folder.

Now we will need the setup for the module so we'll create a Setup.class.php in the new created Blog folder.

The setup file handles the creating tables, permissions, urls, folders for images and anything you need to prepare your module.

First thing you need is to set the namespace for the module (keep in mind that the framework has a PSR-0 autoloader), so you need to set it like this: namespace Module\Blog;

Then we need the following classes: Controller\AdminController to register permissions for managing blog posts, Model\Model to work with the database and Utils\Util for a function that converts posts titles into URLs.

Now we need to define the Setup class that extends the parent class (Module\Setup):

 class Setup extends \Module\Setup {

The constructor for the class needs to register itself using the parent's constructor; after identifying the module's id by the parent's constructor we need to check if the table posts exists, if not we will create it by importing a sql file; then we will need to register a special permission for the module (we will name it Manage blog), add the permission after create to the administrator with the username admin, register the frontend urls and the backend urls  and create the images folder for the module.

The content of Setup.class.php file:

 //PSR-0 namespace
namespace Module\Blog;
//We need AdminController to register permission for managing blog posts
use Controller\AdminController;
//We need Model to work with the database
use Model\Model;
//We need Util class for a function that converts posts titles into URLs
use Utils\Util;

class Setup extends \Module\Setup {
	public function __construct() {
		//We need to construct the parent Setup class to initialize the module ID
		parent::__construct();
		//Start checking for table posts
		$blogTable = new Model('posts');
		//If table `posts` was not found then $blogTable's schema is empty
		if(!count($blogTable->schema)) {
			//We load the sql for creating the tables from the install.sql file inside this directory
			$sql = file_get_contents(dirname(__FILE__) . '/install.sql');
			//Run multi query, because we need to create the tables and alter them with foreign keys if exist
			$blogTable->runMultiQuery($sql);
		}
		//Check if permission exists, if not then it will create
		$permissionName = 'Manage blog';
		$permission = AdminController::registerPermission($permissionName);
		//Get the administrator with username `admin`
		$administrator = new Model('admins');
		$administrator = $administrator->getOneResult('username', 'admin');
		//Add permission to `admin` user
		$admin_permission = new Model('admins_permissions');
		$admin_permission->admin = $administrator->id;
		$admin_permission->permission = $permission->id;
		$admin_permission->create();

		//Register frontend routes
		$this->registerFrontendUrl(array(
			//URL for the page
			'url' => 'blog',
			//Type: 0 - Exact match for url; 1 - Regex match for url
			'type' => 0,
			//Must be logged in: 0 - Visible for guest users; 1 - Visible for logged in users
			'mustBeLoggedIn' => 0,
			//Menu position: 0 - Not shown in menu; 1 - Top menu (default); 2 - Right menu (eg: Login, My account)
			'menu_position' => 1,
			//Menu text: the text used for the link in menu
			'menu_text' => 'Blog',
			//Submenu text: the text used for the link if is a dropdown menu
			'submenu_text' => '',
			//Menu parent: the URL for the parent menu (eg: news, if we want to show the blog link under the News menu)
			'menu_parent' => '',
			//Menu order: the order of the link inside menu
			'menu_order' => 3
		));

		$this->registerFrontendUrl(array(
			//Regex for matching URLs
			'url' => '^blog\/page\-[0-9+]\/?$',
			//Type 1, because we regex match the url
			'type' => 1,
			//Menu position 0, because we don't want to show this url in the menu
			'menu_position' => 0
		));

		//Now we need to re-register all the urls for the posts if there are any
		$posts = new Model('posts');
		$posts = $posts->get();
		foreach($posts AS $post) $this->registerFrontendUrl(array(
			//URL for the page based by post title
			'url' => 'blog/' . Util::getUrlFromString($post->title) . '.html',
			//Type 0, because we match the url with the title
			'type' => 0,
			//Menu position 0, because we don't want to show every post url in the menu
			'menu_position' => 0
		));
		//Register administration page
		$this->registerBackendUrl(array(
			//Permission name for accessing the page
			'permission' => $permissionName,
			//URL for administration page (this will be translated into admin/posts)
			'url' => 'posts',
			//Menu text for administration nav
			'menu_text' => 'Posts',
			//Icon name (from FontAwesome; check http://fontawesome.io/icons/)
			'menu_class' => 'text-width',
			//Menu parent: the URL for the parent menu (eg: pages, if we want to show the posts link under the Pages menu)
			'menu_parent' => ''
		));

		//Create the img/posts folder if not exists so we can store the posts images
		$postsImg = _APP_DIR_ . 'img/posts/';
		if(!file_exists($postsImg)) mkdir($postsImg);
		return true;
	}
}