From 74cf8718cd1a09ac159e933c898ede1a9d474679 Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Wed, 12 Oct 2011 21:57:41 +0200 Subject: 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. --- ratatoeskr/frontend.php | 152 ++++++++++++++++++++++++++++++------- ratatoeskr/setup/create_tables.php | 2 +- ratatoeskr/sys/models.php | 150 +++++++++++++++++++++++------------- 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 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, ). * 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], and . (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 = "
"; + /* 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 = ""; if($ste->evalbool(@$params["default"])) - $form_body = "

{$translation["comment_form_name"]}:

-

{$translation["comment_form_mail"]}:

-

{$translation["comment_form_text"]}:

+ $form_body = "

{$translation["comment_form_name"]}:

+

{$translation["comment_form_mail"]}:

+

{$translation["comment_form_text"]}:

"; 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
"; }); @@ -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 "" . (($ste->evalbool(@$params["default"])) ? $translation["page_prev"] : $sub($ste)) . ""; }); $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 "" . (($ste->evalbool(@$params["default"])) ? $translation["page_next"] : $sub($ste)) . ""; }); @@ -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 .= "\n"; + $output .= "\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 . * * 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 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: * */ -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
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 object) * $text - The text (an object) * $excerpt - Excerpt (an object) @@ -1665,7 +1695,7 @@ class Article * $allow_comments - Are comments allowed? * $tags - Arrray of 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 (
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(), -- cgit v1.2.3-70-g09d2