Now we will need the output controller.

The class is Page, so we need to create a Page.class.php file in the module directory and set the PSR-0 namespace.

To return a page we need to return an object with the following properties:

  • title (the content of the title tag)
  • description (the content of the meta description tag)
  • js (array of javascript files)
  • css (array of stylesheet files)
  • content (html content)
  • ogimage (optional; the url of the Open Graph image, if we need other than the application logo; usually for blog or news pages when we have articles with their own main images)

The content of Page.class.php file

//PSR-0 namespace
namespace Module\Blog;
use Model\Model;
use Utils\Util;

class Page {
	private $postsPerPage = 12;
	public function output() {
		/*
		 * Get the current URL
		 * We need to know if the url is "blog" so that we will output the latest n posts per page (n is the postsPerPage value),
		 * 								 "blog/page-x" so that we will output the n posts for that x number page
		 *								 or the url matches a post title
		 */
		$currentUrl = Util::getCurrentUrl();
		//This is the object we use for output
		$page = new \stdClass();
		//Set the default page title, description and H1
		$page->title = _APP_NAME_ . ' | ' . __('Blog');
		$page->description = _APP_NAME_ . ' | ' . __('Blog');
		$page->h1 = __('Blog');
		//No content in the page yet, because we still don't know what we need to output
		$page->content = '';
		//No javascripts yet
		$page->js = array();
		//No stylesheets yet
		$page->css = array();
		//Construct the model, because any page we need to show we will need the model
		$posts = new Model('posts');
		//If current user URL is "blog" or the URL match blog/page-x then we will output a list of n posts (n is the postsPerPage value)
		if($currentUrl == 'blog' || preg_match('/blog\/page\-[\d+]/', $currentUrl)) {
			//Only show the posts that have status 1, meaning they are published and not hidden
			$posts->status = 1;
			//Order the posts by their update date
			$posts->order('date_updated DESC');
			//Count the total visible posts
			$totalPosts = $posts->countItems();
			//Check if URL has "page-x" in it, if so then take the page no, if not then the pageno is 1, so we will ouptut the latest n posts
			$pageno = preg_match('/posts\/page\-(\d+)/', $currentUrl, $matches)?$matches[1]:1;
			//We limit the results from we request from the database based by the page no and the no of posts per page
			$limit = (($pageno - 1) * $this->postsPerPage) . ', ' . $this->postsPerPage;
			$posts->limit($limit);
			//Get the posts inside the $posts variable
			$posts = $posts->get();
			//Start the page content
			$page->content = /** @lang text */
				'<div class="container-fluid">
			<div class="row">
				<div class="col-lg-12 text-center">
					<h1 class="title">' . __($page->h1) . '</h1>
				</div>
			</div>
		</div>
		<div class="container" id="posts">' . PHP_EOL;
			foreach($posts AS $index => $post) {
				//Check if post has an image, if not then use the application logo instead
				if(empty(trim($post->image))) {
					$img = _FOLDER_URL_ . 'img/' . _LOGO_;
					$spanimgc = ' noimg';
				}
				else {
					//If post has image then show it's thumbnail
					$img = _FOLDER_URL_ . 'img/posts/' . str_replace('.jpg', '-360x220.jpg', rawurlencode($post->image));
					$spanimgc = '';
				}
				//Build the post URL
				$href = _FOLDER_URL_ . 'blog/' . Util::getUrlFromString($post->title) . '.html';
				//If post's content has more than 200 characters then show only the first 200 characters succeeded by "..."
				if(strlen($post->content) > 200) {
					$pos = strpos($post->content, ' ', 200);
					$storyText = substr(strip_tags($post->content), 0, $pos) . '...';
				}
				//If post's content has maximum 200 characters then show the full content
				else $storyText = $post->content;
				//We group posts into a grid system with 3 columns; for every 3n post start a new row ($index starts from 0, so we start the row at 3x: $index = 0: 0 % 3 == 0 (row with posts with indexes 0, 1, 2),  $index = 3: 3 % 3 == 0 (row with posts 3, 4, 5) etc.
				if($index % 3 == 0) $page->content .= '				<div class="row">';
				//Build the post by the next template
				$page->content .= '<article class="col-lg-4">
						<header>
							<h2>
								<a href="' . $href. '" title="' . htmlentities($post->title) . '">
									<span class="imgstory' . $spanimgc . '">
										<img src="' . $img . '" alt="' . htmlentities($post->title) . '" />
									</span>
									' . $post->title . '
								</a>
							</h2>
							<p><time datetime="' . $post->date_updated . '">' . date('d.m.Y', strtotime($post->date_updated)) . '</time></p><br />
						</header>
						<div class="content">
							' . $storyText . '
						</div>
						<a href="' . $href. '" class="readmore">&gt;&gt; ' . __('read more') . '</a>
					</article>' . PHP_EOL;
				//We need to close the rows after the 3n post ($index starts from 0, so we close at 3x - 1: after posts with indexes 2, 5, 8 etc) (*)
				if($index % 3 == 2) $page->content .= '				</div>' . PHP_EOL;
			}
			//After we build the posts content we need to check if we have an opened row by counting the posts; if count of posts % 3 > 0 then we didn't closed the last row (see (*) mark above)
			if(count($posts) % 3 != 0) $page->content .= '</div>';
			//If we have more visible posts in the database than the posts per page then build the pagination system
			if($totalPosts > $this->postsPerPage) {
				//Build the back page no button
				$butBack = ($pageno > 1)?'<li class="previous"><a href="' . _FOLDER_URL_ . 'blog/page-' . ($pageno - 1) . '">' . __('Newer') . ' <span aria-hidden="true">&larr;</span></a></li>' . PHP_EOL:'';
				//Build the forward page no button
				$butForward = ($pageno < ceil($totalPosts / $this->postsPerPage))?'<li class="next"><a href="' . _FOLDER_URL_ . 'blog/page-' . ($pageno + 1) . '">' . __('Older') . ' <span aria-hidden="true">&rarr;</span></a></li>' . PHP_EOL:'';
				$page->content .= '<nav>
			<ul class="pager">
				' . $butBack . $butForward . '
			</ul>
		</nav>' . PHP_EOL;
			}
			//Close the "#posts" container
			$page->content .= '</div>' . PHP_EOL;
		}
		//If current user URL is not "blog" and doesn't match "blog/page-x" then we will search the post with the title like the url
		else {
			//Strip the "blog/" and ".html" strings from the current URL to get only the title of the post
			$title = str_replace(array('blog/', '.html'), '', $currentUrl);
			//Search the post by the title
			$posts->title = array($title, 'LIKE');
			$posts = $posts->get();
			//We found the post because we have >= 0 posts with that title
			if(count($posts)) {
				//Take the first post from the array (basically we should have only one post in this array)
				$post = $posts[0];
				//Set the page title
				$page->title = $post->title;
				//Set the page meta description
				$page->description = $post->description;
				//Set the page H1
				$page->h1 = $post->title;
				//If post doesn't have an image then show the logo instead
				if(empty(trim($post->image))) $image = "<img src='" .  _FOLDER_URL_ . "img/" . _LOGO_ . "' id='imgstory' />";
				else {
					$image = "<img src='" .  _FOLDER_URL_ . "img/posts/" . rawurlencode($post->image) . "' id='imgstory' />";
					//If post has image then set page meta open graph image
					$page->ogimage = _ADDRESS_ . 'img/posts/' . str_replace('.jpg', '-720x220.jpg', rawurlencode($post->image));
				}
				//Build the output
				$page->content = $image . '
		<article id="content" class="container marginbot40">
			<header>
				<h1 class="text-center">' . $post->title . '</h1>
				<time datetime="' . $post->date_updated . '">' . date('d.m.Y', strtotime($post->date_updated)) . '</time>
			</header><br />
			<div class="content">
				' . $post->content . '
			</div>
		</article>' . PHP_EOL;
			}
			//If post isn't found redirect to homepage
			else header('Location: ' . _FOLDER_URL_);
		}
		//Return the $page object we just built
		return $page;
	}
}