GiriGiri seeks to enable web developers/coders to make changes and additions to its system with minimum effort. With that, anything that could lock-in the code into predetermined, set routines are avoided. Ie, there are no complex module installation/registry concept, there are no complex dependencies, there are no extensive configuration settings or operations that need to be done in admin side on the database to put in modules. You just drop in the module folder, import its sql table if it has any db tables, and you are set.
Module classes too, are coded and loaded as singletons. Hence, all of them are independent of each other, except a few core modules. The Module loader class, only initializes singletons, and dispatches actions to modules. This makes possible to avoid using a factory-extender class structure. Therefore, a singleton does not become an extender of the factory class, but as an entity itself. This accomplishes a few things :
So, a variable sitting in an array in an extender class loaded by factory class like
If the practice of giving simplistic names to modules are used, this will simplify to something like :
Any coder, even the ones with little experience with PHP OOP can recognize easily that, the above is the value of password of the user details array in the module user, without much effort.
This increases code readability, reduces errors and makes it less troublesome to code big modules, or many modules.
Modules are entities in themselves, totally contained with their own template files for html, language files, and their classes. Its so much that, what happens in module, stays in module. A module will not be aware of the existence of another module in the system, without you specifically making it aware. It will be just handed over an action to perform, and it will perform that action and any number of actions given to them in succession, and just that. If you do not invoke that module singleton in another module, there will be no way they can interact with each other.
You just initialize a module (singleton) in another module, and all the methods of that module, is available to the other module. There is no intermediary class in between, there is no need to juggle variables in between. You can initialize the other module in one, more methods (functions) of that module, therefore, limiting any kind of interaction in between modules, to wherever needed.
This facilitates various things, but foremost are that you can easily put in/remove modules, code modules without needing to be concerned about what happens in others, and, the fact that it reduces security issues in any module, by keeping everything that is happening in that module, only in that module.
Because all modules are coded as singletons, modules get initialized one time. This means that, whenever they are invoked, they will be the SAME object, with all its values and state, wherever they are invoked. This makes tracking any kind of state, variable in between different modules very easy. And it is the underlying concept behind the globals singleton that GiriGiri uses to store all its widely usable variables.
Coupled with the module-action dispensing logic, modules can be loaded only at times they are needed. Totally run time. A module being loaded in, say, a page that includes a form and requires its generation, may not need to be present in the page that the form is submitted to. That reduces load on processing power and memory, during high volume usage cases.
The significant drawback of this module-action logic is that, one needs to initialize any other modules, singletons (including core classes) that is needed to be used in a function, in that function. So basically, one needs to slap in the initialization command of any module that is necessary within that method, into the method. However, this is not so much a burden, compared to having to write long reference strings to variables in a traditional factory-extender structure. Its just copy/paste, once.
A very useful result of the above design is that, It is possible to give a long string that includes many action commands to many modules to GiriGiri, and make all modules process those actions in succession.
So, when the below string is passed from get, or from post
the module loader will dispatch do_register and activate actions in order to the user module first, set_group action to the group module afterwards, and finally, do_login action to the session module.
As you can see, more than one action can be sent to each module, and, more than one module can be fed with actions.
There is no limit to this. You can send as many module-action mappings as you want.
What this accomplishes is, further separation and simplification of module methods for each module. With the above string, depending on the contents of the request variable, a user is registered, then activated, and a group is set for that user, and then s/he is logged into the system.
This actually has further implications ; the output of an entire complex page, can be determined with nothing but simple actions to different modules. All the outputs of these modules can be assigned to template keys, therefore, complex pages can be formatted, created, just like playing with lego bricks.
This singleton module concept provides us with a very important ease - the core modules that are required, or the core singletons that carry variables are the same objects wherever they are wanted and initialized.
This means that, the global singleton carrying ALL the variables that are used in processes, ($gb), will be available in all modules as it is, and it will act as a carrier of information in between these modules.
Import request variables and cookie variables into this singleton, and you will have the request variables available to all modules in a safe, sterilized singleton.
Also, its possible to carry around important variables like configuration, or internal variables (say, like $gb->internal['formerror']), and have less worries about tracking variables, sanitizing or processing them.
Same goes for the core modules. All methods, variables in core modules, will be available to all modules as they are. This includes the versatile template singleton/module.
This allows for central coordination of various important functions, like template creation and population, variable tracking.
With all the above, we can approach the permission concept in a new way :
Instead of giving permission levels to entire modules, we can just give permissions to individual actions in modules.
Say, instead of giving 'administration rights' to an entire module, we can give administrator group the rights to actions create_user, edit_user, delete_user. And, registered users to edit_self. And finally, the unregistered anonymous visitors register_form and do_register actions.
With this logic, there is no need to lump 'admin functions' into sets, and we can define permission sets as we want. We can create a group, and then assign them the rights to crete_user, edit_user, but not give them permission to delete_user. With that, we have created a group that is not a super admin, and cant delete any users.
Similarly, say, you can create an entire demo installation of GiriGiri or a module/app you develop on it, by allowing anonymous users the rights to see all forms, admin screens, but disallow from doing any save/modify operations.
As you can see, there is much wiggle room with this kind of module logic and permission system.
But there is one other important consequence of this approach :
These above, allow us to approach the 'page' concept in a slightly different way than how other mvc structures or templating structures do.
We can create nonexisting pages, and assign module-action mappings to them in the database, and whenever that page is loaded, in addition to the module-action map requested from it, it will also perform the module-action mappings that were saved into it in the database.
Lets say, we have to create a page which will show users the registration form if they are not registered, but, profile form when they are logged in.
So, we can just create a nonexisting page called user in the page module, and then assign the module-action mapping user-registerform-profile to it. If, we give permission for the registerform action to only the anonymous group, and give permission for profile to only registered group and admin group, then, when page=user is requested from GiriGiri with NO other module-action mapping or requests by a registered user who is logged in, GiriGiri will first attempt to load the registerform action from its relevant module. Seeing it is not allowed for that group, GiriGiri will NOT load that module and run that action, and instead will move to the next module. profile action from the relevant module is allowed for registered users. So, girigiri will load up the profile form/insert into the page template and print it out.
Similarly, an anonymous user coming to the page will first see the registration form, but because its not allowed for their group, wont see the profile form.
As you can understand from this example, it is possible to create very complex page structures, dynamically created by modules. Each module assigned to the page will run the action its assigned. (each module can be assigned more than once with different actions or even the same action). Their procedures will be run and output will be incorporated, and the page will still respond to individual module-action requests coming from get or post, running them on top of saved m-a mappings too.
As you can see, it is totally game of lego bricks.
Using the singleton module concept, the template core class/object and global class/object can keep page template (skeleton page with no keys populated) the page content (the keys that carry the content items to be inserted, may be directly content like text, or structures in themselves, like forms, login forms etc.) and language (the replacements of whatever language chosen, into any key in the page skeleton structure.
The benefit of this is, all the modules participating can use these two core classes/objects totally independently, and the state of matters as in separate page structure, content, and language is carried up until the last moment at which the page is built and sent to client.
Up till that very point, you can do whatever you want with these. If you want, make a small modification and have the template builder object send all the language strings to google translate or another service, and have them translated, and then place them into the content, and end up with a translated page, or, run last time modifications on page content, like search/replaces. It gives the freedom to you.
In summary, GiriGiri has been designed around a developer friendly design. It aims to reduce any kind of overhead involved in developing web apps/sites, by allowing the developer maximum freedom, but still allowing building of complex, but modular apps.