aboutsummaryrefslogtreecommitdiff
path: root/ratatoeskr
diff options
context:
space:
mode:
authorKevin Chabowski <kevin@kch42.de>2011-10-12 21:57:41 +0200
committerKevin Chabowski <kevin@kch42.de>2011-10-12 21:57:41 +0200
commit74cf8718cd1a09ac159e933c898ede1a9d474679 (patch)
treeefa5af61364bace8e7a5e7b0745728c5e51328cd /ratatoeskr
parent7d15e81a023946d8265f1bf684f4b9b52b7bfa10 (diff)
downloadratatoeskr-cms-74cf8718cd1a09ac159e933c898ede1a9d474679.tar.gz
ratatoeskr-cms-74cf8718cd1a09ac159e933c898ede1a9d474679.tar.bz2
ratatoeskr-cms-74cf8718cd1a09ac159e933c898ede1a9d474679.zip
Cleaned up the urltitle/-name mess. Improved models.php.
* Replaced all urlitle stuff with urlname stuff. Before this, both names were used for the same thing which was f*cking confusing! * Added possible throwing of AlreadyExistError for already existing urlname and for all save() methods where uniqueness could be broken. * Also added kses-powered HTML filtering for comments.
Diffstat (limited to 'ratatoeskr')
-rw-r--r--ratatoeskr/frontend.php152
-rw-r--r--ratatoeskr/setup/create_tables.php2
-rw-r--r--ratatoeskr/sys/models.php150
3 files changed, 224 insertions, 80 deletions
diff --git a/ratatoeskr/frontend.php b/ratatoeskr/frontend.php
index ffb2941..c1daeb9 100644
--- a/ratatoeskr/frontend.php
+++ b/ratatoeskr/frontend.php
@@ -13,6 +13,7 @@ require_once(dirname(__FILE__) . "/sys/utils.php");
require_once(dirname(__FILE__) . "/languages.php");
require_once(dirname(__FILE__) . "/sys/models.php");
require_once(dirname(__FILE__) . "/sys/textprocessors.php");
+require_once(dirname(__FILE__) . "/libs/kses.php");
/*
* Function: section_transform_ste
@@ -71,7 +72,7 @@ function tag_transform_ste($tag, $lang)
* Returns:
* Array with these fields:
* * id
- * * urltitle
+ * * urlname
* * fullurl
* * title
* * text
@@ -89,12 +90,12 @@ function article_transform_ste($article, $lang)
$languages = array();
foreach($article->title as $language => $_)
- $languages[$language] = "$rel_path_to_root/$language/{$article->section->name}/{$article->urltitle}";
+ $languages[$language] = "$rel_path_to_root/$language/{$article->section->name}/{$article->urlname}";
return array(
"id" => $article->get_id(),
- "urltitle" => $article->urltitle,
- "fullurl" => htmlesc("$rel_path_to_root/$lang/{$article->section->name}/{$article->urltitle}"),
+ "urlname" => $article->urlname,
+ "fullurl" => htmlesc("$rel_path_to_root/$lang/{$article->section->name}/{$article->urlname}"),
"title" => htmlesc($article->title[$lang]->text),
"text" => textprocessor_apply_translation($article->text[$lang]),
"excerpt" => textprocessor_apply_translation($article->excerpt[$lang]),
@@ -108,6 +109,52 @@ function article_transform_ste($article, $lang)
);
}
+function comment_filter($html)
+{
+ return kses($html, array(
+ "a" => array("href" => 1, "hreflang" => 1, "title" => 1, "rel" => 1, "rev" => 1),
+ "b" => array(),
+ "i" => array(),
+ "u" => array(),
+ "strong" => array(),
+ "em" => array(),
+ "p" => array("align" => 1),
+ "br" => array(),
+ "abbr" => array(),
+ "acronym" => array(),
+ "code" => array(),
+ "pre" => array(),
+ "blockquote" => array("cite" => 1),
+ "h1" => array(), "h2" => array(), "h3" => array(), "h4" => array(), "h5" => array(), "h6" => array(),
+ "img" => array("src" => 1, "alt" => 1, "width" => 1, "height" => 1),
+ "s" => array(),
+ "q" => array("cite" => 1),
+ "samp" => array(),
+ "ul" => array(),
+ "ol" => array(),
+ "li" => array(),
+ "del" => array(),
+ "ins" => array(),
+ "dl" => array(),
+ "dd" => array(),
+ "dt" => array(),
+ "dfn" => array(),
+ "div" => array(),
+ "dir" => array(),
+ "kbd" => array("prompt" => 1),
+ "strike" => array(),
+ "sub" => array(),
+ "sup" => array(),
+ "table" => array("style" => 1),
+ "tbody" => array(), "thead" => array(), "tfoot" => array(),
+ "tr" => array(),
+ "td" => array("colspan" => 1, "rowspan" => 1),
+ "th" => array("colspan" => 1, "rowspan" => 1),
+ "tt" => array(),
+ "var" => array()
+ ));
+}
+
/*
* Function: comment_transform_ste
* Transforms an <Comment> object to an array, so it can be accessed via a STE template.
@@ -128,7 +175,7 @@ function comment_transform_ste($comment)
return array(
"id" => $comment->get_id(),
- "text" => textprocessor_apply($comment->text, $ratatoeskr_settings["comment_textprocessor"]),
+ "text" => comment_filter(textprocessor_apply($comment->text, $ratatoeskr_settings["comment_textprocessor"])),
"author" => htmlesc($comment->author_name),
"timestamp" => $comment->get_timestamp()
);
@@ -143,11 +190,11 @@ function comment_transform_ste($comment)
* Parameters:
* var - (mandatory) The name of the variable, where the current article should be stored at.
* id - (optional) Filter by ID.
- * urltitle - (optional) Filter by urltitle.
+ * urlname - (optional) Filter by urlname.
* section - (optional) Filter by section (section name).
* status - (optional) Filter by status (numeric, <ARTICLE_STATUS_>).
* tag - (optional) Filter by tag (tag name).
- * sort - (optional) How to sort. Format: "fieldname direction" where fieldname is one of [id, urltitle, title, timestamp] and direction is one of [asc, desc].
+ * sort - (optional) How to sort. Format: "fieldname direction" where fieldname is one of [id, urlname, title, timestamp] and direction is one of [asc, desc].
* perpage - (optional) How many articles should be shown per page (default unlimited).
* page - (optional) On which page are we (starting with 1). Useful in combination with $current[page], <page_prev> and <page_next>. (Default: 1)
* maxpage - (optional) (variable name) If given, the number of pages are stored in this variable.
@@ -167,6 +214,18 @@ $ste->register_tag("articles_get", function($ste, $params, $sub)
if(!isset($params["var"]))
throw new Exception("Parameter var is needed in article_get!");
+ if(isset($params["section"]))
+ {
+ try
+ {
+ $params["section"] = Section::by_name($params["section"]);
+ }
+ catch(NotFoundError $e)
+ {
+ unset($params["section"]);
+ }
+ }
+
$result = Article::by_multi($params);
if(isset($params["tag"]))
@@ -187,7 +246,7 @@ $ste->register_tag("articles_get", function($ste, $params, $sub)
function sort_fx_factory($cmpfx, $field, $direction)
{
- return function($a, $b) use ($sorter, $field, $direction) { return $cmpfx($a[$field], $b[$field]) * $direction; };
+ return function($a, $b) use ($cmpfx, $field, $direction) { return $cmpfx($a[$field], $b[$field]) * $direction; };
}
if(isset($params["sort"]))
@@ -201,7 +260,7 @@ $ste->register_tag("articles_get", function($ste, $params, $sub)
switch($field)
{
case "id": $sort_fx = sort_fx_factory("intcmp", "id", $direction); break;
- case "urltitle": $sort_fx = sort_fx_factory("strcmp", "urltitle", $direction); break;
+ case "urlname": $sort_fx = sort_fx_factory("strcmp", "urlname", $direction); break;
case "title": $sort_fx = sort_fx_factory("strcmp", "title", $direction); break;
case "timestamp": $sort_fx = sort_fx_factory("intcmp", "timestamp", $direction); break;
}
@@ -319,6 +378,7 @@ $ste->register_tag("article_comments_count", function($ste, $params, $sub)
* Parameters:
* var - (mandatory) The name of the variable, where the current comment should be stored at.
* article - (mandatory) The name of the variable, where the article is stored at.
+ * sort - (optional) Should the comments be sorted chronologically (asc) or inverse (desc)? Default: asc
*
* Tag Content:
* The tag's content will be executed for every comment. The current comment will be written to the variable specified by the var parameter before.
@@ -345,7 +405,8 @@ $ste->register_tag("article_comments", function($ste, $params, $sub)
}
$comments = $article->get_comments($lang, True);
- usort($comments, function($a,$b) { intcmp($a->get_timestamp(), $b->get_timestamp()); });
+ $sortdir = (@$params["sort"] == "desc") ? -1 : 1;
+ usort($comments, function($a,$b) use ($sortdir) { return intcmp($a->get_timestamp(), $b->get_timestamp()) * $sortdir; });
$comments = array_map("comment_transform_ste", $comments);
@@ -383,6 +444,9 @@ $ste->register_tag("article_comments", function($ste, $params, $sub)
*
* Returns:
* The finished HTML form.
+ *
+ * See Also:
+ * The "prevcomment" field in <$current>.
*/
$ste->register_tag("comment_form", function($ste, $params, $sub)
{
@@ -403,15 +467,27 @@ $ste->register_tag("comment_form", function($ste, $params, $sub)
if(!$article->allow_comments)
return "";
- $form_header = "<form action=\"{$tpl_article["fullurl"]}?comment\" method=\"POST\" accept-charset=\"UTF-8\">";
+ /* A token protects from double sending of the same form and is also a simple protection from stupid spambots. */
+ $token = uniqid("", True);
+ $_SESSION["ratatoeskr_comment_tokens"][$token] = time();
+
+ $form_header = "<form action=\"{$tpl_article["fullurl"]}?comment\" method=\"POST\" accept-charset=\"UTF-8\"><input type=\"hidden\" name=\"comment_token\" value=\"$token\" />";
if($ste->evalbool(@$params["default"]))
- $form_body = "<p>{$translation["comment_form_name"]}: <input type=\"text\" name=\"author_name\" /></p>
-<p>{$translation["comment_form_mail"]}: <input type=\"text\" name=\"author_mail\" /></p>
-<p>{$translation["comment_form_text"]}:<br /><textarea name=\"comment_text\" cols=\"50\" rows=\"10\"></textarea></p>
+ $form_body = "<p>{$translation["comment_form_name"]}: <input type=\"text\" name=\"author_name\" value=\"" . htmlesc(@$_POST["author_name"]) . "\" /></p>
+<p>{$translation["comment_form_mail"]}: <input type=\"text\" name=\"author_mail\" value=\"" . htmlesc(@$_POST["author_mail"]) . "\" /></p>
+<p>{$translation["comment_form_text"]}:<br /><textarea name=\"comment_text\" cols=\"50\" rows=\"10\">" . htmlesc(@$_POST["comment_text"]) . "</textarea></p>
<p><input type=\"submit\" name=\"post_comment\" /></p>";
else
+ {
+ $ste->vars["current"]["oldcomment"] = array(
+ "name" => @$_POST["author_name"],
+ "mail" => @$_POST["author_mail"],
+ "text" => @$_POST["comment_text"]
+ );
$form_body = $sub($ste);
+ unset($ste->vars["current"]["oldcomment"]);
+ }
return "$form_header\n$form_body\n</form>";
});
@@ -437,32 +513,34 @@ $ste->register_tag("comment_form", function($ste, $params, $sub)
$ste->register_tag("page_prev", function($ste, $params, $sub)
{
+ global $translation;
if(!isset($params["current"]))
throw new Exception("Need parameter 'current' in ste:page_prev.");
if(!isset($params["maxpage"]))
throw new Exception("Need parameter 'maxpage' in ste:page_prev.");
- if($params["page"] == 1)
+ if($params["current"] == 1)
return "";
parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query);
- $query["page"] = $params["page"] - 1;
+ $query["page"] = $params["current"] - 1;
$url = $_SERVER["REDIRECT_URL"] . "?" . http_build_query($query);
return "<a href=\"" . htmlesc($url) . "\">" . (($ste->evalbool(@$params["default"])) ? $translation["page_prev"] : $sub($ste)) . "</a>";
});
$ste->register_tag("page_next", function($ste, $params, $sub)
{
+ global $translation;
if(!isset($params["current"]))
throw new Exception("Need parameter 'current' in ste:page_next.");
if(!isset($params["maxpage"]))
throw new Exception("Need parameter 'maxpage' in ste:page_next.");
- if($params["page"] == $params["maxpage"])
+ if($params["current"] == $params["maxpage"])
return "";
parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query);
- $query["page"] = $params["page"] + 1;
+ $query["page"] = $params["current"] + 1;
$url = $_SERVER["REDIRECT_URL"] . "?" . http_build_query($query);
return "<a href=\"" . htmlesc($url) . "\">" . (($ste->evalbool(@$params["default"])) ? $translation["page_next"] : $sub($ste)) . "</a>";
});
@@ -515,8 +593,8 @@ $ste->register_tag("languages", function($ste, $params, $sub)
{
$ste->set_var_by_name($params["var"], array(
"short" => $lang,
- "fullname" => urlesc($languages[$lang]["language"]),
- "url" => urlesc("$rel_path_to_root/$lang/" . implode("/", array_slice($ste->vars["current"]["url_fragments"], 1)))
+ "fullname" => htmlesc($languages[$lang]["language"]),
+ "url" => htmlesc("$rel_path_to_root/$lang/" . implode("/", array_slice($ste->vars["current"]["url_fragments"], 1)))
));
$output .= $sub($ste);
}
@@ -566,7 +644,7 @@ $ste->register_tag("styles_load", function($ste, $params, $sub)
try
{
$style = Style::by_name($stylename);
- $output .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . htmlesc($rel_path_to_root . "css.php?name=" . urlencode($style->name)) . "\" />\n";
+ $output .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . htmlesc($rel_path_to_root . "/css.php?name=" . urlencode($style->name)) . "\" />\n";
}
catch(DoesNotExistError $e)
{
@@ -577,6 +655,16 @@ $ste->register_tag("styles_load", function($ste, $params, $sub)
return $output;
});
+$ste->register_tag("title", function($ste, $params, $sub)
+{
+ $pagetitle = $sub($ste);
+ if(isset($ste->vars["current"]["article"]))
+ return $ste->vars["current"]["article"]["title"] . " – $pagetitle";
+ if(isset($ste->vars["current"]["section"]))
+ return $ste->vars["current"]["section"]["title"] . " – $pagetitle";
+ return $pagetitle;
+});
+
/*
* STEVar: $current
* Holds information about the current page in the frontend (the part of the webpage, the visitor sees).
@@ -591,6 +679,7 @@ $ste->register_tag("styles_load", function($ste, $params, $sub)
* * comment_prev - If the user wanted to preview the article, this will be set and contain the HTML code of the comment.
* * styles - The styles, that should be loaded. You can also just use <styles_load>.
* * url_fragments - Array of URL parts. Mainly used internally, so you *really* should not modify this one...
+ * * oldcomment - The data of the previously sent formular (subfields: name, mail, text). Only set inside the <comment_form> tag.
*
* Plugins might insert their own $current fields.
*/
@@ -601,16 +690,23 @@ $ste->register_tag("styles_load", function($ste, $params, $sub)
*/
$comment_validators = array(
- function()
+ function() /* Basic validator. Checks, if all mandatory fields are set and if the form token is okay. Also provides some stupid spambot protection... */
{
global $translation;
if(empty($_POST["author_name"]))
throw new CommentRejected($translation["author_name_missing"]);
- if(empty($_POST["author_email"]))
+ if(empty($_POST["author_mail"]))
throw new CommentRejected($translation["author_email_missing"]);
if(empty($_POST["comment_text"]))
throw new CommentRejected($translation["comment_text_missing"]);
- }
+ if(!isset($_POST["comment_token"]))
+ throw new CommentRejected($translation["comment_form_invalid"]);
+ if(!isset($_SESSION["ratatoeskr_comment_tokens"][$_POST["comment_token"]]))
+ throw new CommentRejected($translation["comment_form_invalid"]);
+ if(time() - $_SESSION["ratatoeskr_comment_tokens"][$_POST["comment_token"]] < 10) /* Comment filled in in under 10 seconds? Most likely a spambot. */
+ throw new CommentRejected($translation["comment_too_fast"]);
+ unset($_SESSION["ratatoeskr_comment_tokens"][$_POST["comment_token"]]);
+ },
);
/*
@@ -654,7 +750,7 @@ function frontend_url_handler(&$data, $url_now, &$url_next)
load_language($languages[$lang]["translation_exist"] ? $lang : "en"); /* English is always available */
if(count($path) == 0)
- array_unshift($path, $ratatoeskr_settings["default_section"]->name);
+ array_unshift($path, $default_section->name);
$section_name = array_shift($path);
@@ -697,8 +793,8 @@ function frontend_url_handler(&$data, $url_now, &$url_next)
if(isset($_GET["comment"]))
{
- if(isset($_POST["comment_prev"]))
- $ste->vars["current"]["comment_prev"] = textprocessor_apply($_POST["comment_text"], $ratatoeskr_settings["comment_textprocessor"]);
+ if(isset($_POST["preview_comment"]))
+ $ste->vars["current"]["comment_prev"] = comment_filter(textprocessor_apply($_POST["comment_text"], $ratatoeskr_settings["comment_textprocessor"]));
else if(isset($_POST["post_comment"]))
{
$rejected = False;
@@ -743,6 +839,6 @@ function frontend_url_handler(&$data, $url_now, &$url_next)
* See Also:
* <register_comment_validator>
*/
-class CommentValidationFailed extends Exception {}
+class CommentRejected extends Exception {}
?>
diff --git a/ratatoeskr/setup/create_tables.php b/ratatoeskr/setup/create_tables.php
index b17d6f0..e9cfdaa 100644
--- a/ratatoeskr/setup/create_tables.php
+++ b/ratatoeskr/setup/create_tables.php
@@ -6,7 +6,7 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE `PREFIX_articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
- `urltitle` text COLLATE utf8_unicode_ci NOT NULL,
+ `urlname` text COLLATE utf8_unicode_ci NOT NULL,
`title` int(11) NOT NULL,
`text` int(11) NOT NULL,
`excerpt` int(11) NOT NULL,
diff --git a/ratatoeskr/sys/models.php b/ratatoeskr/sys/models.php
index 0a14a3d..c0320fa 100644
--- a/ratatoeskr/sys/models.php
+++ b/ratatoeskr/sys/models.php
@@ -53,7 +53,7 @@ class DoesNotExistError extends Exception { }
/*
* Class: AlreadyExistsError
- * This Exception is thrown by an ::create-constructor if the creation of the object would result in duplicates.
+ * This Exception is thrown by an ::create-constructor or a save-method, if the creation/modification of the object would result in duplicates.
*/
class AlreadyExistsError extends Exception { }
@@ -210,6 +210,11 @@ class User
*/
public function save()
{
+ $result = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_users` WHERE `username` = '%s' AND `id` != %d", $this->username, $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if($sqlrow["n"] > 0)
+ throw new AlreadyExistsError();
+
qdb("UPDATE `PREFIX_users` SET `username` = '%s', `pwhash` = '%s', `mail` = '%s', `fullname` = '%s', `language` = '%s' WHERE `id` = %d",
$this->username, $this->pwhash, $this->mail, $this->id, $this->fullname, $this->language);
}
@@ -627,8 +632,7 @@ class Multilingual implements Countable, ArrayAccess, IteratorAggregate
}
/*
- * Variable: $global_settings_keys_buffer
- * Buffer for settings key.
+ * Buffer for settings keys.
* NEVER(!) MODIFY DIRECTLY!
*/
$global_settings_keys_buffer = NULL;
@@ -847,7 +851,7 @@ class Comment
/*
* Constructor: create
* Creates a new comment.
- * Automatically sets the $timestamp and $visible (default form setting "comment_visible_default").
+ * Automatically sets the $timestamp and $visible (default from setting "comment_visible_default").
*
* Parameters:
* $article - An <Article> Object.
@@ -859,7 +863,7 @@ class Comment
$obj = new self;
qdb("INSERT INTO `PREFIX_comments` (`article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`) VALUES (%d, '%s', '', '', '', UNIX_TIMESTAMP(NOW()), %d)",
- $article->id, $language, $ratatoeskr_settings["comment_visible_default"] ? 1 : 0);
+ $article->get_id(), $language, $ratatoeskr_settings["comment_visible_default"] ? 1 : 0);
$obj->id = mysql_insert_id();
$obj->article = $article;
@@ -869,6 +873,8 @@ class Comment
$obj->text = "";
$obj->timestamp = time();
$obj->visible = $ratatoeskr_settings["comment_visible_default"];
+
+ return $obj;
}
/*
@@ -882,7 +888,7 @@ class Comment
{
$obj = new self;
- $result = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, visible` FROM `PREFIX_comments` WHERE `id` = %d",
+ $result = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible` FROM `PREFIX_comments` WHERE `id` = %d",
$id);
$sqlrow = mysql_fetch_assoc($result);
if($sqlrow === False)
@@ -906,7 +912,7 @@ class Comment
*/
public function save()
{
- qdb("UPDATE `PREFIX_comments` SET `author_name` = '%s', `author_mail` = '%s', `text` = '%s', `visible` = %d` WHERE `id` = %d`",
+ qdb("UPDATE `PREFIX_comments` SET `author_name` = '%s', `author_mail` = '%s', `text` = '%s', `visible` = %d WHERE `id` = %d",
$this->author_name, $this->author_mail, $this->text, ($this->visible ? 1 : 0), $this->id);
}
@@ -964,15 +970,24 @@ class Style
*/
public static function create($name)
{
- $obj = new self;
- $obj->name = $name;
- $obj->code = "";
+ try
+ {
+ self::by_name($name);
+ }
+ catch(DoesNotExistError $e)
+ {
+ $obj = new self;
+ $obj->name = $name;
+ $obj->code = "";
- qdb("INSERT INTO `PREFIX_styles` (`name`, `code`) VALUES ('%s', '')",
- $name);
+ qdb("INSERT INTO `PREFIX_styles` (`name`, `code`) VALUES ('%s', '')",
+ $name);
- $obj->id = mysql_insert_id();
- return $obj;
+ $obj->id = mysql_insert_id();
+ return $obj;
+ }
+
+ throw new AlreadyExistsError();
}
/*
@@ -996,9 +1011,9 @@ class Style
* Parameters:
* $name - The name.
*/
- public static function by_name($id)
+ public static function by_name($name)
{
- $obj = new seld;
+ $obj = new self;
$obj->populate_by_sqlresult(qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE `name` = '%s'", $name));
return $obj;
}
@@ -1009,6 +1024,11 @@ class Style
*/
public function save()
{
+ $result = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_styles` WHERE `name` = '%' AND `id` != %d", $this->name, $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if($sqlrow["n"] > 0)
+ throw new AlreadyExistsError();
+
qdb("UPDATE `PREFIX_styles` SET `name` = '%s', `code` = '%s' WHERE `id` = %d",
$this->name, $this->code, $this->id);
}
@@ -1283,6 +1303,11 @@ class Section
*/
public function save()
{
+ $result = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_sections` WHERE `name` = '%s' AND `id` != %d", $this->name, $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if($sqlrow["n"] > 0)
+ throw new AlreadyExistsError();
+
$styles = "+";
foreach($this->styles as $style)
{
@@ -1465,6 +1490,11 @@ class Tag
*/
public function save()
{
+ $result = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_tags` WHERE `name` = '%s' AND `id` != %d", $this->name, $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if($sqlrow["n"] > 0)
+ throw new AlreadyExistsError();
+
$this->title->save();
qdb("UPDATE `PREFIX_tags` SET `name` = '%s', `title` = %d` WHERE `id` = %d",
$this->name, $this->title->get_id(), $this->id);
@@ -1652,7 +1682,7 @@ class Article
/*
* Variables: Public class variables
*
- * $urltitle - URL title
+ * $urlname - URL name
* $title - Title (an <Multilingual> object)
* $text - The text (an <Multilingual> object)
* $excerpt - Excerpt (an <Multilingual> object)
@@ -1665,7 +1695,7 @@ class Article
* $allow_comments - Are comments allowed?
* $tags - Arrray of <Tag> objects
*/
- public $urltitle;
+ public $urlname;
public $title;
public $text;
public $excerpt;
@@ -1690,7 +1720,7 @@ class Article
throw new DoesNotExistError();
$this->id = $sqlrow["id"];
- $this->urltitle = $sqlrow["urltitle"];
+ $this->urlname = $sqlrow["urlname"];
$this->title = Multilingual::by_id($sqlrow["title"]);
$this->text = Multilingual::by_id($sqlrow["text"]);
$this->excerpt = Multilingual::by_id($sqlrow["excerpt"]);
@@ -1714,35 +1744,48 @@ class Article
/*
* Constructor: create
- * Create a new Article object
+ * Create a new Article object.
+ *
+ * Parameters:
+ * urlname - A unique URL name
*/
- public static function create()
+ public static function create($urlname)
{
global $ratatoeskr_settings;
- $obj = new self;
- $obj->urltitle = "";
- $obj->title = Multilingual::create();
- $obj->text = Multilingual::create();
- $obj->excerpt = Multilingual::create();
- $obj->meta = "";
- $obj->custom = array();
- $obj->article_image = NULL;
- $obj->status = ARTICLE_STATUS_HIDDEN;
- $obj->section = Section::by_id($ratatoeskr_settings["default_section"]);
- $obj->timestamp = time();
- $obj->allow_comments = $ratatoeskr_settings["allow_comments_default"];
- qdb("INSERT INTO `PREFIX_articles` (`urltitle`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments`) VALUES ('', %d, %d, %d, '', '%s', 0, %d, %d, %d, %d)",
- $obj->title->get_id(),
- $obj->text->get_id(),
- $obj->excerpt->get_id(),
- base64_encode(serialize($obj->custom)),
- $obj->status,
- $obj->section->get_id(),
- $obj->timestamp,
- $obj->allow_comments ? 1 : 0);
- $obj->id = mysql_insert_id();
- return $obj;
+ try
+ {
+ self::by_urlname($urlname);
+ }
+ catch(DoesNotExistError $e)
+ {
+ $obj = new self;
+ $obj->urlname = $urlname;
+ $obj->title = Multilingual::create();
+ $obj->text = Multilingual::create();
+ $obj->excerpt = Multilingual::create();
+ $obj->meta = "";
+ $obj->custom = array();
+ $obj->article_image = NULL;
+ $obj->status = ARTICLE_STATUS_HIDDEN;
+ $obj->section = Section::by_id($ratatoeskr_settings["default_section"]);
+ $obj->timestamp = time();
+ $obj->allow_comments = $ratatoeskr_settings["allow_comments_default"];
+
+ qdb("INSERT INTO `PREFIX_articles` (`urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments`) VALUES ('', %d, %d, %d, '', '%s', 0, %d, %d, %d, %d)",
+ $obj->title->get_id(),
+ $obj->text->get_id(),
+ $obj->excerpt->get_id(),
+ base64_encode(serialize($obj->custom)),
+ $obj->status,
+ $obj->section->get_id(),
+ $obj->timestamp,
+ $obj->allow_comments ? 1 : 0);
+ $obj->id = mysql_insert_id();
+ return $obj;
+ }
+
+ throw new AlreadyExistsError();
}
/*
@@ -1756,14 +1799,14 @@ class Article
{
$obj = new self;
$obj ->populate_by_sqlresult(qdb(
- "SELECT `id`, `urltitle`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `id` = %d", $id
+ "SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `id` = %d", $id
));
return $obj;
}
/*
* Constructor: by_urlname
- * Get by urltitle
+ * Get by urlname
*
* Parameters:
* $urlname - The urlname
@@ -1772,7 +1815,7 @@ class Article
{
$obj = new self;
$obj ->populate_by_sqlresult(qdb(
- "SELECT `id`, `urltitle`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `urltitle` = '%s'", $urlname
+ "SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `urlname` = '%s'", $urlname
));
return $obj;
}
@@ -1782,7 +1825,7 @@ class Article
* Get Articles by multiple criterias
*
* Parameters:
- * $criterias - Array that can have these keys: id, urltitle, section, status
+ * $criterias - Array that can have these keys: id (int) , urlname (string), section (<Section> object), status (int)
*
* Returns:
* Array of Article objects
@@ -1795,7 +1838,7 @@ class Article
switch($k)
{
case "id": $subqueries[] = qdb_fmt("`id` = %d", $v); break;
- case "urltitle": $subqueries[] = qdb_fmt("`urltitle` = '%s'", $v); break;
+ case "urlname": $subqueries[] = qdb_fmt("`urlname` = '%s'", $v); break;
case "section": $subqueries[] = qdb_fmt("`section` = %d", $v->get_id()); break;
case "status": $subqueries[] = qdb_fmt("`status` = %d", $v); break;
default: continue;
@@ -1860,6 +1903,11 @@ class Article
*/
public function save()
{
+ $result = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_article` WHERE `urlname` = '%s' AND `id` != %d", $this->urlname, $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if($sqlrow["n"] > 0)
+ throw new AlreadyExistsError();
+
$this->title->save();
$this->text->save();
$this->excerpt->save();
@@ -1877,8 +1925,8 @@ class Article
)
);
- qdb("UPDATE `PREFIX_articles` SET `urltitle` = '%s', `title` = %d, `text` = %d, `excerpt` = %d, `meta` = '%s', `custom` = '%s', `article_image` = %d, `status` = %d, `section` = %d, `timestamp` = %d, `allow_comments` = %d WHERE `id` = %d",
- $this->urltitle,
+ qdb("UPDATE `PREFIX_articles` SET `urlname` = '%s', `title` = %d, `text` = %d, `excerpt` = %d, `meta` = '%s', `custom` = '%s', `article_image` = %d, `status` = %d, `section` = %d, `timestamp` = %d, `allow_comments` = %d WHERE `id` = %d",
+ $this->urlname,
$this->title->get_id(),
$this->text->get_id(),
$this->excerpt->get_id(),