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 email@example.com:tmaiaroto/minerva.git app/libraries/minerva
Then do the same for li3_access and li3_flash_message.
git submodule add firstname.lastname@example.org:tmaiaroto/li3_access.git app/libraries/li3_access git submodule add email@example.com: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 firstname.lastname@example.org: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.
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.
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.
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 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.