Welcome to Geeklog, Anonymous Sunday, September 01 2024 @ 12:49 am EDT
Geeklog Forums
GL2 Plugin API (Draft)
vinny
I'm looking for any suggestions that will improve the API or the documentation. I'm especially interested in recommendations to expand on Apendix B and improvements to the readability of the document.
This is another big step forward in moving towards a real implementation of GL2. If you check out GL2's cvs, you can see we're slowly moving away from vaporware.
Thanks,
Vinny
James Fryer
> It is especially important to note that GL2 is being planned to use PHP 5
Why PHP5? Wouldn't PHP4 give you wider compatibility? What features of PHP5 are essential for GL2?
> The GL2 plugin architecture will be event based.
> Each plugin will register to listen for events that are generated by
> the GL2 kernel and other plugins.
I'd like more detail about the event based architecture you propose.
- What are its advantages over a conventional function call architecture?
- How will it work in practise? I'd like to see an example of how a page is generated from event calls.
- You realise you will have a domain terminology problem with internal events and calendar events?
I'm slightly skeptical about attempts to introduce event-based and MVC paradigms into web programming, which doesn't easily fit this model. An event model to me implies there is a running server, whereas PHP generates pages on demand. What happens to an event that occurs when no one is looking at the site?
> The Plugin Interface Class
One of the main difficulties at the moment is that plugins are quite hard to write. I hope you will consider the needs of plugin authors at every stage of the design process.
> class glPluginInterface {
> /**************************************************
> * Installs and registers the plugin with the GL2 kernel
> *
> * Handles the creation of data structures, security setup, and
> * registers for events.
> *
> * @access public
> **************************************************/
> public function install();
What do these functions return? This should be documented.
> Handling Events
> At that point it is the responsiblitiy of the plugin to do any required processing
> and to return an appropriate value.
How is this value returned? As strings of HTML code from the handle event function, which are then assembled by the event dispatcher?
How will different formats be handled, e.g. if I want a text or XML version of a page?
> Triggering Events
It may also be useful to have a function or option that delays triggering an event until a particular time.
> Directory Structure
> .class.php (interface class)
Why does this have a unique name? You already have the directory name to identify the plugin. I would give this file a standard name, e.g. 'main.class.php'. Advantages to this are, it makes it easier to create a new plugin by copying an old one, and it simplifies the code for manipulating plugins.
> Templates
> GL2 will only support HTML_Template_Flexy.
Why this library in particular? Why not Smarty?
I don't have time to go into this in detail but a big problem with the current template system is that it does not properly separate display and application logic. The current templates are so simplistic that any complex display logic has to be carried out in the code before the template is called. Thus you lose the advantage of a template system which is separating the two kinds of logic. I hope this will be addressed in the new system.
> core.adduser A new user gets added (not self registered)
> core.newuser A new user registers with the site
Is it really necessary to have separate events for these? I think this will lead to duplication of code. Wouldn't it be better to have one event for adding users, with a parameter to say whether it is added by the admin or by registration?
> core.header.display Insert javascript/CSS in html
Supposing I want to add something extra to the headers added in this event? Can I do this with the event system?
Dirk
One of the main difficulties at the moment is that plugins are quite hard to write.
What exactly, apart from the not exactly stellar documention, are your problems with the current API?
Plugins can be fairly simplistic (and easy to write), as you don't have to implement all the plugin API functions. See, say, my Manual Digest plugin or the "MacIG" sample plugin for examples.
bye, Dirk
Tony
1) Why PHP5? Wouldn't PHP4 give you wider compatibility? What features of PHP5 are essential for GL2?
ANSWER: Well GL2 is a long ways from being production ready and the 1.3.x tree will live for quite some time (even after the GL2 release). PHP5 brings many missing object oriented features that were missing in 4. I could run through them all but I'd simply refer you to the Zend site or the PHP site. At a high level the big advantages are: 1) Much improved exception handling. In PHP4 the best way to handle exceptions is using PEAR::Error, in PHP5 we have the "try...catch" clause. PHP5 also forces private, public, protected methods and properties to be honored. PHP5 introduces abstract classes as well as interfaces.
2) I'm slightly skeptical about attempts to introduce event-based and MVC paradigms into web programming, which doesn't easily fit this model. An event model to me implies there is a running server, whereas PHP generates pages on demand. What happens to an event that occurs when no one is looking at the site?
ANSWER: Uh, I'm not following you at all here. MVC fits any paradigm that has a user interface, business logic and a backend database. I couldn't diagree with you more here. To be clear, the 'event' model can be thought of more as the Observable/Observer design pattern. We don't want to over engineer GL2 however some of the classic design patterns made popular by Java make sense for use in any language. All the event model does is allow plugins to specify which kernel events they care to listen to. In 1.3.x we are terribly inefficient because for each 'event' the GL 1.3.x attempts to call the corresponding AP method on the plugin even if the plugin doesn't implement ti.
3) One of the main difficulties at the moment is that plugins are quite hard to write. I hope you will consider the needs of plugin authors at every stage of the design process.
COMMENT: Dirk has already addressed this well. You seem a bit hostile (though deriving context from posts on the internet is hard). If you have a vested interest in this I'd encourage to become a part of the process. That doesn't mean you have to code but if you have specific ways we can make improvements we'd love to hear them. However, making broad sweeping statements without giving justification of what you mean will only upset people.
4) What do these functions return? This should be documented.
ANSWER: Good point. We haven't begun working on exception handling yet so what they return is still in the air. I will say, though, we will be using PHPDoc so don't worry too much it will be documented
5) How is this value returned? As strings of HTML code from the handle event function, which are then assembled by the event dispatcher? How will different formats be handled, e.g. if I want a text or XML version of a page?
ANSWER: much of this will depend on the event that was fired. Each event may return different things, one may return and object, one my return a string an other may return nothing at all. You have to take this into context. The other part of your question is output format. We will be publishing at a later time how the layout stuff will work (much work has already started) but to give you an answer, if your plugin supports multiple output formats (e.g. XHTML, XML, WAP, etc) great, you will be able to do that. Where we are most concerned now is when we need to show pages that integrate information from multiple plugins.
6) It may also be useful to have a function or option that delays triggering an event until a particular time.
COMMENT: Can you give an example where this would be useful?
7) Why does this have a unique name? You already have the directory name to identify the plugin. I would give this file a standard name, e.g. 'main.class.php'. Advantages to this are, it makes it easier to create a new plugin by copying an old one, and it simplifies the code for manipulating plugins.
ANSWER: We will have to look at this more. Our ultimate goal is to not have any such requirements other than plugins go into the directories with unique names. The only other problem we must manage is the potential for classes in different plugins with the same name. Any suggestions on how to best avoid this is welcome.
8) Why this library in particular? Why not Smarty?
ANSWER: Well simply because Flexy is better. Flexy is a lexical parser that compiles the templates into PHP code to avoid costly regex string parsing that other template classes use. Flexy also includes most of the bells and whistles of Smarty (control structures, etc).
9) I don't have time to go into this in detail but a big problem with the current template system is that it does not properly separate display and application logic. The current templates are so simplistic that any complex display logic has to be carried out in the code before the template is called. Thus you lose the advantage of a template system which is separating the two kinds of logic. I hope this will be addressed in the new system.
COMMENT: the Utopia you are after doesn't exist. With our implementation of PHPLib you do have to write more PHP to handle complex display (e.g. nested templates). However, this is still nice because the web-design guy doesn't need to see that PHP code and can work on the templates themselves. With newer template system like Flexy, you can basically add code to them to handle the complex displays but then you have a problem where the average Joe web designer now has to make sure he didn't break the template because of removing a close to a for loop or something like that. In the end you have to strike the middle ground...I agree that IT/PHPLib isn't the greatest but at the time we decided to use it it was the most mature. Look into Flexy, it is almost at it's first stable release and I think you will like what you see.
10) Is it really necessary to have separate events for these? I think this will lead to duplication of code. Wouldn't it be better to have one event for adding users, with a parameter to say whether it is added by the admin or by registration?
ANSWER: we are always for considering alternatives. Keep in mind that we created the event-based model because it introduces a level of consistency in how things get triggered. I will say, however, I do enjoy the use of encapsulation. Depending on your plugin you may do radically different things between the two events, one muddy the code by putting it all in one function when you can make it more atomic by splitting it up?
11) Supposing I want to add something extra to the headers added in this event? Can I do this with the event system?
ANSWER: Yes.
---The reason people blame things on previous generations is that there's only one other choice.
The reason people blame things on previous generations is that there's only one other choice.
vinny
> "Why PHP5? Wouldn't PHP4 give you wider compatibility? What features of PHP5 are essential for GL2?"
The biggest reason is the better handling of classes in PHP5. We plan to use many of the features that are included in PHP5. Also, since GL2 is (at a minimum) 6 months away, we think that PHP5 will be gathering momentum at that point and we'll start to see a large installed base. If necessary we can back-port to PHP4.
> I'd like more detail about the event based architecture you propose.
> - What are its advantages over a conventional function call architecture?
I'm not sure that I can articulate this well, but I'll try. Since plugins register for functions, only those plugins that want to respond to an event will need to do so. If we used functions architechture (similar to what we have in GL 1.3.x) we would have to check for the existence of the function for a particular plugin or else have every plugin return a result for every function call.
Also we think we'll increase portability between versions of GL2 by this implementation.
We could force a function model to do all the same things, but we believe that implementation would not be as clean (and hence make plugin development slightly more difficult). We think that this event architechure gives devlopers more flexibility without increasing complexity. We're open to comments for or against this. If you think functions are the better way to go, let us know and we'll consider you're arguments.
> - How will it work in practise? I'd like to see an example of how a page is generated from event calls.
We're working on an example.
> - You realise you will have a domain terminology problem with internal events and calendar events?
No I wasn't thinking about this at the time, but I agree completely. Recommendations for new terminology are welcome.
> "I'm slightly skeptical about attempts to introduce event-based and MVC paradigms into web programming, which doesn't easily fit this model. An event model to me implies there is a running server, whereas PHP generates pages on demand. What happens to an event that occurs when no one is looking at the site?"
Presumably if no-one was looking at the site and an event was generated there would be no View class executed. A command would execute, do what it needed, and then terminate. Though if the event was to send an email for instance, then the View would handle the formating of the email and send it.
Tony's MVCnPHP was crafted with web development in mind. To minimize memmory footprint and processing it loads only classes (Views and Commands) that it needs to execute. I think you'll find this implementation is usefully for making efficient (and maintainable) web pages.
> "One of the main difficulties at the moment is that plugins are quite hard to write. I hope you will consider the needs of plugin authors at every stage of the design process."
We're trying hard to fix that in GL2. We're trying to make a "Hello World" plugin be simple to implement but still grant developments flexibility and power for more complex plugins.
> What do these functions return? This should be documented.
You're right, I'll fix that in the next version of document. The current plan is for install(), upgrade() and uninstall() to return "true" on success and either "false" or an error message on failure. We're still working on the details. Suggestions are welcome in this area (as in any other).
The handlEvent() function will return a single variable (possibly a reference to structure or array) which will be defined per event. That too needs to be added to the documentation.
> "How is this value returned? As strings of HTML code from the handle event function, which are then assembled by the event dispatcher?"
That was poorly written. I think the last half of the answer to the previous question covers it. Basically the return type will be on a per event basis. Likely this will not be HTML (as HTML/xml/email/text will be generated by the Views).
> "How will different formats be handled, e.g. if I want a text or XML version of a page?"
The Views will handle outputing different formats. Tony and I are still working on a specificication for how Views should handle different formats.
> "It may also be useful to have a function or option that delays triggering an event until a particular time."
Something I hadn't thought about but that might be a good idea. Can you think of an example where this might be usefull?
> "Why does this have a unique name? You already have the directory name to identify the plugin. I would give this file a standard name, e.g. 'main.class.php'. Advantages to this are, it makes it easier to create a new plugin by copying an old one, and it simplifies the code for manipulating plugins."
Absolutely correct. Again, something I just wasn't thinking about when I drafted the document. What do you think of 'interface.class.php', or do you think 'main.class.php' (or something else) would make more sense?
> "Why this library in particular? Why not Smarty? I don't have time to go into this in detail but a big problem with the current template system is that it does not properly separate display and application logic. The current templates are so simplistic that any complex display logic has to be carried out in the code before the template is called. Thus you lose the advantage of a template system which is separating the two kinds of logic. I hope this will be addressed in the new system."
I think you should check out HTML_Template_Flexy. It supports most (if not all) of the template logic that Smarty supports. It also can use pre-compiled (or compiled on demand) templates. The big advantage of it over Smarty is that it fits into the MVC architechture much cleaner.
> "Is it really necessary to have separate events for these? I think this will lead to duplication of code. Wouldn't it be better to have one event for adding users, with a parameter to say whether it is added by the admin or by registration?"
Basically those were both added to increase flexibility. Though a plugin would have to register for each event seperately, a plugin could handle the two events with the same code:
function handleEvent($event, $var = '') {
switch ($event) {
case 'core.newuser':
case 'core.adduser':
//do stuff
break;
}
}
> "Supposing I want to add something extra to the headers added in this event? Can I do this with the event system?"
Thinking about this we should probably add events for the different html meta tags so they can be combined into a single HTML tag. Is that what you had in mind? Otherwise I envision this event allowing you to add anything you want between and .
-Vinny
tomw
One question -- will the plugin directory be in or out of the webtree? If in the web tree, how will you handle security for config variables.
Tony
So my question back is what is the best way to secure the config files? We could provide a checking machanism similar to Gallery that requires certain permissions on files but that may make plugins installation and configuration more complicated. I'm open for suggestions.---The reason people blame things on previous generations is that there's only one other choice.
The reason people blame things on previous generations is that there's only one other choice.
James Fryer
Tony:
> PHP5
Fair enough, your reasons make sense. It is a risk though, what if PHP5 takeup is not as high as expected? (c.f. Apache 2). Rewriting the software is a risk in itself, I would say reduce other risks as much as possible.
> Uh, I'm not following you at all here. MVC fits any paradigm that has a user interface, business logic and a
backend database.
I think that replying to these messages has helped me 'get' what you are talking about. Tell me if this is correct.
1. The user makes a request for a GL2 page.
2. GL2 gets data from the database and creates a Model object representing the GL2 page
3. If the user has submitted a form then changes are made to the Model as appropriate
4. GL2 creates a View object with the Model object as parameter
5. The View is rendered as HTML (or whatever) and sent to the user
I can see then how MVC can work here. One difference is that with a desktop application the model will continually update the view, whereas with a web application you might as well create the view at the end, but this is a minor point.
> In 1.3.x we are terribly inefficient because for each 'event' the GL 1.3.x attempts to call the corresponding AP method on the plugin even if the plugin doesn't implement ti.
Has this inefficiency been measured? Is it a real problem with GL installations? I find GL quite speedy.
> You seem a bit hostile
I didn't mean to come across that way. I was trying to be helpful by constructively (but robustly) criticising the paper. You acknowledge that GL1 has architectural faults, hence the development of GL2. If the current plugin system was ideal, we would not be having this discussion, so bringing up its shortcomings seems appropriate. If I have upset anyone I apologise. (NB I will reply to Dirk's message separately.)
> Each event may return different things, one may return an object, one my return a string
Doesn't this makes it difficult to interpret or use the results of an event unless the caller knows the type of the event?
> 6) It may also be useful to have a function or option that delays triggering an event until a particular time.
> COMMENT: Can you give an example where this would be useful?
A 'Quote of the Day' plugin which updates every day.
> Well simply because Flexy is better.
Fair enough.
> the [template] Utopia you are after doesn't exist.
No, but it is possible to come quite close. I don't see any way to avoid loops and conditionals inside templates. I agree this means it's a more skilled job maintaining them. I think that separating application logic from display logic (as you are doing with your View and Model classes) is essential if you want an application to be flexible.
> Depending on your plugin you may do radically different things between the two events [adding a user as an admin or by registering] one muddy the code by putting it all in one function when you can make it more atomic by splitting it up?
I would imagine that most plugins that handle these events will handle them very similarly. This level of granularity needs justifying with examples where one case is not a subset of the other.
Vinny:
> We're working on an example [of how a page is generated from event calls]
Just a basic pseudocode walkthough would make it a lot clearer.
> What do you think of 'interface.class.php', or do you think 'main.class.php' (or something else) would make more sense?
My preference is for 'main'. 'Interface' to me implies that the file doesn't contain an implementation. It doesn't really matter though, as long as it's consistent.
> Thinking about this we should probably add events for the different html meta tags so they can be combined into a single HTML tag. Is that what you had in mind? Otherwise I envision this event allowing you to add anything you want between and .
I was thinking about meta-tags but there might also be a need to add other stuff. For example a plugin might need to add JavaScript functions to support its client-side interface. Or a plugin might want to add CSS tags. Could this be handled?
jlhughes
All of my Geeklog sites (more than six) are on commercial servers running Linux. All I have is FTP access to these files.
Since I don't have access outside the webtree, my solution has been to put the non-webtree directories under the cgi-bin directory.
Is there a reason why this isn't a good option for those installations that don't have root access to the server?
tomw
Might I suggest the following scenario:
Have the default install of both plugins and the program itself be into the web root -- so that simply uncompressing the files in the correct spot will result in them being in the correct place and functioning. Then have a security howto that will tell the more astute how to move the sensitive files out of the webroot. If someone does not understand about paths, then they can leave it in the default configuration.
Imagine this if you will 'No more questions about how to set the path variables!' Well I am overly optimistic here.
![Wink](images/smilies/wink.gif)
Good programing practices prevent people from viewing php files directly anyway.
TomW
Tony
Fair enough, your reasons make sense. It is a risk though, what if PHP5 takeup is not as high as expected? (c.f. Apache 2). Rewriting the software is a risk in itself, I would say reduce other risks as much as possible.
Keep in mind that 1.3.x is around and is supported under many old (really old) versions of PHP4. We haven't been very good at changing the minimum requirements for PHP nor the database mainly because users insist that we don't. However, even when GL2 is here under PHP5 1.3.x will still be around until PHP5 has enough adopters. GL2 is a great place to change the minimum requiremetns and we have taken that liberty not to alienate users but to build a better product. So, to be clear, this is a good thing...users will have more choice.
I think that replying to these messages has helped me 'get' what you are talking about. Tell me if this is correct..
Uh, sorta. Not exactly. I really must refer you to the MVCnPHP code:
http://cvs.geeklog.net/cvs.php/MVCnPHP
The README should help explain a few things and there is a rudimentary sample app included. I will have a working classified plugin that uses MVCnPHP that will show how to use it in a real world application. I plan on releasing that this weekend.
Has this inefficiency been measured? Is it a real problem with GL installations? I find GL quite speedy.
Just depends on the number of plugins and the number of users you have. The fact you are making checks for the existence of a function is just overhead that isn't needed. Not a huge deal but something that bugs developers.
If I have upset anyone I apologise
No problem, your feedback has prompted a good discussion!
Doesn't this makes it difficult to interpret or use the results of an event unless the caller knows the type of the event?
Not really. We should make return values as consistent and predictable as possible but an event model will undoubted require different types of data to be passed around. PHP supports reflection so, in code, it will be easy enough to determine which object we are getting back. Besides, our documentation should nip this in the bud to a certain extent.
This level of granularity needs justifying with examples where one case is not a subset of the other.
Isn't encapsulation a good enough reason? If two events handle an event the same way you would either have one event call the handler of another or create a seperate private method that both events can call. Trust me, when we lift the hood on this you'll appreciate having this level of separation...it is more flexible and unltimately more maintainable IMHO.
--Tony
---The reason people blame things on previous generations is that there's only one other choice.
The reason people blame things on previous generations is that there's only one other choice.
Tim
GL2 has been discussed here on and off for over two years now with very little progress made and projected times sliding and sliding. Originally, it was going to work with PHP4 then changed to PHP5. I don't mean to sound ungrateful but I think you developers ought to seriously discuss whether to put 1.3.x in a caretaker status and put some real effort behind GL2's development or just can GL2 all together and stay with the 1.3.x architecture otherwise you'll be saying yet again in six months it's at least another six months away.
I suggest using a constant (eg INSIDE_GL) defined in the main config file and a check made at the top of all the other files. Example:
if (!defined('INSIDE_GL')) {
die();
}
I added something similar in all my files. Instead of immediately dying though, I have it display a custom 404 error page in order to "hide" them. I'd like to see plugins use standard error pages provided by the core so there's a feeling of consistency.
This is a very bad idea. IMO GL2 should be made flexible enough where other scripts (Gallery, PHPBB, or whatever) can be integrated as plugins many of which do not use this template system.
From the docs, it's not clear whether code from all the plugins are loaded at once. This is a feature I do not like on the current software. Instead of checking one time whether a plugin is activated and only loading the code needed for a page, it checks multiple times and then adds code from all the plugins even if it's not used. I hope this is not the same plan for GL2.
It appears you are making plugin writers create different SQL files to handle different databases. IMO this should be handled by a core class which takes the data provided by the plugin writer and puts it in the proper SQL format for whichever database.
Lastly, may I suggest you look at Mambo to get some ideas on how to make uploading a plugin much simpler for users rather than manually moving files around. Mambo allows a user to upload the plugin as one compressed file and the script handles the decompression.
Tony
Well, being that I am the primary caretaker of GL2 I take most of the responsibility. All I can say is I have a wife, two kid and a day job. Progress is being made of late and you should take this as a good sign. Moving 1.3.x into a maintenance only schedule isn't going to work...we simply have too many users wanting progress to be made while GL2 si going on. So the big issue with time and GL2 is more a case of us finding the time needed. Help is always wanted and if anybody can assist there is plenty of work to go around. Otherwise, you'll just have to be on the time schedule our lives can afford us.
From the docs, it's not clear whether code from all the plugins are loaded at once. This is a feature I do not like on the current software. Instead of checking one time whether a plugin is activated and only loading the code needed for a page, it checks multiple times and then adds code from all the plugins even if it's not used. I hope this is not the same plan for GL2.
It appears you are making plugin writers create different SQL files to handle different databases. IMO this should be handled by a core class which takes the data provided by the plugin writer and puts it in the proper SQL format for whichever database.
Lastly, may I suggest you look at Mambo to get some ideas on how to make uploading a plugin much simpler for users rather than manually moving files around. Mambo allows a user to upload the plugin as one compressed file and the script handles the decompression.
First off, not all plugins will have to use our template system. That is simply the one we will be using and the one we would recommend to others. Not sure where you think we require this but it isn't. However, Flexy is quite capable and we've put a lot of time and thought into the decision to use it.
As far as code loadiing, obviously you haven't read Vinny's comment regarding MVCnPHP. That framework will only load the code needed to process the current request.
A core class for handling SQL would make sense but it isn't trivial. Instead we simply need to insist that we use the SQL standards in place to gaurantee the best cross-dbms compatibility. At the samet time, we need to allow plugin authors to leverage the power for their specific DBMS so I think providing them a way to do that is going to be key. Using PEAR:
![](http://www.geeklog.net/images/smiles/icon_biggrin.gif)
The reason people blame things on previous generations is that there's only one other choice.
Blaine
I found it interesting that they have taken a similar approach with an OO based event driven architecture that also appears to be using a MVC based UI layer.
There has been a lot of re-work and several attempts on the template based design. I believe it is written to support various template libraries. It may be useful to look and learn from some of their work. They are also keeping updated docs and have a very extensive class library.
They also have had UNIT Tests from the beginining. This level is clearly a full-time job for a team of developers.
Geeklog components by PortalParts -- www.portalparts.com
Euan
This sounds like a good idea...
Cheers,
Euan.
-- Heather Engineering
-- No job too small
zachofalltrades
This sounds like a good idea...
Cheers,
Euan.
As a very recent newcomer to GL 1.3, I must add my voice in support of this comment. I've been testing various GPL/LAMP CMS packages for several months, trying to find ONE that will work well for each of several websites that I maintain and will soon be creating. I just would really prefer to become expert at only one CMS -- so I've become a novice at a dozen. It is probably too much to ask to get a one-size fits all, especially when the security and feature set requirements vary from one project to another. But this is where a range of available plugins comes in to save the day.
Unfortunately, plugin installation in GL is more complicated that almost all of the other popular LAMP CMS solutions. Several other systems are simply upload/extract/activate (or even just upload/activate), but with GL it is upload/extract/ copy files or move and rename a subdirectory / copy more files or move and rename another directory / copy more files and or move and rename yet another directory / then activate / and then do some more...
I can handle that, but it takes a while to figure out. I'll be that some users just give up -- and that reduces the potential size of the GL community.
Tony
All the things you guys are complaining about are the same concerns we have but it's nice to have these ideas brough back to light. More input is encouraged. Oh and help, as always, is needed so if any of this sounds like fun let me know.
The reason people blame things on previous generations is that there's only one other choice.
- Normal Topic
- Sticky Topic
- Locked Topic
- New Post
- Sticky Topic W/ New Post
- Locked Topic W/ New Post
- View Anonymous Posts
- Able to post
- Filtered HTML Allowed
- Censored Content