/home/a/aquarion/sites/www.aquarionics.com/epistula/include/class.php
All my code (That is, anything not in the "Others" list on the right) is BSD licenced.
You can also view this page as text/plain or colour-coded source
<?PHP
/*******************************************************************************
Classes
********************************************************************************
The classes, including the display class (which is dreadfully sick),
the syndication formats and other stuff
TODO: use a templating system, for fucks sake
$Id: class.php,v 1.4 2004/08/17 19:59:35 aquarion Exp $
$log$
*******************************************************************************/
include("classes/html.class.php");
class Epistula {
##--------------+
#| Field |
#+--------------+
#| id |
#| title |
#| date_created |
#| date_edited |
#| author |
#| content |
#+--------------#
var $id;
var $title;
var $date_created;
var $author;
var $content;
var $description;
var $location;
var $format;
var $cats;
var $fields;
var $actions;
var $filters;
var $trackbacks;
var $debug;
var $_table;
var $_type;
function Epistula($id=0) {
global $_EP;
$this->_type = $this->_table = get_class($this);
#$this->cats = array();
$this->fields = array();
$this->trackbacks = array();
$this->id = 0;
if (isset($_COOKIE['location'])){
$this->location = $_COOKIE['location'];
} else {
$this->location = $_EP['location'];
}
$this->date_created = "NOW()";
$this->date_edited = "NOW()";
$this->author = 0;
$this->format = "textile";
$this->status = "0";
$this->debug = array("Created ".$this." object");
if ($id != 0){
$this->loadData($id);
}
// Set up local category cache
$this->debug[] = "Set up local category cache";
$q = "select * from category order by name";
$res = safequery($q, false); // don't panic on fail.
while ($feline = mysql_fetch_assoc($res)){
$feline['oldstatus'] = false;
$feline['newstatus'] = false;
$this->cats[$feline['id']] = $feline;
}
// End
$fields = mysql_list_fields($_EP['dbname'], get_class($this));
$columns = mysql_num_fields($fields);
for ($i = 0; $i < $columns; $i++) {
$this->fields[] = array(mysql_field_name($fields, $i), mysql_field_type($fields, $i));
}
$actions = array();
$filters = array();
$this->setActionsFilters();
}
/**
void function loadData (int id)
Load the data from id $id into the object
*/
function loadData($id){
$this->debug[] = "Loading data from id ".$id;
$res = safequery("Select *, unix_timestamp(date_created) as created_epoch from ".get_class($this)." where id = ".$id);
$idexist = mysql_num_rows($res);
if ($idexist != 0){
$row = mysql_fetch_assoc($res);
foreach ($row as $key=>$value){
$this->$key = $value;
}
$cats = getCat(get_class($this),$id);//full version of all cats.
foreach ($cats as $cat){
$this->cats[$cat['id']]['oldstatus'] = true;
$this->cats[$cat['id']]['newstatus'] = true;
}
} else { // Attempt to get id broke. Table or ID doesn't exist
$this->debug[] = "** Couldn't load ".get_class($this)."-".$id." from DB, object is empty.";
return false;
}
} // end func load Data
function setActionsFilters(){
$this->debug[] = "Set defaults for actions & filters";
$actions = array(
array("pingback" => true),
array("pingThings" => true)
);
$filters = array(
array("html" => false),
array("tagify" => true)
);
}
function validate(){
$this->debug[] = "Validating...";
$required = array("title", "author", "content");
foreach ($required as $check){
if (isset($this->$required)){
$error .= ucwords($required)." cannot be empty\n";
}
}
$catcount = 0;
foreach($this->cats as $cat){
if ($cat['newstatus']){
$catcount++;
}
}
if ($catcount == 0){
$error .= "Must set at least one category";
}
#print_r($this);
if (count($error) == 0){
$this->debug[] = "Validation sucessful";
return array(true,$error);
} else {
$this->debug[] = "Validation failed.";
return array(false,$error);
}
}
function save($notreally=false){
if ($this->title == ""){
$this->title = "Untitled";
}
$this->debug[] = "Saving object to database";
$this->content = addslashes($this->doFilters(stripslashes($this->content)));
$this->description = addslashes($this->doFilters(stripslashes($this->description)));
$table = get_class($this);
$validate = $this->validate();
if (!$validate[0]){
$this->debug[] = $validate[1];
return array(false,$validate[1]);
} elseif($this->id != 0) {
$this->debug[] = "ID set, creating update query";
$query = "update ".$table." set ";
$index_check = count($this->fields)-1;
$index_count = 0;
foreach ($this->fields as $field){
if ($field[0] == "date_created" || $field[0] == "date_edited" || $field[0] == "id") {
true;
} else {
if ($field[1] == "blob" || $field[1] == "string"){
$query .= $field[0]." = \"".$this->$field[0]."\"";
} else {
$query .= $field[0]." = ".$this->$field[0];
}
if ($index_count != $index_check){
$query .= ", ";
}
}
$index_count++;
}
$query .= " where id=".$this->id;
#$this->debug[] = "Build query: ".$query;
if ($notreally){
$this->debug[] = "Not saved to DB, as requested";
$this->saveCats("notreally");
$return = $query;
} else {
$this->debug[] = "Saving to DB...";
#$this->debug[] = "<pre>".print_r_to_var($this)."</pre>";
safequery($query, false);
$this->saveCats();
$this->doActions();
$delc_log = deleteCache($this->id,$table);
$this->debug[] = "Deleting Cache Files";
#foreach ($delc_log as $entry) {
# $this->debug[] = $entry;
#}
$return = true;
}
} else {
$this->debug[] = "ID not set, creating insert query";
$query = "insert into ".$table." (";
$fields = "";
$values = "";
$index_check = count($this->fields)-1;
$index_count = 0;
foreach ($this->fields as $field){
$fields .= $field[0];
if ($field[1] == "blob" || $field[1] == "string"){
$values .="\"".$this->$field[0]."\"";
} else {
$values .=$this->$field[0];
}
if ($index_count != $index_check){
$fields .= ", ";
$values .= ", ";
}
$index_count++;
}
$query .= $fields.") values (".$values.")";
#$this->debug[] = "Created query ".$query;
if ($notreally){
$this->debug[] = "Not saved to DB, as requested";
$return = $query."\n";
$this->debug[] = $query."\n";
$return .= $this->saveCats("notreally");
} else {
$this->debug[] = "Saving to DB...";
safequery($query, true);
$this->id = mysql_insert_id();
$this->saveCats();
$this->doActions();
$delc_log = deleteCache($this->id,$table);
foreach ($delc_log as $entry) {
$this->debug[] = $entry;
}
}
}
return $return;
}
function saveCats($notreally=false){
$this->debug[] = "Saving categories to db...";
foreach($this->cats as $cat){
if ($cat['newstatus'] != $cat['oldstatus']){
if ($cat['newstatus']){ // if it's now categorised as that
$query = "insert into cat_links (page_id, page_type, cat_id)"
." values (".$this->id.", \"".get_class($this)."\", ".$cat['id'].")";
$this->debug[] = "Added object to ".$cat['name'];
} else {
$query = "delete from cat_links where "
." page_type = \"".get_class($this)."\" and page_id = ".$this->id;
$this->debug[] = "Deleted object from ".$cat['name'];
}
if ($notreally){
return $query;
} else {
safequery($query, false);
}
}
}
}
function remove(){
$item = get_class($this);
$id = $this->id;
$queries = array(
"delete from $item where id = $id",
"delete from cat_links where page_type = \"$item\" and page_id = \"$id\"",
"delete from attachment where page_type = \"$item\" and page_id = \"$id\"",
"delete from crossreference where attachfromtype = \"$item\" and attachfromid = \"$id\"",
"delete from crossreference where attachtotype = \"$item\" and attachtoid = \"$id\"",
"delete from comment where thread_id = \"".$item."-".$id."\"");
deleteCache($id,$item);
foreach ($queries as $query){
safequery($query);
}
}
function doFilters($content){
$this->debug[] = "Applying filters:";
if ($this->filters['htmlize'] == true) {
$content = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]","<a href=\"\\0\" class=\"commentlink\">\\0</a>", $content);
$content = nl2br($content);
}
if ($this->filters['tagify'] == true) {
$content = tagifythis($content);
}
return $content;
}
function doActions(){
global $_EP;
$this->debug[] = "Doing actions:";
if ($this->actions['pingThings'] == true) {
$return = pingServices();
foreach ($return as $name => $ping){
$this->debug[] = "Sending ping to ".$name;
$this->debug[] = $ping[1];
}
}
if ($this->actions['pingBack']) {
$this->debug[] = "Sending pingbacks - ".date("H:i");
$content = process($this->content, $this->format);
$links = liftLinks(stripslashes($this->content));
pingback($links, get_class($this), $this->id, true);
}
$this->debug[] = "Done actions - ".date("H:i");;
}
function display($path){
}
}
class journal extends Epistula {
}
class article extends Epistula {
var $status;
}
class writing extends Epistula {
}
class moblog extends Epistula {
}
class twitter extends Epistula {
}
class item extends Epistula { // Obsolete
}
/**
Context of the class
Short description.
*/
class syndication
{
var $title;
var $url;
var $description;
var $author;
var $email;
var $items;
/**
void function syndication (void)
Constructor for Syndication Class
*/
function syndication()
{
global $_EP;
$this->title = $_EP['book'];
$this->url = $_EP['url'];
$this->description = "Descriptionless Item";
$this->author = "Aquarion";
$this->email = $_EP['admin'];
$this->items = array();
} // end func
/**
void function (void)
Short description.
*/
function build()
{
$out = "Syndication for ".$this->author." (".$this->email."), who stupidly asked for a syndication without a corresponding class.\n";
$out .= "Lets all laugh at ".$this->author.", shall we? and not read.".$this->title." at ".$this->url."\n";
return $out;
} // end func
} // end class
/*
Necho Cut 1, 2003-07-03
*/
class necho extends syndication
{
function build()
{
// global $_EP;
// $this->title = $_EP['book'];
// $this->url = $_EP['url'];
// $this->description = "Descriptionless Item";
// $this->author = "Aquarion";
// $this->email = $_EP['admin'];
// $this->items = array();
global $_EP;
$dateformat = "Y-m-d\TH:i:00O";
$out = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
$out .= "<feed xmlns=\"http://example.com/newformat#\" xmlns:ent=\"http://www.purl.org/NET/ENT/1.0/\" version=\"1.0\">\n"
."<title>".$_EP['book']."</title>\n"
."<subtitle>".$this->description."</subtitle>\n"
."<link>".$_EP['url']."</link>\n"
."<modified>".date($dateformat)."</modified>\n";
foreach ($this->items as $item){
# title url id content type epoch
if ($item['link']){
$guid = $item['link'];
} else {
$guid = getPermalink($item['epistulatype'],$item['id']);
}
$trackback = $_EP['url']."/trackback/".$item['epistulatype']."/".$item['id'];
#$comments = count(get_comments_array($item['epistulatype']."-".$item['id']));
$categories = getCat($item['epistulatype'],$item['id']);
$text = process($item['content'], $item['format']);
if ($item['description'] == ""){
$desc = htmlspecialchars(break_string(strtr($text,"’","'"),400),ENT_NOQUOTES);
} else {
$desc = strip_tags(process($item['description'], $item['format']));
}
$out .= "\n<entry>\n"
."\t<title>".htmlspecialchars($item['title'],ENT_NOQUOTES)."</title>\n"
."\t<link>".$guid."</link>\n"
."\t<id>".$_EP['url']."/".$item['epistulatype']."-".$item['id']."</id>\n"
# ."\t<comments>".$guid."</comments>\n"
."\t<summary>".$desc."</summary>\n"
."\t<created>".date($dateformat,$item['epoch'])."</created>"
."\t<issued>".date($dateformat,$item['epoch'])."</issued>"
."\t<modified>".date($dateformat,$item['update_epoch'])."</modified>"
. "\t<content type=\"text/html\"><![CDATA[".strtr($text,"’","'")."]]></content>\n";
foreach ($item['attachments'] as $attachment){
$out .= "<content type=\"".$attachment['mimetype']." "
."src=\"".$_EP['url']."/".$attachment['file']."\" "
# ."length=\"".$attachment['size']."\" "
."\"/>\n";
}
foreach ($categories as $cat){
$out .= "\t<ent:topic>".$cat['name']."</ent:topic>\n";
}
# $out .="\t<slash:comments>".$comments."</slash:comments>\n"
# ."\t<slash:section>".$item['epistulatype']."</slash:section>\n"
# ."\t<trackback:ping>".$trackback."</trackback:ping>\n"
# ."</item>\n";
$out .="</entry>\n";
}
$out .= "</feed>";
return $out;
}
}
/**
Context of the class
Short description.
*/
class rss2 extends syndication
{
/**
string function build (void)
Returns a valid RSS2 feed.
*/
function build()
{
if (PHP_VERSION >= 5){
$dateformat = "c";
$tzd = ""; // Don't need TimeZone Data
} else {
$dateformat = "Y-m-d\TH:i:00";
$mod = date("Z")%(60*60);
if ($mod != 0){
$semi = ":00";
} else {
$semi = ":30";
}
$tzd = sprintf("%+03d",(date("Z")/(60*60))).$semi;
}
// <dc:date>2004-09-15T11:10:00+0000</dc:date>
// 2002-10-02T10:00:00-05:00
global $_EP;
$out ="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
."<rss version=\"2.0\" \n"
." xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n"
." xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\"\n"
." xmlns:admin=\"http://webns.net/mvcb/\"\n"
." xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
." xmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\n"
." xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n"
." xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">\n"
."<channel>\n"
."<title>".$this->title."</title>\n"
."<link>".$this->url."</link>\n"
."<description>".htmlspecialchars($this->description)."</description>\n"
."<dc:language>en-gb</dc:language>\n"
."<dc:creator>".$this->author." (".$this->email.")</dc:creator>\n"
."<dc:rights>Copyright ".date("Y")." ".$this->author."</dc:rights>\n"
."<dc:date>".date($dateformat).$tzd."</dc:date>\n"
."<admin:generatorAgent rdf:resource=\"http://www.aquarionics.com/epistula/?v=".$_EP['version']."\" />\n"
."<admin:errorReportsTo rdf:resource=\"mailto:".$_EP['admin']."\"/>\n"
."<sy:updatePeriod>daily</sy:updatePeriod>\n"
."<sy:updateFrequency>8</sy:updateFrequency>\n"
."<sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>\n";
foreach ($this->items as $item){
# title url id content type epoch
if ($item['link']){
$guid = $item['link'];
} else {
$guid = getPermalink($item['epistulatype'],$item['id']);
}
$trackback = $_EP['url']."/trackback/".$item['epistulatype']."/".$item['id'];
$comments = count(get_comments_array($item['epistulatype']."-".$item['id']));
$categories = getCat($item['epistulatype'],$item['id']);
$text = process($item['content'], $item['format']);
if ($item['description'] == ""){
$desc = htmlspecialchars(break_string(strtr($text,"’","'"),400),ENT_NOQUOTES);
} else {
$desc = htmlspecialchars(strip_tags(process($item['description'], $item['format'])));
}
if ($item['display'] == "description"){
$text = $desc;
}
$out .="<item>\n"
."\t<title>".htmlspecialchars($item['title'],ENT_NOQUOTES)."</title>\n"
."\t<link>".$guid."</link>\n"
."\t<comments>".$guid."</comments>\n"
."\t<description>".$desc."</description>\n"
."\t<guid isPermaLink=\"true\">".$guid."</guid>\n";
$out .= "\t<content:encoded><![CDATA[".strtr($text ,"’","'")."]]></content:encoded>\n"
."\t<dc:date>".date($dateformat,$item['epoch']).$tzd."</dc:date>\n";
foreach ($categories as $cat){
$out .= "\t<dc:subject>".$cat['name']."</dc:subject>\n";
}
foreach ($item['attachments'] as $attachment){
$out .= "<enclosure "
."url=\"".$_EP['url']."/".$attachment['file']."\" "
."length=\"".$attachment['size']."\" "
."type=\"".$attachment['mimetype']."\"/>\n";
}
$out .="\t<slash:comments>".$comments."</slash:comments>\n"
."\t<slash:section>".$item['epistulatype']."</slash:section>\n"
."\t<trackback:ping>".$trackback."</trackback:ping>\n"
."</item>\n";
}
$out .= "</channel>\n"
."</rss>";
return $out;
} // end func
} // end class
/**
Context of the class
Short description.
*/
class rss extends syndication
{
/**
void function build (void)
Create and return RSS feed.
*/
function build()
{
global $_EP;
$out ="<?xml version=\"1.0\"?>\n"
."<?xml-stylesheet type=\"text/xsl\" href=\"/assets/rss.xsl\"?>"
."<rss version=\"0.92\">\n"
."<channel>\n"
."<title>".$this->title."</title>\n"
."<link>".$this->url."</link>\n"
."<description>".$this->description."</description>\n"
."<language>en-gb</language>\n"
."<managingEditor>".$this->author." (".$this->email.")</managingEditor>\n"
."<webMaster>Site Admin (".$_EP['admin'].")</webMaster>\n"
."<lastBuildDate>".date("D, d M Y H:i:00 O")."</lastBuildDate>\n" # Fri, 13 Apr 2001 19:23:02 GMT
."<docs>http://backend.userland.com/rss092</docs>\n";
foreach ($this->items as $item){
# title url id content type epoch
#$guid = $_EP['url']."/".$item['epistulatype']."/id/".$item['id'];
if ($item['link']){
$guid = $item['link'];
} else {
$guid = getPermalink($item['epistulatype'],$item['id']);
}
$text = process($item['content'], $item['format']);
if ($item['description'] == ""){
$desc = htmlspecialchars(break_string(strtr($text,"’","'"),400),ENT_NOQUOTES);
} else {
$desc = strip_tags(process($item['description'], $item['format']));
}
$out .="<item>\n"
."\t<title>".htmlspecialchars($item['title'],ENT_NOQUOTES)."</title>\n"
."\t<link>".$guid."</link>\n"
."\t<description>".$desc."</description>\n";
if (is_array($item['attachments'])){
foreach ($item['attachments'] as $attachment){
$out .= "<enclosure "
."url=\"".$_EP['url']."/".$attachment['file']."\" "
."length=\"".$attachment['size']."\" "
."type=\"".$attachment['mimetype']."\"/>\n";
}
}
$out .= "</item>\n";
}
$out .= "</channel>\n"
."</rss>";
return $out;
} // end func
} // end class
/**
Context of the class
Short description.
*/
class cdf extends syndication // Microsoft Common Data Format.
/*
XML ENCODING="UTF-8" VERSION="1.0"
<CHANNEL HREF="http://domain/folder/pageOne.extension"
BASE="http://domain/folder/"
LASTMOD="1998-11-05T22:12"
PRECACHE="YES"
LEVEL="0">
<TITLE>Title of your Channel</TITLE>
<ABSTRACT>Synopsis of your channel's contents.</ABSTRACT>
<SCHEDULE>
<INTERVALTIME DAY="14"/>
</SCHEDULE>
<LOGO HREF="wideChannelLogo.gif" STYLE="IMAGE-WIDE"/>
<LOGO HREF="imageChannelLogo.gif" STYLE="IMAGE"/>
<LOGO HREF="iconChannelLogo.gif" STYLE="ICON"/>
<ITEM HREF="pageTwo.extension"
LASTMOD="1998-11-05T22:12"
PRECACHE="YES"
LEVEL="1">
<TITLE>Page Two's Title</TITLE>
<ABSTRACT>Synopsis of Page Two's contents.</ABSTRACT>
<LOGO HREF="pageTwoLogo.gif" STYLE="IMAGE"/>
<LOGO HREF="pageTwoLogo.gif" STYLE="ICON"/>
</ITEM>
</CHANNEL>
*/
{
/**
void function (void)
Short description.
*/
function build()
{
global $_EP;
$out ="<?xml version=\"1.0\"?>\n"
."<CHANNEL HREF=\"".$this->url."\" "
."BASE=\"".$this->url."\" "
."LASTMOD=\"".date("Y-m-d\Th:i")."\" "
."PRECACHE=\"YES\" "
."LEVEL=\"0\">\n"
."\t<TITLE>".$this->title."</TITLE>\n"
."\t<ABSTRACT>".$this->description."</ABSTRACT>\n"
."\t<SCHEDULE>\n"
."\t\t<INTERVALTIME HOUR=\"1\"/>\n"
."\t</SCHEDULE>\n";
foreach ($this->items as $item){
# title url id content type epoch
#$guid = $_EP['url']."/".$item['epistulatype']."/id/".$item['id'];
if ($item['link']){
$guid = $item['link'];
} else {
$guid = getPermalink($item['epistulatype'],$item['id']);
}
$text = process($item['content'], $item['format']);
if ($item['description'] == ""){
$desc = strtr(break_string($text,400), "ãäåçèéêëìíîïðñòóôõö÷øùúûüýêë’", "aaaceeeeiiiionooooo/ouuuuyee'");
} else {
$desc = strip_tags(process($item['description'], $item['format']));
}
$desc = htmlspecialchars(strtr($desc,"’","'"),ENT_NOQUOTES);
$title = htmlspecialchars(strtr($item['title'],"’","'"),ENT_NOQUOTES);
$out .="\t<ITEM href=\"".$guid."\" "
."LASTMOD=\"".date("Y-m-d\Th:i",$item['epoch'])."\" "
."PRECACHE=\"YES\" "
."LEVEL=\"0\">\n"
."\t\t<TITLE>".$title."</TITLE>\n"
."\t\t<ABSTRACT>".$desc."</ABSTRACT>\n";
$out .= "\t</ITEM>\n";
}
$out .= "</CHANNEL>\n";
return $out;
} // end func
} // end class
/**
Context of the class
Short description.
*/
class esf extends syndication
{
/**
void function (void)
Short description.
*/
function build()
{
global $_EP;
$out ="#".$this->title." Newsfeed, in Episula Syndication Feed format (ESF)\n"
."#http://www.aquarionics.com/nodes/index.php?name=esf\n"
."title\t".$this->title."\n"
."contact\t".$this->email." (".$this->author.")\n"
."link\t".$this->url."\n\n";
foreach ($this->items as $item){
# title url id content type epoch
if ($item['link']){
$guid = $item['link'];
} else {
$guid = getPermalink($item['epistulatype'],$item['id']);
}
$out .=$item['epoch']."\t"
.$item['title']."\t"
.$guid."\t\n";
}
return $out;
} // end func
} // end class
/*
// The great generic form creation thing. Started at 3am 10/01/2003
class form{
var $action;
var $method;
var $name;
var $items;
var $title;
function form($name = "form",$method = "post" ,$action=$_SERVER['PHP_SELF']){
$this->name=$name;
$this->method=$method;
$this->action=$action;
$this->action=array();
$this->title=false;
}
function buildHtml(){
// Buttons
submit
reset
// Checkboxen
label name checked
r
}
}*/
/*
Spelchecker server code by Simon Willison,
http://simon.incutio.com/archive/2003/03/18/#phpAndJavascriptSpellChecker
*/
class SpellChecker {
var $command;
var $text;
var $errors = array();
function SpellChecker($command = 'ispell') {