Shift8 Creative Graphic Design and Website Development

lithium library

Getting Started with Minerva

Posted by Tom on Tue, Jul 19 2011 08:18:00

Minerva was only ever a few ideas I threw around. However, I noticed people were following it. So I wanted to write a short blog post to help people get started with it. This would allow you to see how it works. By no means should you attempt to use this for a production site. I mean, you could...But, I'm telling you don't. The reason is because I don't want you to be disappointed when something doesn't work the way you'd expect or when you run into a problem that you can't figure out. Further, there's really no documention. Lots of comments within the code...But no documentation.

That said. I would absolutely love for others to get involved and fork the CMS. I would love to hear ideas and feedback.

First, the requirements... You need to be running PHP 5.3+ and using MongoDB. I know some of you would love to use MySQL or some other database, but due to the schemaless nature of MongoDB, Minerva requires it. Sorry. You'll also need a few various libraries from the community. Don't worry, we'll go through those below. Personally, I'm ok with these requirements because I don't want to re-invent the wheel. There's plenty of good CMS' out there that use MySQL and older versions of PHP. It's not my intention to re-invent the wheel.

So, Minerva works as plugin that can sit on top of any of your Lithium apps. With a working copy of Lithium, clone Minerva to your app/libraries folder. In fact, you may want to use git submodules. So really, you'd want to run something like (you may need the -f flag to do this by the way):

git submodule add git@github.com:tmaiaroto/minerva.git app/libraries/minerva

Then do the same for li3_access and li3_flash_message.

git submodule add git@github.com:tmaiaroto/li3_access.git app/libraries/li3_access
git submodule add code@dev.lithify.me:li3_flash_message.git app/libraries/li3_flash_message

After that, you would run two more submodule commands in order to get the files you need (note if you cloned Lithium from github, your lithium library directory should also be a submodule so you'd need to do this for that as well):

git submodule init
git submodule update 

If you would like Facebook support (the ability to login to the CMS with your Facebook user) then you'll also need the li3_facebook library.

git submodule add git@github.com:tmaiaroto/li3_facebook.git app/libraries/li3_facebook

Note: With the li3_facebook library, there is a submodule for the Facebook SDK within the library. So you will need to run a git submodule init and update within app/libraries/li3_facebook in order to retrieve it.

That's it. All the files will be ready to go. Of course, now you need to add the libraries within your app/config/bootstrap/libraries.php file.

Minerva is designed so that you don't need to touch any of its files that are cloned from the repository. You can pass your config options within your own libraries.php file when you call Libraries::add(). The order in which you add these libraries is going to matter a little bit. You need to have li3_access loaded before Minerva. This will work:

Libraries::add('li3_access');
Libraries::add('li3_flash_message');
Libraries::add('minerva');

That's basically it. Note, if using Facebook integration you will not need to add the li3_facebook library since the minerva library will do that for you. However, you will need to specify values for 'appId' and 'secret' keys in the minerva library configuration under a 'facebook' key. ie. Libraries::add('minerva', array('facebook' => array('appId' => 123, 'secret' => 123))); Some other handy configuration keys include, 'connections' which is an array with 'production' and 'development' each normal connection settings arrays. Also a 'show_errors' and 'development_errors' key both with boolean values. More on this later.

Now you can go to yoursite.com/minerva. Actually, I use minerva.local, so I'll reference that from now on. Just replace that with whatever domain name you have setup. You'll see the welcome page. It has some copy, some of the instructions are actually dated and wrong. It will tell you that you can edit files within the Minerva library in order to change templates...I am changing that to add another template path which would be under your main app directory. Again, this is so you don't need to touch any files within the minerva library. No git ignore, etc. 

You likely want to see the backend though. You'll need a user account to do that. The first user account will become admin. No other users registering after that will have an admin role, so don't worry. I do plan to create an intstaller in the future. However, go to: http://minerva.local/minerva/users/register

This will be the front-end registration form. It'll register the first user as an administrator role. So you can go back to: http://minerva.local/minerva/admin which will redirect you to login. 

Now you should be logged in and see the CMS backend. You can add users, pages, etc. However, you'll like want to take a look at the minerva_blog library to see how pages can be hooked into and extended to create new types of pages. You'd add that after the minerva library, again, with Libraries::add('minerva_blog'); You could also add that as a submodule.

At this point, I think you get a general idea for the direction of the CMS. Keeping it modular is important, but dependency issues could arrise. If you went to try Minerva without having the li3_flash_message library or configure it for use with Facebook without the li3_facebook library then it would show you a warning message about missing dependencies. I hope to expand upon that, not just to maybe make it look a little nicer, but to allow all libraries to run through some sort of dependency check process. 

Along with keeping things modular, the other goal is to keep things clean. "Minerva Plugins" we'll call them, which are really just libraries, interact with the CMS without touching any of the core code. So you add and remove them very easily while still being able to stay up to date with the latest version of Minerva. The goal is to ensure backward compatibility, but of course problems could crop up with that as well. I'd preferably like it to warn you before an upgrade and I would like to have upgrades from the CMS control panel. So, there's a lot to consider and a lot left to do.

There are really no test cases for the CMS and things are in a state of change. However, most of the foundation is pretty solid. I don't imagine I'll be changing how plugins work and how you can extend core models to add new schema, validation, etc. The template paths are pretty much solid now too. Again the idea is that you put your templates outside the minerva library. 

Feedback, questions, and pull requests always welcome! Hopefully I can put up a roadmap soon so I can take this into more of an alpha status.


As noted above, there's a few configuration options. These will grow more robust, but for now the important ones are for including Facebook and debugging purposes. Here's a snip my app/config/boostrap/librarires.php for an example (note: these are all optional setting, the default database name is minerva and minerva_dev):

Libraries::add('li3_access');
Libraries::add('li3_flash_message');
Libraries::add('minerva', array(
    'connections' => array(
		'production' => array(
			'host' => 'localhost',
			'database' => 'minerva_cms'
		),
		'development' => array(
			'host' => 'localhost',
			'database' => 'minerva_cms_dev'
		)
    ),
    'facebook' => array(
        'appId' => 'XXXXXX',
        'secret' => 'XXXXX'
    ),
    'show_errors' => true,
    'development_errors' => true
));
Libraries::add('minerva_blog');

To the connections array you can add all the same settings you would normally. So, if you were running MongoDB in replica set mode, you'd want to have a key 'replicaSet' set to true. You would also want your 'host' key to have a comma separated list of host names.

Li3_Access: A Lithium Access Control Class

Posted by Tom on Tue, Dec 21 2010 17:53:00

So of course me being me I'm working on a million projects all at the same time. Lately I've been trying to push a lot on my Lithium CMS, Minerva. As a byproduct of all that I am happy to release li3_access, an access control class for the Lithium framework. Don't get too excited, it won't handle your ACL the way you may be looking for out of the box, but you can definitely use it to handle your ACL/RBAC. It extends the adaptable class so expect adapters for RBAC in the future.

Not to go against the flow, there's actually a spec for an ACL system for Lithium. I built my library to fall in line with it so that hopefully there will be less wheel re-inventing. Not that it is a huge class or anything, but it was well thought out and it does come with test cases -- bonus! :)

So of course it doesn't really do much without an adapter and while I don't have a robust RBAC adapter that may use some sort of tree system from the database, I do have a "rules based" adapter that comes bundled with the library. 

You can basically think of this rules based adapter like validation. There's even a method within this adapter called "add" and it does exactly what the validation class does. It adds rules to check for access. If any come back false then it returns an array with some data; including a message explaining why access was denied and a redirect URL. You can then check multiple rules at once. It's very quick and easy to use. Many sites will be able to use this alone and won't require some larger database ACL system. This really involves no queries (well unless you needed data from the database to determine true or false).

Using this adapter you can get very detailed control over access rules; for example, you can lock out specific users during specific times of the day for specific content if you wanted. That's simply something you can't do with a traditional RBAC system. You would have to use your RBAC system and then add to that extra code to catch those special conditions. This allows you to neatly organize and check against your rules much like validation.

For more information and the code, check out li3_access on Github. Remember to keep your eyes open for new adapter in the future, or feel free to contribute one! Thanks, hope you enjoy.

Combine & Minify Assets with Lithium

Posted by Tom on Fri, Jul 23 2010 09:40:00
Before li3_assets(before - click to enlarge)

li3_assets is a nice Lithium library that I've been working on for the Lithium php framework. It is a very easy to configure (and use) library that will combine and optimize your assets all into one file. How does this impact your web site? Well really, it's how traffic won't impact your web server. What happens is instead of say 5 or 6 JavaScript files if you're using jQuery and a handful of plugins, you'll have just one and it will be minified or packed for you. So you don't even need to be using a minified or packed version of the script. In my test here, I saw 12 requests go down to 5 requests and 302Kb page size drop to 187Kb. The numbers really can be staggering depending on how many scripts (and css files) and whether or not they were originally minified or packed or not. This helps overall performance in a website and helps when you have large amounts of traffic coming to your website. The server will serve out less requests and smaller amounts of data so it can handle more visitors.

Before li3_assets(after - click to enlarge)

For JavaScript you have the choice of using JSMin or Packer and for CSS you have the choice of using CSSTidy or a simple whitespace and new line removal. This removal code is very simple, but also very safe. The reason I left a few options for both is because sometimes when you start minifying and packing code, things break. It's rare, but possible. Some of these tools have options and those can be passed as well in the configuration.

As an added bonus, this library also will run less files through phpless. Less is a CSS shorthand syntax that will be converted into actual CSS files. The idea is to speed up your development time. After the files are run through phpless and converted, they are then run through CSSTidy and combined into the single CSS file.

These single combined and condensed assets will live in a directory of your choice and be named with a hash string. This hash was generated from all of the assets used. This way every page that has different assets (JavaScript and for the CSS), will have a different combined hash and therefore different file. Updates? If you have an update to a CSS or JavaScript file, you'll have to remove this hashed file so it can be regenerated. In other words, you may not want to enable all this until you're live with your site.

What's this about images? Images can be "optimized" as well. All images placed with the Html image helper on any given template can be output as base64 data URI's if you so choose. The major drawback to using data URI's is that they don't work on IE 6 and IE 7. You can find some JavaScript solution to this problem, ignore this problem, or don't use data URIs. The benefit? Well, if you're caching your view templates, you've now just embedded all images within the HTML code of your view template. So you can probably take a page down to about 3 requests. One for the JS, one for the CSS, and one for the HTML code plus images within. Now you're really starting to save the server quite a bit of work.

So how easy is this to use? How do you use it? Lithium makes this simple. You will run the Libraries::add() method and add li3_assets. Within the same call, you'll pass all of the configuration options. Then in your layout you'll call $this->optimize->styles() and $this->optimize->scripts() instead of $this->styles() and $this->scripts(). So it runs based on the "scripts for layout" feature. Where any script you place within any of your view templates that contain the array option "inline" as false, you will have those be put into the layout template up top within your head section (or wherever you chose in your layout template). The li3_assets library's helper basically intercepts these assets and runs the magic. It then simply returns the HTML code for the assets to be embedded into the page. Simple. So this makes it nice when you want to turn off the optimization. It also makes it flexible so you can have certain layouts that optimize and others that do not. Here's the code all formatted. First, the library configuration.

Libraries::add('li3_assets', array(
  'config' => array(
       'js' => array(
            'compression' => 'packer', // possible values: 'jsmin', 'packer', false (true uses jsmin)
            'output_directory' => 'optimized', // directory is from webroot/css if full path is not defined
            'packer_encoding' => 'Normal', // level of encoding (only used for packer), possible values: 0,10,62,95 or 'None', 'Numeric', 'Normal', 'High ASCII'                                                      
            'packer_fast_decode', => true, // default: true
            'packer_special_chars' => false // default: false
       ),
       'css' => array(
            'compression' => 'tidy', // possible values: true, 'tidy', false
            'tidy_template' => 'highest_compression',
            'less_debug' => false, // debugs lessphp writing messages to a log file, possible values: true, false
            'output_directory' => 'optimized' // directory is from webroot/css if full path is not defined
       ),
       'image' => array(
            'compression' => true, // uses base64/data uri, possible values: true, false
            'allowed_formats' => array('jpeg', 'jpg', 'jpe', 'png', 'gif') // which images to base64 encode
       )
  )
));

This shows all of the options, but there are defaults. Then in your layout template put the following within the head section of your template:

echo $this->optimize->scripts();
echo $this->optimize->styles();

That should do it. Now any script in any template using that layout defined like this:

echo $this->html->script('scriptname', array('inline' => false));

...Will be sent to the layout and intercepted and added to the list of scripts to be processed. The same goes for CSS as well.

To convert all images within a template using the Html::image() helper method, you'll simple put at the top of the view template:

$this->optimize->images();

This doesn't output anything, but it does trigger a method that will apply a filter to the Html::image() method. Filters are a real nice feature with Lithium. Now any call to the image() method will be intercepted and the data will be converted to a base64 data URI and returned. I think the use of images as data URI's is limited, but can be a nice feature to have. I think it's especially handy on certain pages where you know a lot of traffic will hit and also helpful for mobile devices. Remember that making another request (connection) takes time and while we don't notice it on high-speed internet, mobile devices will notice it. It also changes when images get loaded and rendered in a browser as well. So I feel it's an under used trick of the trade.

Again, you can grab this library from the repository on the rad-dev site. http://rad-dev.org/li3_assets.