Tag Archive for 'PHP CMS'

Sandlight CMS IV: Dynamic Responsive Web PHPages

responsiveAt this point in the Sandlight CMS development process, two design patterns have been employed: 1) Chain of Responsibility as a device checker, and 2) Abstract Factory for making different parts for different devices. As usual, I’ve been posting the results so far on the Sandlight Productions, LLC website. The site itself is the example used in this series. This post is Part IV of the Sandlight CMS series, and if you have not been following the series you can review what has been done so far beginning with Part I.

At this stage, the project is ready to use the Abstract Factory to produce the needed parts and put them together into a page. However, before going ahead and have the factory build the parts I’d like to take an intermediate step and just build a dynamic responsive Web page.

The Dynamic Responsive Web PHPage

The easiest way to proceed is to begin with an HTML5 page, encapsulate the page into a PHP object (class) and add methods. The reason for this step is that the Web site, in addition to being responsive, needs to be dynamic. This means that it needs a way for the administrator to add changes, and in order for this to transpire, the dynamic portion of the page has to include variables in the place of static text, graphics and/or video. Figure 1 shows the general layout envisioned for the page:

Figure 1: Dynamic Responsive Web Page

Figure 1: Dynamic Responsive Web Page

Everything about the page must be responsive, but some parts are static and some are dynamic. In the two-column outline in Figure 1, the entire left column is static yet it must be responsive to different devices. In Parts I to III of this series, the pages have been responsive. The next step in making them both responsive and dynamic is to create parts of the page that will be dynamic since they are already set up to be responsive. Before continuing, click the Play button to see the progress so far and the Download button for all of the source code and accompanying files:
PlayDownload

Using PHP alone, creating a dynamic page is simple. Just place PHP variables where content goes. This is true for both the pages formatted by CSS3 and jQuery. Importantly, though, all of the Web pages should be encapsulated into PHP classes, using heredoc string variables as has been shown in previous installment of this series.

QR Code: The New Responsive Component

Quick Response Code (QR) is a new necessity for Web sites doing business on the Web and for just about every other kind of site that wants to increase its exposure. Basically, using a QR Code reader in a mobile device (phone or tablet) automatically brings up the link coded in the QR image (a square with some squiggly block images.) That beats trying to to thumb in a URL on a tiny phone keyboard. The following two can be downloaded free (at the time of this writing.):

sandlightqrcodeI’m pretty certain that other smart phones have QR readers; so if you have something other than an iOS or Android operating system on your mobile device, an Internet search for “QR Scanner” will probably be able to locate one for you.

sandlightOnce you have a QR scanner, you need a coded image, such as the one to your right. Go ahead and scan it to see what happens. It should take you to the Sandlight Productions, LLC home page build on this CMS (updated.) On it you will find several more QR codes for links to sites related to Sandlight. You can get the coded images online at different sites. One site allows you to include your logo and choice of colors is QRCode Monkey. The QR code image in green to your left with the Sandlight logo in the middle does exactly the same thing as the black one. So, if you’d like your QR Code images to keep your graphic designer happy, consider the visual options beyond the default. Figure 2 shows a page being scanned with an iPhone (left) and the linked page in the iPhone (right).

Figure 2: Scanned QR URL uploaded in mobile phone.

Figure 2: Scanned QR URL uploaded in mobile phone.

Adding QR codes to your site (or your client’s site) is very easy, and you should definitely include it in your dynamic responsive CMS. Let’s now see how the dynamic responsive two-column page is created:
Continue reading ‘Sandlight CMS IV: Dynamic Responsive Web PHPages’

Share

Sandlight CMS III: PHP Abstract Factory

abfacNote: This is the third in a series for developing a CMS for Sandlight Productions. Drop by the Sandlight site to see the progress so far, and be sure to check your country’s flag count!

Now that the CMS has a filter for different devices, it now needs a pattern to take care of those devices and different types of content that they will display. Previous posts on this blog used the Bridge pattern and the Factory Method pattern. However, another pattern might be more useful for all of the different things that a Content Management System (CMS) might do. A review of the series of posts on this blog for how to select a design pattern, shows the different criteria to consider. The CMS has to create different elements of a Web page for different devices and that fact must be the focal point of the consideration. The section head for Creational Patterns in Learning PHP Design Patterns, lists the Abstract Factory pattern as a creational one, but that pattern was not discussed in the book nor on this blog. It would appear to be just what this CMS needs.

The Abstract Factory Design Pattern

The Abstract Factory pattern has features for families of factories and products instead of individual factories as does the Factory Method pattern. In comparing the relatively simple Factory Method pattern with the Abstract Factory, the Abstract Factory has multiple abstract product interfaces with multiple concrete factories for the families of the products.

Figure 1 shows the the Abstract Factory class diagram, and when you look at it, try to focus on the fact that the pattern has two types of interfaces: Factory and Product. So, if you understand the Factory Method pattern, you have a starting point for appreciating the Abstract Factory:

Figure 1: Abstract Factory class diagram

Figure 1: Abstract Factory class diagram

Unlike the Factory Method pattern, the Abstract Factory includes a Client class as an integral part of the pattern. Further, the Client holds an association between both the AbstractFactory (AbsFactory) and the two AbstractProduct classes. So while it shares some of the basic Factory Method characteristics, it is clearly a different pattern than the Factory Method.

Since the Abstract Factory may appear to be daunting, the color-coded the product instantiations (dashed lines) in the file diagram (appearing in the Play window) help show where each concrete factory method calls. Experiment with different combinations of factories (devices) and products (page parts) and look at the diagram so that you can see the path. Phone instantiations are in green, Tablet in red, and Desktop in blue. Experiment with the different single products first, and then click the bottom button to see what different “pages” each device factory displays.

Implementing the Abstract Factory in PHP

To see how this implementation of the Abstract Factory design pattern works, click the Play button. You will see both the interactive Abstract Pattern tester and the of the file diagram of this implementation of the Abstract Factory for the evolving Sandlight CMS. Click the Download button to see all of the files in the diagram. For this particular post, downloading all of the files is more important than usual because there are lots of them, and rather than having listings for all in this write-up, I’ve just selected representative ones.
PlayDownload

In addition to the Abstract Factory file diagram (viewed when you click the Play button), the following quick overview of the participants’ roles and how the CMS implements the Abstract Factory explain how this implementation works:

Client client: Only uses interfaces declared by IAbFactory (interface) and IProducts (abstract classes IHeaderProduct, IImageProduct and ITextProduct.) This means that the Client can only use the classes and methods implemented from those two interface types—factory or products. In other words, it should not directly implement a product (a page element) by directly using a product independent of the factory and product interfaces. Figure 2 illustrates this point:

Figure 2: Client works through Abstract Factory implementations

Figure 2: Client works through Abstract Factory implementations

In going over the other participants below, keep in mind that the Client can only implement concrete implementations of the IAbFactory to request products (page parts for different devices.)

IAbFactory interface: Establishes the methods for the concrete factories.

  • PhoneFactory implements operations to create phone products
  • TabletFactory implements operations to create tablet products
  • DesktopFactory implements operations to create desktop products

IHeaderProduct: abstract class Establishes the method for concrete header products and adds protected property for returning completed product.

  • PhoneHeader defines phone object to be created by the PhoneFactory and
    implements the IHeaderProduct interface
  • TabletHeader defines tablet object to be created by the Tabletactory and
    implements the IHeaderProduct interface
  • DesktopHeader defines desktop object to be created by the DesktopFactory and
    implements the IHeaderProduct interface

IImageProduct: abstract class Establishes the method for concrete image and/or video products and adds protected property for returning completed product.

  • PhoneImage defines phone object to be created by the PhoneFactory and
    implements the IImageProduct interface
  • TabletImage defines tablet object to be created by the Tabletactory and
    implements the IImageProduct interface
  • DesktopImage defines desktop object to be created by the DesktopFactory and
    implements the IImageProduct interface

ITextProduct: abstract class Establishes the method for concrete text products and adds protected property for returning completed product.

  • PhoneText defines phone object to be created by the PhoneFactory and
    implements the ITextProduct interface
  • TabletText defines tablet object to be created by the Tabletactory and
    implements the ITextProduct interface
  • DesktopText defines desktop object to be created by the DesktopFactory and
    implements the ITextProduct interface

Comparing the above outline with the Abstract Factory file diagram (seen when you click the Play button) shows that the Abstract Factory is bound to the idea of a factory implementing a product. The specific classes (products) requested are never directly referenced by the Client; rather it is through a factory. The CMS application requires factories for the different device categories; Phone, Tablet and Desktop. Each factory should be able to build the necessary parts (products) for each device. In this case (and for this example) the products are a Header, Graphic and Text. Each factory can build its own version of the products; so requesting a header, for example, is through a concrete factory, and depending on which concrete factory the clients requests, it builds the appropriate product.
Continue reading ‘Sandlight CMS III: PHP Abstract Factory’

Share

Sandlight CMS II : Mobile First!

mobileFirstI’m not a graphic designer, and so I depend on others for the graphic elements and arrangement of my Web pages. However, I strive to make a site that is clear, easy to understand and useful. My focus is on good user experience (UX) and information design—clear communication with the user. In order to have good UX, you need to know something about Responsive Web Design (RWD), and if you don’t, check out the RWD link. Further, if you are unfamiliar with the approaches to RWD, I’m sold on the Mobile First approach, but possibly for different reasons than designers. Let me explain.

In designing my own site, my focus is on content categories, ease of maintenance, which includes updates and changes, and device flexibility. So I have to keep all of those in mind. I want PHP to handle regular updates by using content from a MySql database (the Content Management of CMS), and I need it to work on different devices. By tackling mobile first, I have to create a diamond-tipped focus on exactly what I want the user to view because even with the new “Phablets,” I’m not dealing with a lot of screen real estate. Currently, my old working mobile phone has a CSS resolution of 320 x 480, and my Phablet is 414 x 736. That’s less that 100 units different. (By CSS resolution, I’m referring to what CSS reads as far as screen width is concerned. See this table.)

Choosing the Devices

In an another sniffer program using a Chain of Responsibility (CoR) design pattern and a PHP user agent ($_SERVER['HTTP_USER_AGENT']) posted on this blog, the sniffer detected the user agent and then found the handler responsible for that agent. Now that user agents have been replaced by CSS screen width (as determined by a JavaScript function) for determining the device, we can use the same CoR pattern making the necessary changes. However, instead of getting real pages, we can use stand-ins that only have the roughest page content. All of the content will be encapsulated into PHP classes using heredoc strings. Near-future posts cover the mechanics of working out the MySql to provide dynamic content for the pages, along with other details necessary for the CMS. For now, though, the dummy pages will only contain enough material to demonstrate that each is appropriate for the selected device. Use the buttons below to see the current state of the CMS and download the files for this portion:
PlayDownload

Note that all devices can now access the Flag Counter. Where is your country on the Flag Counter? (See the note about the Flag Counter at the end of this post.)

Back to the Chain of Responsibility Pattern (CoR)

The CoR pattern is handy because it’s easy to update and change. For example, suppose that having three device categories (e.g., phone, tablets and desktops) proves to be inadequate and you want to add two more; one for laptops and another for phablets. It’s a simple matter to add to the chain and add device classes to handle the new devices. Figure 1 shows the first design pattern to be used in the CMS:

Figure 1: Chain of Responsibility Implementation

Figure 1: Chain of Responsibility Implementation

In Part I of this series, you can see how the device width and height is determined using a JavaScript closure (object) to pass the information to HTML and on to PHP. Since we only need to find the width, the JavaScript code has been slightly altered and placed in a separate file (deviceCatcher.js) in case it needs to be reused.

?View Code JAVASCRIPT
//deviceCatcher.js
function getWide()
{
	var wide = screen.width;
	return function()
	{
		return wide;
	}
}
var w = getWide();
//Send data to PHP class, CoRClient.php	
var lambdaPass= function() {window.location.href = "CoRClient.php?hor=" + w();};

The HTML file simply calls the closure function which passes the values to PHP:

<html>
	<head>
		<title>Device Catcher</title>
		<script src="deviceCatcher.js" type="text/javascript"></script>
	</head>
	<body onload=lambdaPass()>
	</body>
</html>

The HTML file is a trigger to get the ball rolling with the client class (CoRClient).

Starting the Chain

The client pulls the viewing device’s width from the superglobal, and passes it to a PHP variable. Given the variability in the width of device screens, I made the decision to work with three sizes to get started: 1) phone, 2) tablet, and 3) desktop. So, depending on the width, the request would be handled by one of those three device groups. I used the following cutoff sizes:

  1. Phone: >= 480
  2. Tablet: >=481 and < 900
  3. Desktop: >= 900

I used this table as a guide, but cutoff points can be anything you want.

Getting the width from the superglobal is easy enough using a static variable:

self::$wide=$_GET['hor'];

The, using the cutoffs, the program needs to generate three strings, phone, tablet, and desktop to send to the Request class that stores the appropriate string. The most obvious way is to use conditional statements (if or switch) to generate the correct string for Request. For example an imperative algorithm such as the following would do the trick:

if(self::$wide < = 480)
{
	return "phone";
}
elseif (self::$wide >= 900)
{
	return "desktop";
}
else
{
	return "tablet";
}

However, a functional program would be more compact, and like the JavaScript closure used in Part I, it would be an “object.” Transformed into a functional closure, the operation would look like the following:

$beta = self::$wide >= 900 ? 'desktop' : 'tablet';
$lambda = function($x) use ($beta) {
	$alpha =  $x < = 480 ? 'phone' : $beta;
	return $alpha;};

Using ternary operations ?: , $alpha and $beta both have function-like qualities. for example, $beta could have been written as a function beta() as shown in Figure 2:

Figure 2: "Functional" variables

Figure 2: “Functional” variables

As you can see in Figure 2, $beta provides the same functionality as beta(), and $beta can be used as a reference in the $lambda function along with $alpha in a PHP closure. (For some reason, when $beta is assigned an anonymous function, I was unable to get it to be added as a closure in the $lambda anonymous function.)
Continue reading ‘Sandlight CMS II : Mobile First!’

Share

PHP Bridge Pattern CMS

bridgeCMSA Flexible CMS

The previous post on the PHP Bridge Design pattern shows how a Bridge pattern has two connected but independent interfaces to make design flexibility for different online devices. This post explores how that same flexibility extends to making a Content Management System (CMS). Most of the Bridge participants in the design are unchanged or only slightly changed.

The major change in the Bridge design pattern actually makes it more in line with the original intention of the Bridge. The RefinedAbstraction participant (RefinedPage) no longer includes concrete content for the page. Instead, it provides the parameters for a client to add the content. This change adds flexibility and gives the developer more options than the original StandardPage class.

Two UIs and Multiple Clients

In order to make a decent CMS, you need to have at least two UIs:

  1. An Administrative UI for previewing and adding new content
  2. A User UI for viewing but not changing content

In creating the Administrative UI (HTML5/PHP/JavaScript), I had to use two PHP clients. One client is to preview the new data entered by the admin and the other client is to store the new data (after previewing and possibly editing it). Figure I provides a general overview of the UIs and the Clients that will use the Bridge pattern for a CMS:

Figure 1: User Interfaces and Clients

Figure 1: User Interfaces and Clients

The Administrative UI (BridgeCMSAdmin.html) uses the BridgeCMSAdminClient class for displaying different content and the StoreDataClient class for storing the information in a JSON file. An important condition to remember is that when using JSON files, you need to make their permissions available for reading and writing. (See the Memento II post and the special mini-post on setting permissions on Raspberry Pi systems.) Thus, the need for two clients; one for previewing new material and another for storing it in a JSON file. A lot of files are involved in this CMS; so take a look at the two different UIs and download the files for everything:
PlayPlayAdminDownload

To use the Administrator Module, follow these steps in the listed order:

  1. Type in Header data, select a graphic from the drop down menu, and then type in text for the body.
  2. Click a Desktop, Tablet or Phone radio button and then click Preview Page
  3. When you have everything the way you want it, First click Transfer to Storage and next click Store Data
  4. Now click the Play button and see the page you created.

In the admin UI, I used a drop down menu with only three selections for the graphic file since only three were set up. However, it would not be difficult to upload graphics and their file names. (See the post on uploading graphics using the Template Method.)

The UIs and their Clients

The main feature in creating a CMS is the Administrative UI. It calls two different clients for dealing with previews and persistent data storage. Unless you’re planning on a fairly long body text entry, the JSON file works fine. Look at the code below, and you can see that one of the issues is that the data that is entered for the preview must be transferred to a different form. It transferring the data is a simple task with a little JavaScript. The following script is all it takes:

?View Code JAVASCRIPT
function transferData(formNow)
{
    formNow.header.value = bridgeWork.header.value;
    formNow.graphic.value = bridgeWork.graphic.value;
    formNow.bodytext.value = bridgeWork.bodytext.value;
}

Stored in an external JS file, it was used only when the data was going to be stored; however, before storing it, it had to be transferred from the bridgeWork form to the dataStore form.

< !DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="cmsbridge.css"/>
    <script src="formXfer.js"> </script>
    <title>CMS Admin Bridge</title>
</head>
<body>
    <h2>Enter Update Data</h2>
    <form method="post" name="bridgeWork" action="BridgeCMSAdminClient.php">
        <input type="text" name="header"/>&nbsp;Header<br />
        <select name="graphic">
            <option>Select Travel Graphic</option>
            <option value="nephpAir.jpg">Air</option>
            <option value="nephpTrain.jpg">Train</option>
            <option value="nephpShip.jpg">Ship</option>
        </select>
        <br />
        Enter the text for the body below:<br />
        <textarea name="bodytext" cols="48" rows="12"></textarea><p></p>
        <h3>Preview New Data</h3>
        <input type="radio" name="device" value="Desktop"/>&nbsp;Desktop<br />
        <input type="radio" name="device" value="Tablet"/>&nbsp;Tablet<br />
        <input type="radio" name="device" value="Phone"/>&nbsp;Phone<p></p>
        <input type="submit" name="deliver" value="Preview Page"/>
    </form>
 
    <h3>Store New Data</h3>
    <form method="post" name="dataStore" action="StoreDataClient.php">
        <input type="hidden" name="header"/>
        <input type="hidden" name="graphic"/>
        <input type="hidden" name="bodytext"/>
        <button type="button" onclick="transferData(dataStore)">Transfer to Storage</button>
        <input type="submit" name="jsonstore" value="Store Data"/>
    </form>
 
</body>
</html>

Then using build-in PHP JSON json_encode() method, the data were placed into an array and stored in the JSON file. This was done using the StoreDataClient class:

< ?php
class StoreDataClient
{
    private static $dataStorage=array();
    private static $jsonFile="content.json";
    //Client stores data
    public static function store()
    {
        if (isset($_POST['jsonstore']))
        {   
            self::setStore();
        }
      file_put_contents(self::$jsonFile,json_encode(self::$dataStorage,JSON_UNESCAPED_UNICODE));
    }
 
    private static function setStore()
    {
        //Pushes data from HTML to array
        array_push(self::$dataStorage,$_POST['header'],$_POST['graphic'],$_POST['bodytext']);
    }
}
StoreDataClient::store();
?>

Just in case you’re wondering why a single PHP client class was not used for both preview and storage, it’s simple:

OOP Principle: Each class should have only a single responsibility.

We don’t want to cram classes; so each responsibility has its own class. (Click below to see the other client and the rest of the CMS.)
Continue reading ‘PHP Bridge Pattern CMS’

Share

PHP CMS Project Part IV: La Petite Blog

cms4Bring in the MySql

At this stage there is still no design pattern in the project. You will see that re-use is starting to creep in, and we’re getting to the point where some decisions can be made about what design pattern would best fit this project. In Part V, you will see how a design pattern pulls everything together and why one is helpful to PHP programming.

In Part III of this series, you saw how external data from text files can be placed into an array and used by the DocHere class to populate a web page. In this installment, the same process shows how this can be done using data from a MySql database.

From Data Input to Web Page Display

The whole point of a CMS is to make updating a web site or blog easy. For the time being, I’m going to treat the web page example as a little blog–La Petite Blog. Figures 1 and 2 show how the data are to be entered and the end result pulled out of a database and displayed in the web page.

Figure 1: HTML form to send data to MySql database

Figure 1: HTML form to send data to MySql database

Figure 1 shows that the same categories of data used throughout the project are still in use. Even the CSS file is the same. The form is a simple HTML5 one. (Click View Code to see listing.)

< !doctype html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="heredoc.css"/>
    <meta charset="UTF-8"/>
    <title>Blogette Data Entry</title>
</head>
<body>
<h1>La Petite Blog</h1>
<h2>&nbsp;Enter data to update your blogette</h2>
<div>
    <form name = "content" action="InsertBlog.php" method="post">
        <input type="text" name="css" value="heredoc.css"/>&nbsp;CSS file
        <input type="text" name="title" />&nbsp;Title
        <input type="text" name="header1" />&nbsp;Header 1
        <input type="text" name="header2" />&nbsp;Header 2
        <textarea rows="5" cols="80" name="body1" >&nbsp;Add body text here</textarea>
        <textarea rows="5" cols="80" name="body2" >&nbsp;Add body text here</textarea>
        <input type="text" name="image1" />&nbsp;Image 1 file name
        <input type="text" name="image2"/>&nbsp;Image 2 file name
        <input type="text" name="caption1" />&nbsp;Caption for Image 1
        <input type="text" name="caption2"/>&nbsp;Caption for Image 2
        <input type="submit" value="Store data"/>
    </form>
</div>
</body>
</html>

The “entry” for the system is the class RetrieveBlog. It is almost identical to the Content class in Part III, and it generates the required results as shown in Figure 2.

Figure 2: Page content from database.

Figure 2: Page content from database.

Getting from the HTML5 data input to the PHP-generated web page takes a bit of doing, and so to get started, download the necessary files:
Download

From Data Input to Web View

The whole point of a CMS is to regularly update a web page easily. By the end of this stage, the only thing you’ll need with an FTP client for is to upload graphics. (Uploading graphic files from a web page using PHP is handled up an upcoming post apart from this series.) For now, though, you will be able to update all text in a web page as well as graphics are have already been placed in an image folder. Here’s what we’ll need:

  1. An HTML form for data entry (see above)
  2. A PHP class to create a MySQL Table to store data
  3. A PHP class to take the data from the HTML form and store it in the MySQL table
  4. A PHP class to retrieve the data from the and make it available to the web page

We’ll start with the table.
Continue reading ‘PHP CMS Project Part IV: La Petite Blog’

Share