Snap! Websites
An Open Source CMS System in C++
[these are old tables created a while back and they do not correspond the current scheme]
The new scheme will use a similar set of data, but it uses namespaces to distinguish fields from the different plugins. So for example if the title of a page is called "name" and the content module handles the title, then it will be saved in column: "content::name".
Pages are a quite broad concept that is run first by the core of the system and also by additional plug ins that add functionality to the pages. To do so the system and users can create and edit their page types. A type is not specific to a plugins. Instead, as you create a new type, you can decide whether such and such plugin functionality will be available in the page type.
Field Name | Plugin | Comments |
---|---|---|
name | core | The name of the type (page, blog, comment, ad, etc.) |
description | core | Describe what this type is for. |
help | core | Help on how to use this type when creating a new page or editing an existing page of this type. |
plugins | core | List of the plugins used with this page type (i.e. title,content,filter,...) |
trashcan_cleanup | core | How long does a page of this type stays in the trashcan before completely getting removed from the database. Can be set to forever. |
path | path | The path to use to access these pages (i.e. journal/[yyyy][mm][dd]/[title]) |
short_path | path | The path used to access these pages using the short path of the parent pages (i.e. in a book) |
short_cut | shortcut | The path defined for short cuts to this type (if undefined, no short cuts are created.) |
revision_mode | moderation |
How revisions are handled. The following are flags that determine how the revision behaves.
|
revision_moderators | moderation |
List of references to people who are expected to moderate these pages and whether said moderator must moderate a page or is an optional moderator. Moderators can add to the log if they cannot edit themselves. |
revision_minimum | moderation | The minimum number of moderators who need to check a page before it can be published. |
revision_count | core | Number of revisions to keep. Older ones get deleted automatically after that. |
title_label | title | Label for the title field of the page. All pages need a title but it can be automatically generated so this field can be removed by the user. |
content_label | content | Label for the textarea field used to edit the very content of a page. |
teaser_mode | teaser | Whether a teaser is generated and if so how it is generated: none, machine, human, human required; and whether it is part of the content or a completely separate piece of code. |
filter | filter | Defines a default filter. |
required_log | log |
Whether a log is required when:
|
minimum_words | statistics | Force this minimum number of words in the content. |
maximum_words | statistics | Force this maximum number of words in the content. |
maximum_characters | statistics | Force the maximum number of characters so it can be used over micro-blogging system (i.e. 140 over twitter.) |
minimum_title_length | statistics | Force this minimum number of characters in the title. |
maximum_title_length | statistics | Force this maximum number of characters in the title. |
broadcast | rss | Whether these pages are broadcasted on RSS feeds. |
rss_description | rss | Description of this RSS feed (i.e. feed with only these pages, opposed to the website wide RSS feed.) |
blog_pages | blog | Whether these pages make it to the blog roll. |
spam_check | spam | Whether this type of pages need to be checked for spam. Pages that can be created by "anybody" should be scanned by the spam plugins. |
newsletter | news | This is a newsletter. This is also used by the comment plugin for notifications of replies. |
default_update_freq | xmlsitemap | The default amount to save in the update frequency of this page. |
Categorization of a page is done using taxonomies. Taxonomies are themselves pages which are used by other page types to categorize their content. A taxonomy can be categories by another, but it is not possible to create a loop (i.e. taxonomy A categorize taxonomy B and vice versa.)
Field Name | Plugin | Comments |
---|---|---|
taxonomy | taxonomy | The name of the page type used as a taxonomy. |
type | taxonomy | The reference to the page type using this taxonomy. |
auto_tagging | taxonomy | The algorithm used to automatically tag pages of this type. |
minimum_tags | taxonomy | The minimum number of tags to assign to these pages. |
maximum_tags | taxonomy | The maximum number of tags to assign to these pages. |
The following are Page fields used to manage pages in this system:
Field Name | Plugin | Comments |
---|---|---|
type | core | Determine the type of the page. This allows plugins to create their own types and add their own parameters to just those types. (reference to a Page Type) |
created_on | core | Unix timestamp when this page was created. |
status | core |
The status of this page (flags):
|
last_modified_on | core | Unix timestamp when this page was last modified. Note that each revision has its own timestamp. |
author | core |
The reference to the user account representing the person who created this page. This field does not change when someone else edits the page (although it can be changed in case the person who created the page is not the actual author of the content.) In case of a comment, this is the name the user entered as is. |
published_on | core | When this page is expected to be published. This date can be right now (i.e. published_on = created_on), it can be in the future, or it can be zero (unpublished.) This time should never be smaller than created_on unless it is set to 0. |
unpublish_on | core | Some pages should automatically be hidden after a certain amount of time. This represents the time when the page will be unpublished. If this is zero (or undefined) then the page will not be unpublished automatically. |
sent_on | news | The date and time this newsletter was sent to users. Since it takes time to send, this really only indicates the start date of the process. |
branch | core | The current branch (integer.) |
revision | core | The current revision (integer.) |
layout | core | The layout used for this page |
weight | core |
The page weight used to order pages together (i.e. predefined order) In case of comments, the weight can be used along with a poll mechanism to get the best comment at the top of the list. |
place_before | core |
A reference to another page which is placed before this page. For comments this represents the previous comment (chronologically.) For books this represents the previous page. |
place_after | core |
A reference to another page which is placed after this page. For comments this represents the next comment. For books this represents the next page. |
place_under | core |
A reference to another page considered our parent. In case of a comment, this represents the comment being replied to (in case we support threaded comments.) For books this represents the page that includes this chapter. |
place_over | core |
A reference to another page considered our child (one to many or we point to the very first child and then can go through with place_after?) For books this represents the list of chapters appearing in this page. |
show | rss | Whether the page shall appear in your RSS feed. True by default. |
show | blog | True by default and thus shown in the blog roll, can be set to false to hide that specific entry (we could also look into change the page type) |
sticky | blog | If true, show the message at the top of the list of blog posts. |
user | Email attached to this user. | |
password | user | Encrypted user password. This field includes the hashing code if necessary for the password encryption. |
failure_threshold | user | Number of log in attempts that failed. This value is decremented by 1 once a day. If it goes over a certain value, the user gets blocked. |
access_on | user | Last time this user accessed the website while still logged in. |
login_on | user | Last time this user logged in (i.e. "access_on - login_on" represents the amount of time the user spent on the site.) |
timezone | user | The timezone the user is in. |
picture | user |
An avatar for a user account. The page type 'user' is reserved and locked. In this case the title of a 'user' page is the user name and the description his signature. The title is mandatory. The picture can also be used by comments (TBD--should we have a comment::picture field instead?) |
comments | The email address of the user who posted this comment when the user is not logged in (i.e. anonymous posting.) | |
homepage | comments | A URL to the commenter website. |
update_frequency | xmlsitemap | Defines how often a page is being updated (minutes, hours, days, months...) |
A page comes with revision data (what is called "Its own content".) That data is saved in another table to allow for one to multiple reference.
Field Name | Plugin | Comments |
---|---|---|
created_on | core | When this revision was written. |
editor | core | Reference to the person who wrote this revision (i.e. the editor.) |
ip | core | The IP address when the user saved this revision. |
branch | core | The branch of this revision (integer.) |
revision | core | This revision number (integer.) |
moderate | moderation |
Whether this revision requires moderation. This is often true for comments. This can also be used with the spam module (i.e. if someone not so trusted posts something and the spam module thinks it's spam, turn on this flag.) The moderation module will compute when this flag can be turned off and thus the page published. |
moderators | moderation | List of the people who moderated this revision. |
translate | language | Whether this revision needs translations. Whenever the editor of a revision makes changes to a page, he has the choice to say that (1) it is an original, or (2) it is a translation. In case (1), all the revisions in other languages are marked as "need translation" (i.e. translate=1). In case (2), the translate flag is cleared since the editor just did translation work. (Permissions may permit the editor to do just one or the other...) |
language | language |
In which language this revision is written. In case of a user, this defines the preferred language of that user. |
title | title | The title for this page (text, HTML...) |
teaser | content | A teaser for this content. It may be automatically computed. |
teaser_mode | content | How the teaser was generated (computer, human) and whether it needs to be shown before the content in full page mode or not. |
content | content |
The actual content (text, HTML...) Only editors reads this version to let the user make changes with his original. |
filtered_content | content |
The content after we applied the XSS, HTML, etc. filters. We double the size of this table by saving the filtered version, but we then need to filter only on Save() meaning that we save tons on processing time. Viewing uses this version only. |
link | menu | Link to the destination of this menu item. |
filter | filter | HTML Filter to avoid XSS attacks. If not present, the default is to filter as plain text. |
small_title | news |
Displayed in new lists (this is like a teaser title.) The small title could also be used by the menu as the menu label. |
small_teaser | news |
Displayed in RSS like lists of news. The small teaser could also be used by the menu as the menu title. |
By default, pages written by users are given a title used to define a URL to access the page. The path is defined using the path system (and possibly other plug-ins such as the shortcut and canon path plug-ins.) The path defines the following table to save all the paths together. Since one page may have multiple paths, this is separate from the page table. The table is indexed on the path so we can immediately find which signal to send to which plug-in.
Note that paths that are directly linked to a plug-in, such as the /robots.txt path, get assigned a function that is called to generate the content of said page. When a plug-ins is first installed, its database installation function is called which adds its path to the database (i.e. the robotstxt plug-in adds the /robots.txt path and its generation function.)
Later, when a hit is received from the HTTP server, the path plug-in determines which path was entered in the browser, redirects when necessary, and finally finds the corresponding plug-in function and calls it.
Field Name | Plugins | Comments |
---|---|---|
url | path |
The path to the page. This path is also the index in this table so when a user accesses the website he can directly be sent to the proper processing function. We can have different paths defined for the same page: long path, short path, shortcut, and user defined redirects. |
plugin | path | The name of the plug-in responsible for this path (useful to find all redirects or all shortcuts) |
function | path | A fully qualified function name referencing the function of the responsible plug-in this path. |
page | core | A reference to the page this URL points to. |
Page revisions accept logs (internal comments) that the editor and moderators can enter as they see fit. The log is useful to track the changes down.
Field Name | Plugins | Comments |
---|---|---|
reference | log | Reference to the object being discussed in this log. The log can be used for page revisions, pages, etc. although we may not offer them as such at first. |
author | log | Reference to the user writing the log. |
created_on | log | Time when the log entry was entered. |
log | log | The actual log entry. Only text accepted. |
Each page can be categorized by assigning tags to it. The taxonomy plugin makes sure the minimum and maximum defined for each category is respected. The minimum and maximum definitions and the number of tags determines how the user is asked to enter said tags. The following table is attached to each specific page revision.
Categorization is used to attach a comment to a page! The page being commented is the tag that the comment receives, categorizing that comment to that page.
Problem: In the page content in language A the user write the word Foo. This is also a tag so that tag gets assigned to that revision in language A. Someone wants to visit the page in language B. The word Foo is most generally translated Blah. Therefore the tag in question in language B should show Blah as one of the tags. Unfortunately, in this very language B revision, the word Blah doesn't apply. Instead we need the word Bar. One way to palliate to this problem is to add a language in this tag table. However, this translation problem does not apply to all categories. In general it only applies to free tagging categories.
Field Name | Plugin | Comments |
---|---|---|
page_revision | taxonomy | Reference to the page revision to which this tag is attached. |
tag | taxonomy | Reference to a page representing this tag. |
For the news plugin to send emails generated from a given page, it has to know who needs to be emailed. This means it needs to have a list of subscribers and a list of what was sent when to whom.
Field Name | Plugin | Comments |
---|---|---|
subscriber | news | A reference to a page representing a user. |
news | The user email if there isn't a page representing him/her yet. | |
subscription | news |
A reference to a page type representing a newsletter the user is subscribed to. For comments, this is the page that receives comments (i.e. the parent) and not a page type. |
last_email | news | Last time an email was sent to this user. This can be used to avoid sending more than 1 email per day, week, month, etc. (Should we have a way to accumulate email pages and then send them all in one email once we are permitted to send an email again?) |
To determine when a newsletter shall be sent to someone, we want to determine when we last sent an email and when we have permission (as per the user specifications) to send another email. We may want to either accumulate multiple emails or lose the ones we cannot send if our speed is too high to send all the emails to someone.
Field Name | Plugin | Comments |
---|---|---|
subscriber | news | A reference to a subscriber |
news | news | A reference to a page representing a newsletter to be sent to that subscriber. |
sent_on | news | The date when this email was sent. Zero if it wasn't sent yet (and needs to be at some point.) |
Snap! Websites
An Open Source CMS System in C++