April
15
Release 18 is the latest version of Cognifty. The new big feature is custom content publishers. You can create your own types of content based off of the main file upload tool or text tool. You can write your own plug-in to handle the publishing and do any sort of compiling, checking, or linking required before the content goes out to the site.
The blog system has been ported over to this custom content publishing framework. To make your own publisher you can use the blog publisher as a starting point. To activate your publisher simply add one configuration line to the default.ini
;This is a default content publisher which is required for the blog module to function
content.extrasubtype.blogentry=
@sys.path@/modules/blog/lib/Blog_Content_Publisher.php:Cgn_Content_Publisher_Blog
The content.extrasubtype. is required, anything after that must be a unique identifier for your content type.
I have been using this to make a client support portal. I upload files and set which client organization that file belongs to, then when I publish it, I can move the content to whatever database table I want, or publish it to a disk cache.
Other ideas could be:
Create a movie review content type which requires an IMDB link before publishing.
Make an e-book content type which could convert wiki syntax into PDF.
Split publish a text file into an article and a knowledge base entry.
Schedule your publishing by saving the content to another system or another database table.
Push your content to a static site build tool, like a specialized cruise control.
Push your content to Subversion or other source code manager.
January
22
Released last week, Cognifty 17 brings a new identicon library as well as a simple way to backup your database.
Identicons are a nice way to visually identify something. Most of the time, people confine their use to blog posters who don't have a specific avatar image. Assuming that the poster's IP or e-mail address are unique, the identicon is a visual representation of that piece of data.
I wanted to do something a bit more useful for a site manager than simply identifying anonymous commenters on a blog. So I've added identicons to each piece of content in the admin system: specifically each piece of content which is not an image. Instead of a an icon which simply represents the mime type of the data, each page, download, article, or blog post has a unique image displayed next to it. The idea is that an editor can become more familiar with frequently linked content and identify the correct document much more easily when looking at hundreds of pages.
The identicon is based off of the content's GUID, so it will never change throughout the lifetime of the content.
The library supports two different painters, one for GD and one for SVG. The default "Geometry" based identicon can be extended for other graphic displays, such as words, fractals, or cartoons.
The standard way to create an icon is pretty simple:
$seed = md5(rand());
$size = 64; //pixels
$blocks = 16; //complexity of the geometry
$t['icon'] = new Cgn_Vis_Identicon_Geometry($seed, $size, $size, $blocks);
$t['icon']->buildIcon();
header('Content-type: image/png');
echo $t['icon']->getIcon();
October
01
I didn't blog about release 15 specifically, so I'll combine the new features from 15 and 16 into one post.
Cognifty release 15 brings a new concept of "Sharing Modes" to the table. A sharing mode is a default implementation of row level security.
Traditionally, many PHP applications completely lack any concept of groups or roles. This was one of the major road blocks which kept me from adopting applications like "DotProject". In DotProject, if you wanted a user to be able to view tickets, for example, this user would then be able to view all tickets in the system, regardless of which group a certain user belonged to. If you were to expose parts of DotProject to your external clients, they would be able to see all tickets submitted from all of your clients.
In a system such as this, we can see that there is some level of security, the ability - or ROLE - to view tickets can be restricted to certain users. But each record of data in the domain of tickets were not able to be restricted further, beyond the ability to view them. We call this type of security role based security, or an access control list.
Merely specifying the access to an entire domain of data, as you can see, is not a complete solution to making an application usable by different parties. People who work in one organization should be able to see different information from people in another organization.
To have the most complete security model we need both access control lists and row level security. In Cognifty, the access control lists define global access to services, and the row level security restrict the viewing, editing, and deleting of individual data items down the the user or group level.
I said before that a "Sharing Mode" is an implementation of row level security, but what does that mean? Specifically, a "Sharing Mode" is a label that tells the system which fields in a database table define the specific row-level access. The labels are completely configurable by the developer, but the system comes with some defaults that should satisfy 80% of the use cases out there.
sharingModeRead: same-owner, same-group, parent-group, parent-owner, registered, none
sharingModeCreate: same-owner, same-group, parent-group, parent-owner registered, none
sharingModeUpdate: same-owner, same-group, parent-group, parent-owner registered, none
sharingModeDelete: same-owner, same-group, parent-group, parent-owner registered, none
With these defaults, any CRUD operation is compared against a configurable field, either owner or group, before the operation is run against the database. Let's take an example of a forum system, where viewing some forums are restricted to certain groups, and only the original poster can edit his or her own posts.
The forum itself would have sharingModeRead = "same-group". In this way, if a group_id was specified for the forums, any read operation would first be checked against a list of group IDs from the current user. If the group_id column was empty, or zero, the read operation would succeed for anybody.
The forum post table would have sharingModeRead = "parent-group". With this sharing mode, the system joins the parent table (configurable in the code) with the form post table and checks the group before allowing any reads. This ensures the same sharing mode as the parent forum. The create mode would also have "registered" flag set, so that any user can post to any forum they have access to. And, for updating, the forum post table would have sharingModeUpdate = "same-owner" so that any update operation is compared against the current user's ID first.
All these values can be modified at run-time for special administrative privileges if the current user is part of any forum administrators group.
The biggest new feature in release 16 is the API agents feature. Any registered user of the system can enable or disable their API agent from the account settings screen. The API agent brings a consistent way of accessing any configured service of a Cognifty installation to 3rd party scripts.
Sometimes remote API access is hacked on to a Web project after the project is completed, or near the end of the development cycle. If you start your Web projects with Cognifty, you don't have to worry about developing API access from scratch any more.
Having an API per user account instantly brings the same level of groups and permissions to any API modules that you develop. I've seen global API keys (that is, one API key per installation) already in the project Piwik. Not being able to control the access of API agents (scripts that use an API key to interact with the system) is very bad. If somehow your *global* API key gets leaked, the thief now has all the access allowed by the project's API. Having per user API keys allows you to create robot specific users, limit their permission in the system, then generate API keys for each robot or task.
Some ideas for per user API keys include:
Quickly create per user, authenticated RSS streams (eg. my tasks)
Remote content publishing to live servers (wink wink, release 17)
-
Single sign on service (create a session when pinged with the user's API key)
Create customizable facebook-style embedded apps.
July
28
In release 14 of Cognifty I cleaned up the CGI request handler to work with nanoweb. It's pretty different from the Apache CGI handler for PHP because it doesn't break your PATH INFO, etc. I've always been interested in running "self contained" PHP applications that can be distributed with their own server, at least as a way to demo a product. So, that interest has led me to live CDs, and Apache Friends' XAMPP.
Now, however, I'm all about the nanoweb. You can build a PHP-CGI binary for 1 platform, compile in PDO and SQLite (since sqlite is just a C client library and not a server), and ship it with nanoweb. Now you have a full Web application stack in only about 14 Mb (depending on what you throw into the php-cgi and how much you compile statically).
I think the real benefit of this setup is being able to run an app that is completely self-contained. It doesn't matter if someone has apache installed or not, it doesn't matter if they have php 4.3.0 with safe_mode on, it doesn't matter if they have mysql-5 server but have compiled PHP against mysql-4.1 client libraries. With this sort of setup, your app is completely segmented from what is on the target system.
So, what benefit does being completely segmented have? Well, look at Plesk. It's a complete virtual host manager distributed with it's own Apache, PHP, and Mysql so that it can stay running even if you break the system's default settings to the point where nothing works.
In honor of this release's compatibility with nanoweb and the new SQLite PDO driver, I've written the first part of an article dealing with how to write your own virtual host control panel, or other embedded PHP servers.
Read the article, leave comments here. Tell me if the code is working or not. All the code is available on sourceforge.net's Subversion here.
svn co http://niftyphp.svn.sourceforge.net/niftyphp/niftyserver/tags/tutorial-p1 niftyserver
July
10
trying to put another "r" in RAD
I've just added a new "live cheat sheet" to the http://cognifty.com/index.php/tutorial/ section. I've seen some other projects which have these so-called "cheat sheets", but the cheat sheet is simply a huge PDF. These PDFs usually show a graphical representation of the software system as a set of colored blocks and arrows with tiny variables written inside the blocks. These variables are supposed to help you remember which functions are available at which points in the system.
While it's nice to have an overview of a system with colors and blocks, I don't really want to have to have a PDF reader loaded while I'm developing. So, I'm trying to do a sort of "live cheat sheet", in which you find what you want to do, you click the words, then you are able to simply copy and paste the sample code into your application.
I thought this would be good since a couple of people are always asking me how to do this and that in Cognifty. To me, it's very easy because I know exactly where each type of example code is located. I know that the blog system has the best implementation of the Spam blocking Trusted Service framework. I know that the admin system makes extensive use of the data grid MVC. The problem is, other people don't know these things off the tops of their collective heads.
I'll admit it, a fair amount of my coding time is spent using VI to copy (yank) and paste code from one module to another. I do this even if the code will require significant changes, because it seems a bit easier, or perhaps safer. But, how many other people copy all the boring "scaffolding" from one class to another? For frameworks that generate "scaffolding" code, I would consider typing the command to generate the code just as time consuming as copy, paste, search, replace.
I've already used this system myself to remember the exact class names and function names for some template methods. So, I believe it has some validity. Not only does it help jog a developer's memory and cut down on hunting for good copy/paste code, I think it gives new people a very good idea about what their work will look like inside a framework/application. Instead of seeing all around the code (the class definitions, the function names, the parameter signature) one can actually see inside the code, if you will. This type of code makes up the the day-to-day meat of coding in a system, not the elegant back-end or class hierarchy, which may or may not directly impact a developer.
Is this type of system obsoleted by IDEs with code completion? Is it useful? Does it give anyone a better insight into the CGN code-base?