more dev docs
This commit is contained in:
parent
9a21716f5e
commit
9147b64625
4 changed files with 119 additions and 140 deletions
|
@ -1,33 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
require_once "core/event.php";
|
||||
|
||||
/**
|
||||
* \page themes Themes
|
||||
*
|
||||
* Each extension has a theme with a specific name -- eg. the extension Setup
|
||||
* which is stored in ext/setup/main.php will have a theme called SetupTheme
|
||||
* stored in ext/setup/theme.php. If you want to customise it, create a class
|
||||
* in the file themes/mytheme/setup.theme.php called CustomSetupTheme which
|
||||
* extends SetupTheme and overrides some of its methods.
|
||||
*
|
||||
* Generally an extension should only deal with processing data; whenever it
|
||||
* wants to display something, it should pass the data to be displayed to the
|
||||
* theme object, and the theme will add the data into the global $page
|
||||
* structure.
|
||||
*
|
||||
* A page should make sure that all the data it outputs is free from dangerous
|
||||
* data by using html_escape(), url_escape(), or int_escape() as appropriate.
|
||||
*
|
||||
* Because some HTML can be placed anywhere according to the theme, coming up
|
||||
* with the correct way to link to a page can be hard -- thus we have the
|
||||
* make_link() function, which will take a path like "post/list" and turn it
|
||||
* into a full and correct link, eg /myboard/post/list, /foo/index.php?q=post/list,
|
||||
* etc depending on how things are set up. This should always be used to link
|
||||
* to pages rather than hardcoding a path.
|
||||
*
|
||||
* Various other common functions are available as part of the Themelet class.
|
||||
*/
|
||||
|
||||
abstract class PageMode
|
||||
{
|
||||
const REDIRECT = 'redirect';
|
||||
|
|
|
@ -1,73 +1,4 @@
|
|||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* \page eande Events and Extensions
|
||||
*
|
||||
* An event is a little blob of data saying "something happened", possibly
|
||||
* "something happened, here's the specific data". Events are sent with the
|
||||
* send_event() function. Since events can store data, they can be used to
|
||||
* return data to the extension which sent them, for example:
|
||||
*
|
||||
* \code
|
||||
* $tfe = send_event(new TextFormattingEvent($original_text));
|
||||
* $formatted_text = $tfe->formatted;
|
||||
* \endcode
|
||||
*
|
||||
* An extension is something which is capable of reacting to events.
|
||||
*
|
||||
*
|
||||
* \page hello The Hello World Extension
|
||||
*
|
||||
* \code
|
||||
* // ext/hello/main.php
|
||||
* public class HelloEvent extends Event {
|
||||
* public function __construct($username) {
|
||||
* $this->username = $username;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public class Hello extends Extension {
|
||||
* public function onPageRequest(PageRequestEvent $event) { // Every time a page request is sent
|
||||
* global $user; // Look at the global "currently logged in user" object
|
||||
* send_event(new HelloEvent($user->name)); // Broadcast a signal saying hello to that user
|
||||
* }
|
||||
* public function onHello(HelloEvent $event) { // When the "Hello" signal is recieved
|
||||
* $this->theme->display_hello($event->username); // Display a message on the web page
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ext/hello/theme.php
|
||||
* public class HelloTheme extends Themelet {
|
||||
* public function display_hello($username) {
|
||||
* global $page;
|
||||
* $h_user = html_escape($username); // Escape the data before adding it to the page
|
||||
* $block = new Block("Hello!", "Hello there $h_user"); // HTML-safe variables start with "h_"
|
||||
* $page->add_block($block); // Add the block to the page
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ext/hello/test.php
|
||||
* public class HelloTest extends SCorePHPUnitTestCase {
|
||||
* public function testHello() {
|
||||
* $this->get_page("post/list"); // View a page, any page
|
||||
* $this->assert_text("Hello there"); // Check that the specified text is in that page
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // themes/mytheme/hello.theme.php
|
||||
* public class CustomHelloTheme extends HelloTheme { // CustomHelloTheme overrides HelloTheme
|
||||
* public function display_hello($username) { // the display_hello() function is customised
|
||||
* global $page;
|
||||
* $h_user = html_escape($username);
|
||||
* $page->add_block(new Block(
|
||||
* "Hello!",
|
||||
* "Hello there $h_user, look at my snazzy custom theme!"
|
||||
* );
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Extension
|
||||
*
|
||||
|
|
119
docs/DEV.md
119
docs/DEV.md
|
@ -1,5 +1,121 @@
|
|||
# Development Info
|
||||
|
||||
## Themes
|
||||
|
||||
Theme customisation is done by creating files in `themes/<theme name>`.
|
||||
|
||||
The general idea with Shimmie theming is that each `Extension` will add a
|
||||
set of `Block`s to the `Page`, then the `Page` is in charge of deciding
|
||||
how they should be laid out, what they should look like, etc.
|
||||
|
||||
The overall layout is controlled by `page.class.php`, where the `render()`
|
||||
function will take a look at all of the separate `Block`s and turn them
|
||||
into the final rendered HTML.
|
||||
|
||||
Individual `Extension`s will render their content by calling functions
|
||||
in `ext/<extension name>/theme.php` - for example the code in
|
||||
`ext/comment/main.php` will display a list of comments by calling
|
||||
`display_comment_list()` from `ext/comment/theme.php`.
|
||||
|
||||
If a theme wants to customise how the comment list is rendered, it would
|
||||
do so by creating an override file in `themes/<theme name>/comment.theme.php`
|
||||
with contents like:
|
||||
|
||||
```
|
||||
class CustomCommentTheme extends CommentTheme {
|
||||
public function display_comment_list(
|
||||
array $images,
|
||||
int $page_number,
|
||||
int $total_pages,
|
||||
bool $can_post
|
||||
) {
|
||||
[... render the comment list however you like here ...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Events and Extensions
|
||||
|
||||
An event is a little blob of data saying "something happened", possibly
|
||||
"something happened, here's the specific data". Events are sent with the
|
||||
`send_event()` function. Since events can store data, they can be used to
|
||||
return data to the extension which sent them, for example:
|
||||
|
||||
```
|
||||
$tfe = send_event(new TextFormattingEvent($original_text));
|
||||
$formatted_text = $tfe->formatted;
|
||||
```
|
||||
|
||||
An extension is something which is capable of reacting to events.
|
||||
|
||||
|
||||
### Useful Variables
|
||||
|
||||
There are a few global variables which are pretty essential to most extensions:
|
||||
|
||||
* $config -- some variety of Config subclass
|
||||
* $database -- a Database object used to get raw SQL access
|
||||
* $page -- a Page to holds all the loose bits of extension output
|
||||
* $user -- the currently logged in User
|
||||
* $cache -- an optional cache for fast key / value lookups (eg Memcache)
|
||||
|
||||
Each of these can be imported at the start of a function with eg "global $page, $user;"
|
||||
|
||||
|
||||
### The Hello World Extension
|
||||
|
||||
Here's a simple extension which listens for `PageRequestEvent`s, and each time
|
||||
it sees one, it sends out a `HelloEvent`.
|
||||
|
||||
```
|
||||
// ext/hello/main.php
|
||||
public class HelloEvent extends Event {
|
||||
public function __construct($username) {
|
||||
$this->username = $username;
|
||||
}
|
||||
}
|
||||
|
||||
public class Hello extends Extension {
|
||||
public function onPageRequest(PageRequestEvent $event) { // Every time a page request is sent
|
||||
global $user; // Look at the global "currently logged in user" object
|
||||
send_event(new HelloEvent($user->name)); // Broadcast a signal saying hello to that user
|
||||
}
|
||||
public function onHello(HelloEvent $event) { // When the "Hello" signal is recieved
|
||||
$this->theme->display_hello($event->username); // Display a message on the web page
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
// ext/hello/theme.php
|
||||
public class HelloTheme extends Themelet {
|
||||
public function display_hello($username) {
|
||||
global $page;
|
||||
$h_user = html_escape($username); // Escape the data before adding it to the page
|
||||
$block = new Block("Hello!", "Hello there $h_user"); // HTML-safe variables start with "h_"
|
||||
$page->add_block($block); // Add the block to the page
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
// themes/mytheme/hello.theme.php
|
||||
public class CustomHelloTheme extends HelloTheme { // CustomHelloTheme overrides HelloTheme
|
||||
public function display_hello($username) { // the display_hello() function is customised
|
||||
global $page;
|
||||
$h_user = html_escape($username);
|
||||
$page->add_block(new Block(
|
||||
"Hello!",
|
||||
"Hello there $h_user, look at my snazzy custom theme!"
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Cookies
|
||||
|
||||
ui-\* cookies are for the client-side scripts only; in some configurations
|
||||
(eg with varnish cache) they will be stripped before they reach the server
|
||||
|
||||
|
@ -16,5 +132,8 @@ themes, be careful with these, and avoid styling them, eg:
|
|||
- shm-clink = a link to a comment, flash the target element when clicked
|
||||
* data-clink-sel
|
||||
|
||||
|
||||
## Fin
|
||||
|
||||
Please tell me if those docs are lacking in any way, so that they can be
|
||||
improved for the next person who uses them
|
||||
|
|
44
index.php
44
index.php
|
@ -1,48 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* \mainpage Shimmie2 / SCore Documentation
|
||||
*
|
||||
* SCore is a framework designed for writing flexible, extendable applications.
|
||||
* Whereas most PHP apps are built monolithically, score's event-based nature
|
||||
* allows parts to be mixed and matched. For instance, the most famous
|
||||
* collection of score extensions is the Shimmie image board, which includes
|
||||
* user management, a wiki, a private messaging system, etc. But one could
|
||||
* easily remove the image board bits and simply have a wiki with users and
|
||||
* PMs; or one could replace it with a blog module; or one could have a blog
|
||||
* which links to images on an image board, with no wiki or messaging, and so
|
||||
* on and so on...
|
||||
*
|
||||
* Dijkstra will kill me for personifying my architecture, but I can't think
|
||||
* of a better way without going into all the little details.
|
||||
* There are a bunch of Extension subclasses, they talk to each other by sending
|
||||
* and receiving Event subclasses. The primary driver for each conversation is the
|
||||
* initial PageRequestEvent. If an Extension wants to display something to the
|
||||
* user, it adds a block to the Page data store. Once the conversation is over, the Page is passed to the
|
||||
* current theme's Layout class which will tidy up the data and present it to
|
||||
* the user. To see this in a more practical sense, see \ref hello.
|
||||
*
|
||||
* To learn more about the architecture:
|
||||
*
|
||||
* \li \ref eande
|
||||
* \li \ref themes
|
||||
*
|
||||
* To learn more about practical development:
|
||||
*
|
||||
* \li \ref scglobals
|
||||
* \li \ref unittests
|
||||
*
|
||||
* \page scglobals SCore Globals
|
||||
*
|
||||
* There are four global variables which are pretty essential to most extensions:
|
||||
*
|
||||
* \li $config -- some variety of Config subclass
|
||||
* \li $database -- a Database object used to get raw SQL access
|
||||
* \li $page -- a Page to holds all the loose bits of extension output
|
||||
* \li $user -- the currently logged in User
|
||||
*
|
||||
* Each of these can be imported at the start of a function with eg "global $page, $user;"
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
||||
* Make sure that shimmie is correctly installed *
|
||||
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
|
Reference in a new issue