diff options
Diffstat (limited to 'ratatoeskr')
-rw-r--r-- | ratatoeskr/backend.php | 3938 | ||||
-rw-r--r-- | ratatoeskr/frontend.php | 1294 | ||||
-rw-r--r-- | ratatoeskr/js/backend.js | 32 | ||||
-rw-r--r-- | ratatoeskr/languages.php | 374 | ||||
-rw-r--r-- | ratatoeskr/main.php | 160 | ||||
-rw-r--r-- | ratatoeskr/setup/create_tables.php | 22 | ||||
-rw-r--r-- | ratatoeskr/setup/setup.php | 312 | ||||
-rw-r--r-- | ratatoeskr/sys/db.php | 150 | ||||
-rw-r--r-- | ratatoeskr/sys/init_ste.php | 58 | ||||
-rw-r--r-- | ratatoeskr/sys/models.php | 5652 | ||||
-rw-r--r-- | ratatoeskr/sys/plugin_api.php | 462 | ||||
-rw-r--r-- | ratatoeskr/sys/pluginpackage.php | 458 | ||||
-rw-r--r-- | ratatoeskr/sys/pwhash.php | 106 | ||||
-rw-r--r-- | ratatoeskr/sys/textprocessors.php | 62 | ||||
-rw-r--r-- | ratatoeskr/sys/translation.php | 76 | ||||
-rw-r--r-- | ratatoeskr/sys/urlprocess.php | 226 | ||||
-rw-r--r-- | ratatoeskr/sys/utils.php | 216 | ||||
-rw-r--r-- | ratatoeskr/translations/de.php | 556 | ||||
-rw-r--r-- | ratatoeskr/translations/en.php | 556 |
19 files changed, 7355 insertions, 7355 deletions
diff --git a/ratatoeskr/backend.php b/ratatoeskr/backend.php index 326d82c..a5d5155 100644 --- a/ratatoeskr/backend.php +++ b/ratatoeskr/backend.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/backend.php * The backend. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -20,23 +20,23 @@ $admin_grp = NULL; /* Mass creation of tags. */ function maketags($tagnames, $lang) { - $rv = array(); - foreach($tagnames as $tagname) - { - if(empty($tagname)) - continue; - try - { - $tag = Tag::by_name($tagname); - } - catch(DoesNotExistError $e) - { - $tag = Tag::create($tagname); - $tag->title[$lang] = new Translation($tagname, ""); - } - $rv[] = $tag; - } - return $rv; + $rv = array(); + foreach($tagnames as $tagname) + { + if(empty($tagname)) + continue; + try + { + $tag = Tag::by_name($tagname); + } + catch(DoesNotExistError $e) + { + $tag = Tag::create($tagname); + $tag->title[$lang] = new Translation($tagname, ""); + } + $rv[] = $tag; + } + return $rv; } $backend_subactions = NULL; @@ -46,1957 +46,1957 @@ function build_backend_subactions() global $backend_subactions, $pluginpages_handlers; $backend_subactions = url_action_subactions(array( - "_index" => url_action_alias(array("login")), - "index" => url_action_alias(array("login")), - /* _prelude guarantees that the user is logged in properly, so we do not have to care about that later, and sets some STE vars. */ - "_prelude" => function(&$data, $url_now, &$url_next) - { - global $ratatoeskr_settings, $admin_grp, $ste, $languages; - - if($admin_grp === NULL) - $admin_grp = Group::by_name("admins"); - - $ste->vars["all_languages"] = array(); - $ste->vars["all_langcodes"] = array(); - foreach($languages as $code => $data) - { - $ste->vars["all_languages"][$code] = $data["language"]; - $ste->vars["all_langcodes"][] = $code; - } - ksort($ste->vars["all_languages"]); - sort($ste->vars["all_langcodes"]); - - - /* Check authentification */ - if(isset($_SESSION["ratatoeskr_uid"])) - { - try - { - $user = User::by_id($_SESSION["ratatoeskr_uid"]); - if(($user->pwhash == $_SESSION["ratatoeskr_pwhash"]) and $user->member_of($admin_grp)) - { - if(empty($user->language)) - { - $user->language = $ratatoeskr_settings["default_language"]; - $user->save(); - } - load_language($user->language); - - if($url_next[0] == "login") - $url_next = array("content", "write"); - $data["user"] = $user; - $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language); - - return; /* Authentification successful, continue */ - } - else - unset($_SESSION["ratatoeskr_uid"]); - } - catch(DoesNotExistError $e) - { - unset($_SESSION["ratatoeskr_uid"]); - } - } - load_language(); - - /* If we are here, user is not logged in... */ - $url_next = array("login"); - }, - "login" => url_action_simple(function($data) - { - global $ste, $admin_grp; - if(!empty($_POST["user"])) - { - try - { - $user = User::by_name($_POST["user"]); - if(!PasswordHash::validate($_POST["password"], $user->pwhash)) - throw new Exception(); - if(!$user->member_of($admin_grp)) - throw new Exception(); - - /* Login successful. */ - $_SESSION["ratatoeskr_uid"] = $user->get_id(); - $_SESSION["ratatoeskr_pwhash"] = $user->pwhash; - load_language($user->language); - $data["user"] = $user; - $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language); - } - catch(Exception $e) - { - $ste->vars["login_failed"] = True; - } - - if(isset($data["user"])) - throw new Redirect(array("content", "write")); - } - - echo $ste->exectemplate("/systemtemplates/backend_login.html"); - }), - "logout" => url_action_simple(function($data) - { - unset($_SESSION["ratatoeskr_uid"]); - unset($_SESSION["ratatoeskr_pwhash"]); - load_language(); - throw new Redirect(array("login")); - }), - "content" => url_action_subactions(array( - "write" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $textprocessors, $ratatoeskr_settings, $languages, $articleeditor_plugins; - - list($article, $editlang) = array_slice($url_next, 0); - if(!isset($editlang)) - $editlang = $data["user"]->language; - if(isset($article)) - $ste->vars["article_editurl"] = urlencode($article) . "/" . urlencode($editlang); - else - $ste->vars["article_editurl"] = ""; - - $url_next = array(); - - $default_section = Section::by_id($ratatoeskr_settings["default_section"]); - - $ste->vars["section"] = "content"; - $ste->vars["submenu"] = isset($article) ? "articles" : "newarticle"; - - $ste->vars["textprocessors"] = array(); - foreach($textprocessors as $txtproc => $properties) - if($properties[1]) - $ste->vars["textprocessors"][] = $txtproc; - - $ste->vars["sections"] = array(); - foreach(Section::all() as $section) - $ste->vars["sections"][] = $section->name; - $ste->vars["article_section"] = $default_section->name; - - /* Check Form */ - $fail_reasons = array(); - - if(isset($_POST["save_article"])) - { - if(!Article::test_urlname($_POST["urlname"])) - $fail_reasons[] = $translation["invalid_urlname"]; - else - $inputs["urlname"] = $_POST["urlname"]; - if(!Article::test_status(@$_POST["article_status"])) - $fail_reasons[] = $translation["invalid_article_status"]; - else - $inputs["article_status"] = (int) $_POST["article_status"]; - if(!isset($textprocessors[@$_POST["content_txtproc"]])) - $fail_reasons[] = $translation["unknown_txtproc"]; - else - $inputs["content_txtproc"] = $_POST["content_txtproc"]; - if(!isset($textprocessors[@$_POST["excerpt_txtproc"]])) - $fail_reasons[] = $translation["unknown_txtproc"]; - else - $inputs["excerpt_txtproc"] = $_POST["excerpt_txtproc"]; - if(!empty($_POST["date"])) - { - if(($time_tmp = @DateTime::createFromFormat("Y-m-d H:i:s", @$_POST["date"])) === False) - $fail_reasons[] = $translation["invalid_date"]; - else - $inputs["date"] = @$time_tmp->getTimestamp(); - } - else - $inputs["date"] = time(); - $inputs["allow_comments"] = !(empty($_POST["allow_comments"]) or ($_POST["allow_comments"] != "yes")); - - try - { - $inputs["article_section"] = Section::by_name($_POST["section"]); - } - catch(DoesNotExistError $e) - { - $fail_reasons[] = $translation["unknown_section"]; - } - - $inputs["title"] = $_POST["title"]; - $inputs["content"] = $_POST["content"]; - $inputs["excerpt"] = $_POST["excerpt"]; - $inputs["tags"] = array_filter(array_map("trim", explode(",", $_POST["tags"])), function($t) { return !empty($t); }); - if(isset($_POST["saveaslang"])) - $editlang = $_POST["saveaslang"]; - } - else - { - /* Call articleeditor plugins */ - $article = empty($article) ? NULL : Article::by_urlname($article); - foreach($articleeditor_plugins as $plugin) - call_user_func($plugin["fx"], $article, False); - } - - function fill_article(&$article, $inputs, $editlang) - { - $article->urlname = $inputs["urlname"]; - $article->status = $inputs["article_status"]; - $article->timestamp = $inputs["date"]; - $article->title[$editlang] = new Translation($inputs["title"], ""); - $article->text[$editlang] = new Translation($inputs["content"], $inputs["content_txtproc"]); - $article->excerpt[$editlang] = new Translation($inputs["excerpt"], $inputs["excerpt_txtproc"]); - $article->set_tags(maketags($inputs["tags"], $editlang)); - $article->set_section($inputs["article_section"]); - $article->allow_comments = $inputs["allow_comments"]; - } - - if(empty($article)) - { - /* New Article */ - $ste->vars["pagetitle"] = $translation["new_article"]; - if(empty($fail_reasons) and isset($_POST["save_article"])) - { - $article = Article::create($inputs["urlname"]); - fill_article($article, $inputs, $editlang); - - /* Calling articleeditor plugins */ - $call_after_save = array(); - foreach($articleeditor_plugins as $plugin) - { - $result = call_user_func($plugin["fx"], $article, True); - if(is_string($result)) - $fail_reasons[] = $result; - elseif($result !== NULL) - $call_after_save[] = $result; - } - - if(empty($fail_reasons)) - { - try - { - $article->save(); - foreach($call_after_save as $cb) - call_user_func($cb, $article); - $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang); - $ste->vars["success"] = htmlesc($translation["article_save_success"]); - } - catch(AlreadyExistsError $e) - { - $fail_reasons[] = $translation["article_name_already_in_use"]; - } - } - } - } - else - { - try - { - if(!($article instanceof Article)) - $article = Article::by_urlname($article); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - if(empty($fail_reasons) and isset($_POST["save_article"])) - { - fill_article($article, $inputs, $editlang); - - /* Calling articleeditor plugins */ - $call_after_save = array(); - foreach($articleeditor_plugins as $plugin) - { - $result = call_user_func($plugin["fx"], $article, True); - if(is_string($result)) - $fail_reasons[] = $result; - elseif($result !== NULL) - $call_after_save[] = $result; - } - - if(empty($fail_reasons)) - { - try - { - $article->save(); - foreach($call_after_save as $cb) - call_user_func($cb, $article); - $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang); - $ste->vars["success"] = htmlesc($translation["article_save_success"]); - } - catch(AlreadyExistsError $e) - { - $fail_reasons[] = $translation["article_name_already_in_use"]; - } - } - } - - if(!isset($article->title[$editlang])) - { - $langs_available = array(); - foreach($article->title as $lang => $_) - $langs_available[] = $lang; - $editlang = $langs_available[0]; - } - - foreach(array( - "urlname" => "urlname", - "status" => "article_status", - "timestamp" => "date", - "allow_comments" => "allow_comments" - ) as $prop => $k_out) - { - if(!isset($inputs[$k_out])) - $inputs[$k_out] = $article->$prop; - } - if(!isset($inputs["title"])) - $inputs["title"] = $article->title[$editlang]->text; - if(!isset($inputs["content"])) - { - $translation_obj = $article->text[$editlang]; - $inputs["content"] = $translation_obj->text; - $inputs["content_txtproc"] = $translation_obj->texttype; - } - if(!isset($inputs["excerpt"])) - { - $translation_obj = $article->excerpt[$editlang]; - $inputs["excerpt"] = $translation_obj->text; - $inputs["excerpt_txtproc"] = $translation_obj->texttype; - } - if(!isset($inputs["article_section"])) - $inputs["article_section"] = $article->get_section(); - if(!isset($inputs["tags"])) - $inputs["tags"] = array_map(function($tag) use ($editlang) { return $tag->name; }, $article->get_tags()); - $ste->vars["morelangs"] = array(); - $ste->vars["pagetitle"] = $article->title[$editlang]->text; - foreach($article->title as $lang => $_) - { - if($lang != $editlang) - $ste->vars["morelangs"][] = array("url" => urlencode($article->urlname) . "/$lang", "full" => "($lang) " . $languages[$lang]["language"]); - } - } - - if(!isset($inputs["date"])) - $inputs["date"] = time(); - if(!isset($inputs["article_status"])) - $inputs["article_status"] = ARTICLE_STATUS_LIVE; - - /* Push data back to template */ - if(isset($inputs["tags"])) - $ste->vars["tags"] = implode(", ", $inputs["tags"]); - if(isset($inputs["article_section"])) - $ste->vars["article_section"] = $inputs["article_section"]->name; - $ste->vars["editlang"] = $editlang; - foreach(array( - "urlname" => "urlname", - "article_status" => "article_status", - "title" => "title", - "content_txtproc" => "content_txtproc", - "content" => "content", - "excerpt_txtproc" => "excerpt_txtproc", - "excerpt" => "excerpt", - "date" => "date", - "allow_comments" => "allow_comments" - ) as $k_in => $k_out) - { - if(isset($inputs[$k_in])) - $ste->vars[$k_out] = $inputs[$k_in]; - } - - /* Displaying article editor plugins */ - $ste->vars["displayed_plugins"] = array_map(function($x) { return array("label" => $x["label"], "template" => $x["template"]); }, array_filter($articleeditor_plugins, function($x) { return $x["display"]; })); - - if(!empty($fail_reasons)) - $ste->vars["failed"] = $fail_reasons; - - echo $ste->exectemplate("/systemtemplates/content_write.html"); - }, - "tags" => function(&$data, $url_now, &$url_next) - { - global $translation, $languages, $ste, $rel_path_to_root; - - $url_next = array(); - - $ste->vars["section"] = "content"; - $ste->vars["submenu"] = "tags"; - $ste->vars["pagetitle"] = $translation["tags_overview"]; - - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["tag_multiselect"] as $tagid) - { - try - { - $tag = Tag::by_id($tagid); - $tag->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $ste->vars["success"] = $translation["tags_successfully_deleted"]; - } - - if(isset($_POST["save_changes"])) - { - $newlang = (!empty($_POST["new_language"])) ? $_POST["new_language"] : NULL; - $newtag = NULL; - - if(!empty($_POST["newtagname"])) - { - if(!Tag::test_name(@$_POST["newtagname"])) - $ste->vars["error"] = $translation["invalid_tag_name"]; - else - $newtag = $_POST["newtagname"]; - } - - if(($newlang !== NULL) and (!isset($languages[$newlang]))) - $newlang = NULL; - if($newtag !== NULL) - { - try - { - $newtag = Tag::create($newtag); - } - catch(AlreadyExistsError $e) - { - $newtag = NULL; - } - } - - $translations = array(); - foreach($_POST as $k => $v) - { - if(preg_match('/tagtrans_(NEW|[a-z]{2})_(.*)/', $k, $matches) == 1) - { - $lang = ($matches[1] == "NEW") ? $newlang : $matches[1]; - $tag = $matches[2]; - if($lang === NULL) - continue; - $translations[$tag][$lang] = $v; - } - } - - foreach($translations as $tag => $langmap) - { - if($tag == "NEW") - { - if($newtag === NULL) - continue; - $tag = $newtag; - } - else - { - try - { - $tag = Tag::by_id($tag); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - foreach($langmap as $l => $text) - { - if(empty($text)) - unset($tag->title[$l]); - else - $tag->title[$l] = new Translation($text, ""); - } - - $tag->save(); - } - - $ste->vars["success"] = $translation["tags_successfully_edited"]; - } - - $ste->vars["alltags"] = array(); - $taglangs = array(); - - $alltags = Tag::all(); - foreach($alltags as $tag) - { - $transls = array(); - foreach($tag->title as $l => $t) - { - if(!in_array($l, $taglangs)) - $taglangs[] = $l; - $transls[$l] = $t->text; - } - - $ste->vars["alltags"][] = array( - "id" => $tag->get_id(), - "name" => $tag->name, - "translations" => $transls - ); - } - - $unused_langs = array_diff(array_keys($languages), $taglangs); - - $ste->vars["all_tag_langs"] = array(); - foreach($taglangs as $l) - $ste->vars["all_tag_langs"][$l] = $languages[$l]["language"]; - $ste->vars["unused_languages"] = array(); - foreach($unused_langs as $l) - $ste->vars["unused_languages"][$l] = $languages[$l]["language"]; - - echo $ste->exectemplate("/systemtemplates/tags_overview.html"); - }, - "articles" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - $url_next = array(); - - $ste->vars["section"] = "content"; - $ste->vars["submenu"] = "articles"; - $ste->vars["pagetitle"] = $translation["menu_articles"]; - - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["article_multiselect"] as $article_urlname) - { - try - { - $article = Article::by_urlname($article_urlname); - $article->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $ste->vars["success"] = $translation["articles_deleted"]; - } - - $articles = Article::all(); - - /* Filtering */ - $filterquery = array(); - if(!empty($_GET["filter_urlname"])) - { - $searchfor = strtolower($_GET["filter_urlname"]); - $articles = array_filter($articles, function($a) use ($searchfor) { return strpos(strtolower($a->urlname), $searchfor) !== False; }); - $filterquery[] = "filter_urlname=" . urlencode($_GET["filter_urlname"]); - $ste->vars["filter_urlname"] = $_GET["filter_urlname"]; - } - if(!empty($_GET["filter_tag"])) - { - $searchfor = $_GET["filter_tag"]; - $articles = array_filter($articles, function($a) use ($searchfor) { foreach($a->get_tags() as $t) { if($t->name==$searchfor) return True; } return False; }); - $filterquery[] = "filter_tag=" . urlencode($searchfor); - $ste->vars["filter_tag"] = $searchfor; - } - if(!empty($_GET["filter_section"])) - { - $searchfor = $_GET["filter_section"]; - $articles = array_filter($articles, function($a) use ($searchfor) { return $a->get_section()->name == $searchfor; }); - $filterquery[] = "filter_section=" . urlencode($searchfor); - $ste->vars["filter_section"] = $searchfor; - } - $ste->vars["filterquery"] = implode("&", $filterquery); - - /* Sorting */ - if(isset($_GET["sort_asc"])) - { - switch($_GET["sort_asc"]) - { - case "date": - $ste->vars["sortquery"] = "sort_asc=date"; - $ste->vars["sort_asc_date"] = True; - $ste->vars["sorting"] = array("dir" => "asc", "by" => "date"); - usort($articles, function($a, $b) { return intcmp($a->timestamp, $b->timestamp); }); - break; - case "section": - $ste->vars["sortquery"] = "sort_asc=section"; - $ste->vars["sort_asc_section"] = True; - $ste->vars["sorting"] = array("dir" => "asc", "by" => "section"); - usort($articles, function($a, $b) { return strcmp($a->get_section()->name, $b->get_section()->name); }); - break; - case "urlname": - $ste->vars["sortquery"] = "sort_asc=urlname"; - default: - $ste->vars["sort_asc_urlname"] = True; - $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); - usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); - break; - } - } - elseif(isset($_GET["sort_desc"])) - { - switch($_GET["sort_desc"]) - { - case "date": - $ste->vars["sortquery"] = "sort_desc=date"; - $ste->vars["sort_desc_date"] = True; - $ste->vars["sorting"] = array("dir" => "desc", "by" => "date"); - usort($articles, function($a, $b) { return intcmp($b->timestamp, $a->timestamp); }); - break; - case "section": - $ste->vars["sortquery"] = "sort_desc=section"; - $ste->vars["sort_desc_section"] = True; - $ste->vars["sorting"] = array("dir" => "desc", "by" => "section"); - usort($articles, function($a, $b) { return strcmp($b->get_section()->name, $a->get_section()->name); }); - break; - case "urlname": - $ste->vars["sortquery"] = "sort_desc=urlname"; - $ste->vars["sort_desc_urlname"] = True; - $ste->vars["sorting"] = array("dir" => "desc", "by" => "urlname"); - usort($articles, function($a, $b) { return strcmp($b->urlname, $a->urlname); }); - break; - default: - $ste->vars["sort_asc_urlname"] = True; - $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); - usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); - break; - } - } - else - { - $ste->vars["sort_asc_urlname"] = True; - $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); - usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); - } - - $ste->vars["articles"] = array_map(function($article) { - $avail_langs = array(); - foreach($article->title as $lang => $_) - $avail_langs[] = $lang; - sort($avail_langs); - $a_section = $article->get_section(); - return array( - "urlname" => $article->urlname, - "languages" => $avail_langs, - "date" => $article->timestamp, - "tags" => array_map(function($tag) { return $tag->name; }, $article->get_tags()), - "section" => array("id" => $a_section->get_id(), "name" => $a_section->name) - ); - }, $articles); - - echo $ste->exectemplate("/systemtemplates/articles.html"); - }, - "images" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - list($imgid, $imageaction) = $url_next; - - $url_next = array(); - - $ste->vars["section"] = "content"; - $ste->vars["submenu"] = "images"; - $ste->vars["pagetitle"] = $translation["menu_images"]; - - if(!empty($imgid) and is_numeric($imgid)) - { - try - { - $image = Image::by_id($imgid); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - if(empty($imageaction)) - throw new NotFoundError(); - else - { - if(($imageaction == "markdown") or ($imageaction == "html") or ($imageaction == "ste")) - { - $ste->vars["pagetitle"] = $translation["generate_embed_code"]; - $ste->vars["image_id"] = $image->get_id(); - $ste->vars["markup_variant"] = $imageaction; - if(isset($_POST["img_alt"])) - { - if($imageaction == "markdown") - $ste->vars["embed_code"] = "![" . str_replace("]", "\\]", $_POST["img_alt"]) . "](%root%/images/" . str_replace(")", "\\)", urlencode($image->get_filename())) . ")"; - elseif($imageaction == "html") - $ste->vars["embed_code"] = "<img src=\"%root%/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />"; - elseif($imageaction == "ste") - $ste->vars["embed_code"] = "<img src=\"\$rel_path_to_root/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />"; - } - - echo $ste->exectemplate("/systemtemplates/image_embed.html"); - } - else - throw new NotFoundError(); - } - return; - } - - /* Upload Form */ - if(isset($_POST["upload"])) - { - try - { - $image = Image::create((!empty($_POST["upload_name"])) ? $_POST["upload_name"] : $_FILES["upload_img"]["name"], $_FILES["upload_img"]["tmp_name"]); - $image->save(); - $ste->vars["success"] = $translation["upload_success"]; - } - catch(IOError $e) - { - $ste->vars["error"] = $translation["upload_failed"]; - } - catch(UnknownFileFormat $e) - { - $ste->vars["error"] = $translation["unknown_file_format"]; - } - } - - /* Mass delete */ - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["image_multiselect"] as $image_id) - { - try - { - $image = Image::by_id($image_id); - $image->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $ste->vars["success"] = $translation["images_deleted"]; - } - - $images = Image::all(); - - $ste->vars["images"] = array_map(function($img) { return array( - "id" => $img->get_id(), - "name" => $img->name, - "file" => $img->get_filename() - ); }, $images); - - echo $ste->exectemplate("/systemtemplates/image_list.html"); - }, - "comments" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - list($comment_id) = $url_next; - - $url_next = array(); - - $ste->vars["section"] = "content"; - $ste->vars["submenu"] = "comments"; - $ste->vars["pagetitle"] = $translation["menu_comments"]; - - /* Single comment? */ - if(!empty($comment_id)) - { - try - { - $comment = Comment::by_id($comment_id); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - if(!$comment->read_by_admin) - { - $comment->read_by_admin = True; - $comment->save(); - } - - if(isset($_POST["action_on_comment"])) - { - switch($_POST["action_on_comment"]) - { - case "delete": - $comment->delete(); - $ste->vars["success"] = $translation["comment_successfully_deleted"]; - goto backend_content_comments_overview; - break; - case "make_visible": - $comment->visible = True; - $comment->save(); - $ste->vars["success"] = $translation["comment_successfully_made_visible"]; - break; - case "make_invisible": - $comment->visible = False; - $comment->save(); - $ste->vars["success"] = $translation["comment_successfully_made_invisible"]; - break; - } - } - - $ste->vars["id"] = $comment->get_id(); - $ste->vars["visible"] = $comment->visible; - $ste->vars["article"] = $comment->get_article()->urlname; - $ste->vars["language"] = $comment->get_language(); - $ste->vars["date"] = $comment->get_timestamp(); - $ste->vars["author"] = "\"{$comment->author_name}\" <{$comment->author_mail}>"; - $ste->vars["comment_text"] = $comment->create_html(); - $ste->vars["comment_raw"] = $comment->text; - - echo $ste->exectemplate("/systemtemplates/single_comment.html"); - return; - } - - backend_content_comments_overview: - - /* Perform an action on all selected comments */ - if(!empty($_POST["action_on_comments"])) - { - switch($_POST["action_on_comments"]) - { - case "delete": - $commentaction = function($c) { $c->delete(); }; - $ste->vars["success"] = $translation["comments_successfully_deleted"]; - break; - case "mark_read": - $commentaction = function($c) { $c->read_by_admin = True; $c->save(); }; - $ste->vars["success"] = $translation["comments_successfully_marked_read"]; - break; - case "mark_unread": - $commentaction = function($c) { $c->read_by_admin = False; $c->save(); }; - $ste->vars["success"] = $translation["comments_successfully_marked_unread"]; - break; - case "make_visible": - $commentaction = function($c) { $c->visible = True; $c->save(); }; - $ste->vars["success"] = $translation["comments_successfully_made_visible"]; - break; - case "make_invisible": - $commentaction = function($c) { $c->visible = False; $c->save(); }; - $ste->vars["success"] = $translation["comments_successfully_made_invisible"]; - break; - default; - $ste->vars["error"] = $translation["unknown_action"]; - break; - } - if(isset($commentaction)) - { - foreach($_POST["comment_multiselect"] as $c_id) - { - try - { - $comment = Comment::by_id($c_id); - $commentaction($comment); - } - catch(DoesNotExistError $e) - { - continue; - } - } - } - } - - $comments = Comment::all(); - - /* Filtering */ - $filterquery = array(); - if(!empty($_GET["filter_article"])) - { - $searchfor = strtolower($_GET["filter_article"]); - $comments = array_filter($comments, function($c) use ($searchfor) { return strpos(strtolower($c->get_article()->urlname), $searchfor) !== False; }); - $filterquery[] = "filter_article=" . urlencode($_GET["filter_article"]); - $ste->vars["filter_article"] = $_GET["filter_article"]; - } - $ste->vars["filterquery"] = implode("&", $filterquery); - - /* Sorting */ - if(isset($_GET["sort_asc"])) - { - $sort_dir = 1; - $sort_by = $_GET["sort_asc"]; - } - elseif(isset($_GET["sort_desc"])) - { - $sort_dir = -1; - $sort_by = $_GET["sort_desc"]; - } - else - { - $sort_dir = 1; - $sort_by = "was_read"; - } - - switch($sort_by) - { - case "language": - usort($comments, function($a, $b) use ($sort_dir) { return strcmp($a->get_language(), $b->get_language()) * $sort_dir; }); - break; - case "date": - usort($comments, function($a, $b) use ($sort_dir) { return intcmp($a->get_timestamp(), $b->get_timestamp()) * $sort_dir; }); - break; - case "was_read": - default: - usort($comments, function($a, $b) use ($sort_dir) { return intcmp((int) $a->read_by_admin, (int) $b->read_by_admin) * $sort_dir; }); - $sort_by = "was_read"; - break; - } - $ste->vars["sortquery"] = "sort_" . ($sort_dir == 1 ? "asc" : "desc") . "=$sort_by"; - $ste->vars["sorting"] = array("dir" => ($sort_dir == 1 ? "asc" : "desc"), "by" => $sort_by); - $ste->vars["sort_" . ($sort_dir == 1 ? "asc" : "desc") . "_$sort_by"] = True; - - $ste->vars["comments"] = array_map(function($c) { return array( - "id" => $c->get_id(), - "visible" => $c->visible, - "read_by_admin" => $c->read_by_admin, - "article" => $c->get_article()->urlname, - "excerpt" => substr(str_replace(array("\r\n", "\n", "\r"), " ", $c->text), 0, 50), - "language" => $c->get_language(), - "date" => $c->get_timestamp(), - "author" => "\"{$c->author_name}\" <{$c->author_mail}>" - ); }, $comments); - - echo $ste->exectemplate("/systemtemplates/comments_list.html"); - } - )), - "design" => url_action_subactions(array( - "templates" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - list($template) = $url_next; - - $url_next = array(); - - $ste->vars["section"] = "design"; - $ste->vars["submenu"] = "templates"; - $ste->vars["pagetitle"] = $translation["menu_templates"]; - - if(isset($template)) - { - if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $template) == 0) /* Prevent a possible LFI attack. */ - throw new NotFoundError(); - if(!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$template")) - throw new NotFoundError(); - $ste->vars["template_name"] = $template; - $ste->vars["template_code"] = file_get_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$template"); - } - - /* Was there a delete request? */ - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["templates_multiselect"] as $tplname) - { - if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $tplname) == 0) /* Prevent a possible LFI attack. */ - continue; - if(is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$tplname")) - @unlink(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$tplname"); - } - $ste->vars["success"] = $translation["templates_successfully_deleted"]; - } - - /* A write request? */ - if(isset($_POST["save_template"])) - { - if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["template_name"]) == 1) - { - $ste->vars["template_name"] = $_POST["template_name"]; - $ste->vars["template_code"] = $_POST["template_code"]; - - try - { - \ste\transcompile(\ste\parse(\ste\precompile($_POST["template_code"]), $_POST["template_name"])); - file_put_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/" . $_POST["template_name"], $_POST["template_code"]); - $ste->vars["success"] = $translation["template_successfully_saved"]; - } - catch(\ste\ParseCompileError $e) - { - $e->rewrite($_POST["template_code"]); - $ste->vars["error"] = $translation["could_not_compile_template"] . $e->getMessage(); - } - } - else - $ste->vars["error"] = $translation["invalid_template_name"]; - } - - /* Get all templates */ - $ste->vars["templates"] = array(); - $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates"); - foreach($tpldir as $fo) - { - if($fo->isFile()) - $ste->vars["templates"][] = $fo->getFilename(); - } - sort($ste->vars["templates"]); - - echo $ste->exectemplate("/systemtemplates/templates.html"); - }, - "styles" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - list($style) = $url_next; - - $url_next = array(); - - $ste->vars["section"] = "design"; - $ste->vars["submenu"] = "styles"; - $ste->vars["pagetitle"] = $translation["menu_styles"]; - - if(isset($style)) - { - try - { - $style = Style::by_name($style); - $ste->vars["style_name"] = $style->name; - $ste->vars["style_code"] = $style->code; - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - } - - /* Was there a delete request? */ - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["styles_multiselect"] as $stylename) - { - try - { - $style = Style::by_name($stylename); - $style->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - $ste->vars["success"] = $translation["styles_successfully_deleted"]; - } - - /* A write request? */ - if(isset($_POST["save_style"])) - { - if(Style::test_name($_POST["style_name"])) - { - $ste->vars["style_name"] = $_POST["style_name"]; - $ste->vars["style_code"] = $_POST["style_code"]; - - try - { - $style = Style::by_name($_POST["style_name"]); - } - catch(DoesNotExistError $e) - { - $style = Style::create($_POST["style_name"]); - } - - $style->code = $_POST["style_code"]; - $style->save(); - - $ste->vars["success"] = $translation["style_successfully_saved"]; - } - else - $ste->vars["error"] = $translation["invalid_style_name"]; - } - - /* Get all styles */ - $ste->vars["styles"] = array_map(function($s) { return $s->name; }, Style::all()); - sort($ste->vars["styles"]); - - echo $ste->exectemplate("/systemtemplates/styles.html"); - }, - "sections" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings; - - list($style) = $url_next; - - $url_next = array(); - - $ste->vars["section"] = "design"; - $ste->vars["submenu"] = "sections"; - $ste->vars["pagetitle"] = $translation["menu_pagesections"]; - - /* New section? */ - if(isset($_POST["new_section"])) - { - try - { - Section::by_name($_POST["section_name"]); - $ste->vars["error"] = $translation["section_already_exists"]; - } - catch(DoesNotExistError $e) - { - if((preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["template"]) == 0) or (!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['template']}"))) - $ste->vars["error"] = $translation["unknown_template"]; - else if(!Section::test_name($_POST["section_name"])) - $ste->vars["error"] = $translation["invalid_section_name"]; - else - { - $section = Section::create($_POST["section_name"]); - $section->template = $_POST["template"]; - $section->title[$data["user"]->language] = new Translation($_POST["section_name"], ""); - $section->save(); - $ste->vars["success"] = $translation["section_created_successfully"]; - } - } - } - - /* Remove a style? */ - if(isset($_GET["rmstyle"]) and isset($_GET["rmfrom"])) - { - try - { - $section = Section::by_name($_GET["rmfrom"]); - $style = Style::by_name($_GET["rmstyle"]); - $section->remove_style($style); - $section->save(); - $ste->vars["success"] = $translation["style_removed"]; - } - catch(DoesNotExistError $e) - { - } - } - - /* Delete a section? */ - if(isset($_POST["delete"]) and (@$_POST["really_delete"] == "yes") and isset($_POST["section_select"])) - { - try - { - $section = Section::by_name($_POST["section_select"]); - if($section->get_id() == $ratatoeskr_settings["default_section"]) - $ste->vars["error"] = $translation["cannot_delete_default_section"]; - else - { - $default_section = Section::by_id($ratatoeskr_settings["default_section"]); - foreach($section->get_articles() as $article) - { - $article->set_section($default_section); - $article->save(); - } - $section->delete(); - $ste->vars["success"] = $translation["section_successfully_deleted"]; - } - } - catch(DoesNotExistError $e) - { - } - } - - /* Make section default? */ - if(isset($_POST["make_default"]) and isset($_POST["section_select"])) - { - try - { - $section = Section::by_name($_POST["section_select"]); - $ratatoeskr_settings["default_section"] = $section->get_id(); - $ste->vars["success"] = $translation["default_section_changed_successfully"]; - } - catch(DoesNotExistError $e) - { - } - } - - /* Set template? */ - if(isset($_POST["set_template"]) and isset($_POST["section_select"])) - { - try - { - $section = Section::by_name($_POST["section_select"]); - if((preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["set_template_to"]) == 0) or (!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['set_template_to']}"))) - $ste->vars["error"] = $translation["unknown_template"]; - else - { - $section->template = $_POST["set_template_to"]; - $section->save(); - $ste->vars["success"] = $translation["successfully_set_template"]; - } - } - catch(DoesNotExistError $e) - { - } - } - - /* Adding a style? */ - if(isset($_POST["add_style"]) and isset($_POST["section_select"])) - { - try - { - $section = Section::by_name($_POST["section_select"]); - $style = Style::by_name($_POST["style_to_add"]); - $section->add_style($style); - $ste->vars["success"] = $translation["successfully_added_style"]; - } - catch(DoesNotExistError $e) - { - } - } - - /* Set/unset title? */ - if(isset($_POST["set_title"]) and isset($_POST["section_select"])) - { - if(!isset($languages[$_POST["set_title_lang"]])) - $ste->vars["error"] = $translation["language_unknown"]; - else - { - try - { - $section = Section::by_name($_POST["section_select"]); - if(!empty($_POST["set_title_text"])) - $section->title[$_POST["set_title_lang"]] = new Translation($_POST["set_title_text"], ""); - else if(isset($section->title[$_POST["set_title_lang"]])) - unset($section->title[$_POST["set_title_lang"]]); - $section->save(); - $ste->vars["success"] = $translation["successfully_set_section_title"]; - } - catch(DoesNotExistError $e) - { - } - } - } - - /* Get all templates */ - $ste->vars["templates"] = array(); - $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates"); - foreach($tpldir as $fo) - { - if($fo->isFile()) - $ste->vars["templates"][] = $fo->getFilename(); - } - sort($ste->vars["templates"]); - - /* Get all styles */ - $ste->vars["styles"] = array_map(function($s) { return $s->name; }, Style::all()); - sort($ste->vars["styles"]); - - /* Get all sections */ - $sections = Section::all(); - $ste->vars["sections"] = array_map(function($section) use ($ratatoeskr_settings) { - $titles = array(); - foreach($section->title as $l => $t) - $titles[$l] = $t->text; - return array( - "name" => $section->name, - "title" => $titles, - "template" => $section->template, - "styles" => array_map(function($style) { return $style->name; }, $section->get_styles()), - "default" => ($section->get_id() == $ratatoeskr_settings["default_section"]) - ); - }, $sections); - - echo $ste->exectemplate("/systemtemplates/sections.html"); - } - )), - "admin" => url_action_subactions(array( - "settings" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors; - - $url_next = array(); - - $ste->vars["section"] = "admin"; - $ste->vars["submenu"] = "settings"; - $ste->vars["pagetitle"] = $translation["menu_settings"]; - - $ste->vars["textprocessors"] = array(); - foreach($textprocessors as $txtproc => $properties) - if($properties[1]) - $ste->vars["textprocessors"][] = $txtproc; - - /* Toggle debugmode value? */ - if(isset($_POST["toggle_debugmode"])) - { - if(isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]) - { - $ratatoeskr_settings["debugmode"] = False; - $ste->vars["success"] = $translation["debugmode_now_disabled"]; - } - else - { - $ratatoeskr_settings["debugmode"] = True; - $ste->vars["success"] = $translation["debugmode_now_enabled"]; - } - } - - /* Save comment settings? */ - if(isset($_POST["save_comment_settings"])) - { - if(!in_array(@$_POST["comment_textprocessor"], $ste->vars["textprocessors"])) - $ste->vars["error"] = $translation["unknown_txtproc"]; - else - { - $ratatoeskr_settings["comment_textprocessor"] = $_POST["comment_textprocessor"]; - $ratatoeskr_settings["comment_visible_default"] = (isset($_POST["comment_auto_visible"]) and ($_POST["comment_auto_visible"] == "yes")); - $ste->vars["success"] = $translation["comment_settings_successfully_saved"]; - } - } - - /* Delete language? */ - if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes") and isset($_POST["language_select"])) - { - if($ratatoeskr_settings["default_language"] == $_POST["language_select"]) - $ste->vars["error"] = $translation["cannot_delete_default_language"]; - else - { - $ratatoeskr_settings["languages"] = array_filter($ratatoeskr_settings["languages"], function($l) { return $l != $_POST["language_select"]; }); - $ste->vars["success"] = $translation["language_successfully_deleted"]; - } - } - - /* Set default language */ - if(isset($_POST["make_default"]) and isset($_POST["language_select"])) - { - if(in_array($_POST["language_select"], $ratatoeskr_settings["languages"])) - { - $ratatoeskr_settings["default_language"] = $_POST["language_select"]; - $ste->vars["success"] = $translation["successfully_set_default_language"]; - } - } - - /* Add a language */ - if(isset($_POST["add_language"])) - { - if(!isset($languages[$_POST["language_to_add"]])) - $ste->vars["error"] = $translation["language_unknown"]; - else - { - if(!in_array($_POST["language_to_add"], $ratatoeskr_settings["languages"])) - { - $ls = $ratatoeskr_settings["languages"]; - $ls[] = $_POST["language_to_add"]; - $ratatoeskr_settings["languages"] = $ls; - } - $ste->vars["success"] = $translation["language_successfully_added"]; - } - } - - $ste->vars["debugmode_enabled"] = (isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]); - $ste->vars["comment_auto_visible"] = $ratatoeskr_settings["comment_visible_default"]; - $ste->vars["comment_textprocessor"] = $ratatoeskr_settings["comment_textprocessor"]; - $ste->vars["used_langs"] = array_map(function ($l) use ($ratatoeskr_settings, $languages) { return array( - "code" => $l, - "name" => $languages[$l]["language"], - "default" => ($l == $ratatoeskr_settings["default_language"]) - );}, $ratatoeskr_settings["languages"]); - - echo $ste->exectemplate("/systemtemplates/settings.html"); - }, - "users" => url_action_subactions(array( - "_index" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors; - - $url_next = array(); - - $ste->vars["section"] = "admin"; - $ste->vars["submenu"] = "users"; - $ste->vars["pagetitle"] = $translation["menu_users_groups"]; - - /* Add a new group? */ - if(isset($_POST["new_group"])) - { - if(empty($_POST["group_name"])) - $ste->vars["error"] = $translation["empty_group_name"]; - else - { - try - { - Group::by_name($_POST["group_name"]); - $ste->vars["error"] = $translation["group_already_exists"]; - } - catch(DoesNotExistError $e) - { - $group = Group::create($_POST["group_name"]); - $ste->vars["success"] = $translation["successfully_created_group"]; - } - } - } - - /* Add a new user? */ - if(isset($_POST["new_user"])) - { - if(empty($_POST["username"])) - $ste->vars["error"] = $translation["empty_username"]; - else - { - try - { - User::by_name($_POST["username"]); - $ste->vars["error"] = $translation["user_already_exists"]; - } - catch(DoesNotExistError $e) - { - $group = User::create($_POST["username"], PasswordHash::create($_POST["initial_password"])); - $ste->vars["success"] = $translation["successfully_created_user"]; - } - } - } - - /* Delete groups? */ - if(isset($_POST["delete_groups"]) and ($_POST["really_delete"] == "yes") and (!empty($_POST["groups_multiselect"]))) - { - $deleted = 0; - foreach($_POST["groups_multiselect"] as $gid) - { - try - { - $group = Group::by_id($gid); - if($group->name == "admins") - { - $ste->vars["error"] = $translation["cannot_delete_admin_group"]; - } - else - { - $group->delete(); - ++$deleted; - } - } - catch(DoesNotExistError $e) - { - continue; - } - } - if($deleted > 0) - $ste->vars["success"] = $translation["successfully_deleted_groups"]; - } - - /* Delete users? */ - if(isset($_POST["delete_users"]) and ($_POST["really_delete"] == "yes") and (!empty($_POST["users_multiselect"]))) - { - $deleted = 0; - foreach($_POST["users_multiselect"] as $uid) - { - if($uid == $data["user"]->get_id()) - $ste->vars["error"] = $translation["cannot_delete_yourself"]; - else - { - try - { - $user = User::by_id($uid); - $user->delete(); - ++$deleted; - } - catch(DoesNotExistError $e) - { - continue; - } - } - } - if($deleted > 0) - $ste->vars["success"] = $translation["successfully_deleted_users"]; - } - - /* Get all groups */ - $ste->vars["groups"] = array_map(function($g) { return array( - "id" => $g->get_id(), - "name" => $g->name - ); }, Group::all()); - - /* Get all users */ - $ste->vars["users"] = array_map(function($u) { return array( - "id" => $u->get_id(), - "name" => $u->username, - "memberof" => array_map(function($g) { return $g->name; }, $u->get_groups()), - "fullname" => $u->fullname, - "mail" => $u->mail - ); }, User::all()); - - echo $ste->exectemplate("/systemtemplates/users.html"); - }, - "u" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $admin_grp; - - try - { - $user = User::by_id($url_next[0]); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - $url_next = array(); - - $ste->vars["section"] = "admin"; - $ste->vars["submenu"] = "users"; - $ste->vars["pagetitle"] = $user->username; - - /* Modify data? */ - if(isset($_POST["change_data"])) - { - $user->fullname = $_POST["fullname"]; - $user->mail = $_POST["mail"]; - $user->language = $_POST["lang"]; - - $current_groups = array_map(function($g) { return $g->get_id(); }, $user->get_groups()); - $new_groups = empty($_POST[groups_multiselect]) ? array() : $_POST["groups_multiselect"]; - $groups_exclude = array_diff($current_groups, $new_groups); - $groups_include = array_diff($new_groups, $current_groups); - - foreach($groups_exclude as $gid) - { - try - { - $g = Group::by_id($gid); - $g->exclude_user($user); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - foreach($groups_include as $gid) - { - try - { - $g = Group::by_id($gid); - $g->include_user($user); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $user->save(); - - $ste->vars["success"] = $translation["successfully_modified_user"]; - } - - /* New Password? */ - if(isset($_POST["new_password"])) - { - $pwhash = PasswordHash::create($_POST["password"]); - $user->pwhash = $pwhash; - if($user->get_id() == $data["user"]->get_id()) - $_SESSION["ratatoeskr_pwhash"] = $pwhash; - $user->save(); - - $ste->vars["success"] = $translation["successfully_set_new_password"]; - } - - /* Put data to STE */ - $ste->vars["u"] = array( - "id" => $user->get_id(), - "name" => $user->username, - "fullname" => $user->fullname, - "mail" => $user->mail, - "lang" => $user->language - ); - $ste->vars["groups"] = array_map(function($g) use ($user) { return array( - "id" => $g->get_id(), - "name" => $g->name, - "member" => $user->member_of($g) - ); }, Group::all()); - - echo $ste->exectemplate("/systemtemplates/user.html"); - } - )), - "repos" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - $url_next = array(); - - $ste->vars["section"] = "admin"; - $ste->vars["submenu"] = "repos"; - $ste->vars["pagetitle"] = $translation["menu_plugin_repos"]; - - /* Add a repo? */ - if(isset($_POST["add_repo"])) - { - try - { - $repo = Repository::create($_POST["repo_baseurl"]); - $ste->vars["success"] = $translation["successfully_added_repo"]; - } - catch(RepositoryUnreachableOrInvalid $e) - { - $ste->vars["error"] = $translation["repository_unreachable_or_invalid"]; - } - } - - /* Delete repos? */ - if(isset($_POST["delete_repos"]) and ($_POST["really_delete"] == "yes")) - { - foreach($_POST["repos_multiselect"] as $repo_id) - { - try - { - $repo = Repository::by_id($repo_id); - $repo->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - $ste->vars["success"] = $translation["repos_deleted"]; - } - - /* Force refresh? */ - if(isset($_POST["force_repo_refresh"])) - { - $failed = array(); - foreach($_POST["repos_multiselect"] as $repo_id) - { - try - { - $repo = Repository::by_id($repo_id); - $repo->refresh(True); - } - catch(DoesNotExistError $e) - { - continue; - } - catch(RepositoryUnreachableOrInvalid $e) - { - $failed[] = $repo->get_name(); - } - } - $ste->vars["success"] = $translation["successfully_refreshed_repos"]; - if(!empty($failed)) - $ste->vars["error"] = str_replace("[[REPOS]]", implode(", ", $failed), $translation["repo_refresh_failed_on"]); - } - - /* Fill data */ - $all_repos = Repository::all(); - $ste->vars["repos"] = array_map( - function($r) - { - try - { - $r->refresh(); - } - catch(RepositoryUnreachableOrInvalid $e){} - return array( - "id" => $r->get_id(), - "name" => $r->get_name(), - "description" => $r->get_description(), - "baseurl" => $r->get_baseurl() - ); - }, $all_repos); - - echo $ste->exectemplate("/systemtemplates/repos.html"); - } - )), - "plugin" => url_action_subactions(array( - "list" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $plugin_objs, $api_compat; - - $url_next = array(); - - $ste->vars["section"] = "plugins"; - $ste->vars["submenu"] = "pluginlist"; - $ste->vars["pagetitle"] = $translation["menu_pluginlist"]; - - /* Delete plugins? */ - if(isset($_POST["delete"]) and (($_POST["really_delete"] == "yes") or ($_POST["really_delete"] == "force")) and (!empty($_POST["plugins_multiselect"]))) - { - foreach($_POST["plugins_multiselect"] as $pid) - { - try - { - $plugin = Plugin::by_id($pid); - if($_POST["really_delete"] != "force") - { - if(!isset($plugin_objs[$pid])) - { - eval($plugin->code); - $plugin_objs[$pid] = new $plugin->classname($pid); - } - $plugin_objs[$pid]->uninstall(); - } - $plugin->delete(); - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $ste->vars["success"] = $translation["successfully_deleted_plugins"]; - } - - /* Activate or deactivate plugins? */ - if((isset($_POST["activate"]) or isset($_POST["deactivate"])) and (!empty($_POST["plugins_multiselect"]))) - { - $api_incompat = array(); - $newstatus = isset($_POST["activate"]); - foreach($_POST["plugins_multiselect"] as $pid) - { - try - { - $plugin = Plugin::by_id($pid); - if(!$plugin->installed) - continue; - if($newstatus and (!in_array($plugin->api, $api_compat))) - { - $api_incompat[] = $plugin->name . ("(ID: " . $plugin->get_id() . ")"); - continue; - } - $plugin->active = $newstatus; - $plugin->save(); - if($newstatus and (!isset($plugin_objs[$pid]))) - { - eval($plugin->code); - $plugin_objs[$pid] = new $plugin->classname($pid); - $plugin_objs[$pid]->init(); - } - } - catch(DoesNotExistError $e) - { - continue; - } - } - - $ste->vars["success"] = $translation[$newstatus ? "plugins_activated" : "plugins_deactivated"]; - - if(!empty($api_incompat)) - $ste->vars["error"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["could_not_activate_plugin_api_incompat"])); - } - - $stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); - - /* Update plugins? */ - if(isset($_POST["update"]) and (!empty($_POST["plugins_multiselect"]))) - { - $updated = array(); - foreach($_POST["plugins_multiselect"] as $pid) - { - try - { - $plugin = Plugin::by_id($pid); - if(!empty($plugin->updatepath)) - { - $update_info = @unserialize(@file_get_contents($plugin->updatepath, False, $stream_ctx)); - if(is_array($update_info) and (($update_info["current-version"]+0) > ($plugin->versioncount+0))) - { - $pkg = PluginPackage::load(@file_get_contents($update_info["dl-path"], False, $stream_ctx)); - $plugin->fill_from_pluginpackage($pkg); - $plugin->update = True; - $plugin->save(); - $updated[] = $plugin->name; - } - } - } - catch(DoesNotExistError $e) - { - continue; - } - catch(InvalidPackage $e) - { - continue; - } - } - - if(empty($updated)) - $ste->vars["success"] = $translation["nothing_to_update"]; - else - $ste->vars["success"] = str_replace("[[PLUGINS]]", implode(", ", $updated), $translation["successfully_updated_plugins"]); - } - - /* Load plugin data */ - $all_plugins = Plugin::all(); - $ste->vars["plugins"] = array(); - $api_incompat = array(); - foreach($all_plugins as $p) - { - if(!$p->installed) - continue; - - if(!in_array($p->api, $api_compat)) - $api_incompat[] = $p->name . ("(ID: " . $p->get_id() . ")"); - - $ste->vars["plugins"][] = array( - "id" => $p->get_id(), - "name" => $p->name, - "versiontext" => $p->versiontext, - "active" => $p->active, - "description" => $p->short_description, - "web" => $p->web, - "author" => $p->author, - "help" => !empty($p->help) - ); - } - - if(!empty($api_incompat)) - $ste->vars["notice"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["plugins_incompat"])); - - echo $ste->exectemplate("/systemtemplates/pluginlist.html"); - }, - "help" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - try - { - $plugin = Plugin::by_id($url_next[0]); - if(empty($plugin->help)) - throw new NotFoundError(); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - $url_next = array(); - - $ste->vars["section"] = "plugins"; - $ste->vars["submenu"] = ""; - $ste->vars["pagetitle"] = $plugin->name; - $ste->vars["help"] = $plugin->help; - - echo $ste->exectemplate("/systemtemplates/pluginhelp.html"); - }, - "install" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root, $api_compat; - - $url_next = array(); - - $ste->vars["section"] = "plugins"; - $ste->vars["submenu"] = "installplugins"; - $ste->vars["pagetitle"] = $translation["menu_plugininstall"]; - - $all_repos = Repository::all(); - foreach($all_repos as $repo) - { - try - { - $repo->refresh(); - } - catch(RepositoryUnreachableOrInvalid $e) - { - continue; - } - } - - if(isset($_POST["installpackage"])) - { - if(is_uploaded_file($_FILES["pluginpackage"]["tmp_name"])) - { - try - { - $package = PluginPackage::load(file_get_contents($_FILES["pluginpackage"]["tmp_name"])); - unlink($_FILES["pluginpackage"]["tmp_name"]); - if(in_array($package->api, $api_compat)) - { - $plugin = Plugin::create(); - $plugin->fill_from_pluginpackage($package); - $plugin->installed = False; - $plugin->active = False; - $plugin->save(); - $url_next = array("confirminstall", (string) $plugin->get_id()); - return; - } - else - $ste->vars["error"] = str_replace("[[API]]", $package->api, $translation["incompatible_plugin"]); - } - catch(InvalidPackage $e) - { - $ste->vars["error"] = $translation["invalid_package"]; - unlink($_FILES["pluginpackage"]["tmp_name"]); - } - } - else - $ste->vars["error"] = $translation["upload_failed"]; - } - - if(isset($_POST["search_in_repos"])) - { - $ste->vars["searchresults"] = array(); - $repos_to_scan = ($_POST["searchin"] == "*") ? $all_repos : Repository::by_id($_POST["searchin"]); - $searchfor = strtolower($_POST["searchfor"]); - foreach($repos_to_scan as $repo) - { - foreach($repo->packages as $pkg) - { - if(empty($searchfor) or (strpos(strtolower($pkg[0]), $searchfor) !== False) or (strpos(strtolower($pkg[2]), $searchfor) !== False)) - $ste->vars["searchresults"][] = array( - "name" => $pkg[0], - "description" => $pkg[2], - "reponame" => $repo->get_name(), - "repoid" => $repo->get_id() - ); - } - } - } - - $ste->vars["repos"] = array_map(function($r) { return array( - "id" => $r->get_id(), - "name" => $r->get_name() - ); }, $all_repos); - - echo $ste->exectemplate("/systemtemplates/plugininstall.html"); - }, - "repoinstall" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $rel_path_to_root; - - $stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); - - try - { - $repo = Repository::by_id($_GET["repo"]); - $pkg = $repo->download_package($_GET["pkg"]); - $plugin = Plugin::create(); - $plugin->fill_from_pluginpackage($pkg); - $plugin->installed = False; - $plugin->active = False; - $plugin->save(); - $url_next = array("confirminstall", (string) $plugin->get_id()); - } - catch(DoesNotExistError $e) - { - $ste->vars["error"] = $translation["package_or_repo_not_found"]; - $url_next = array("install"); - } - catch(InvalidPackage $e) - { - $ste->vars["error"] = $translation["invalid_package"]; - $url_next = array("install"); - } - }, - "confirminstall" => function(&$data, $url_now, &$url_next) - { - global $ste, $translation, $languages, $rel_path_to_root; - - list($plugin_id) = $url_next; - $url_next = array(); - - $ste->vars["section"] = "plugins"; - $ste->vars["submenu"] = "installplugins"; - $ste->vars["pagetitle"] = $translation["menu_plugininstall"]; - - try - { - $plugin = Plugin::by_id($plugin_id); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - - if($plugin->installed) - throw new NotFoundError(); - - $ste->vars["plugin_id"] = $plugin->get_id(); - $ste->vars["name"] = $plugin->name; - $ste->vars["description"] = $plugin->short_description; - $ste->vars["code"] = $plugin->code; - $ste->vars["license"] = $plugin->license; - - if(isset($_POST["yes"])) - { - $plugin->installed = True; - $plugin->save(); - eval($plugin->code); - $plugin_instance = new $plugin->classname($plugin->get_id()); - $plugin_instance->install(); - $ste->vars["success"] = $translation["plugin_installed_successfully"]; - $url_next = array("list"); - return; - } - - if(isset($_POST["no"])) - { - $plugin->delete(); - $url_next = array("install"); - return; - } - - echo $ste->exectemplate("/systemtemplates/confirminstall.html"); - } - )), - "pluginpages" => url_action_subactions($pluginpages_handlers) + "_index" => url_action_alias(array("login")), + "index" => url_action_alias(array("login")), + /* _prelude guarantees that the user is logged in properly, so we do not have to care about that later, and sets some STE vars. */ + "_prelude" => function(&$data, $url_now, &$url_next) + { + global $ratatoeskr_settings, $admin_grp, $ste, $languages; + + if($admin_grp === NULL) + $admin_grp = Group::by_name("admins"); + + $ste->vars["all_languages"] = array(); + $ste->vars["all_langcodes"] = array(); + foreach($languages as $code => $data) + { + $ste->vars["all_languages"][$code] = $data["language"]; + $ste->vars["all_langcodes"][] = $code; + } + ksort($ste->vars["all_languages"]); + sort($ste->vars["all_langcodes"]); + + + /* Check authentification */ + if(isset($_SESSION["ratatoeskr_uid"])) + { + try + { + $user = User::by_id($_SESSION["ratatoeskr_uid"]); + if(($user->pwhash == $_SESSION["ratatoeskr_pwhash"]) and $user->member_of($admin_grp)) + { + if(empty($user->language)) + { + $user->language = $ratatoeskr_settings["default_language"]; + $user->save(); + } + load_language($user->language); + + if($url_next[0] == "login") + $url_next = array("content", "write"); + $data["user"] = $user; + $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language); + + return; /* Authentification successful, continue */ + } + else + unset($_SESSION["ratatoeskr_uid"]); + } + catch(DoesNotExistError $e) + { + unset($_SESSION["ratatoeskr_uid"]); + } + } + load_language(); + + /* If we are here, user is not logged in... */ + $url_next = array("login"); + }, + "login" => url_action_simple(function($data) + { + global $ste, $admin_grp; + if(!empty($_POST["user"])) + { + try + { + $user = User::by_name($_POST["user"]); + if(!PasswordHash::validate($_POST["password"], $user->pwhash)) + throw new Exception(); + if(!$user->member_of($admin_grp)) + throw new Exception(); + + /* Login successful. */ + $_SESSION["ratatoeskr_uid"] = $user->get_id(); + $_SESSION["ratatoeskr_pwhash"] = $user->pwhash; + load_language($user->language); + $data["user"] = $user; + $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language); + } + catch(Exception $e) + { + $ste->vars["login_failed"] = True; + } + + if(isset($data["user"])) + throw new Redirect(array("content", "write")); + } + + echo $ste->exectemplate("/systemtemplates/backend_login.html"); + }), + "logout" => url_action_simple(function($data) + { + unset($_SESSION["ratatoeskr_uid"]); + unset($_SESSION["ratatoeskr_pwhash"]); + load_language(); + throw new Redirect(array("login")); + }), + "content" => url_action_subactions(array( + "write" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $textprocessors, $ratatoeskr_settings, $languages, $articleeditor_plugins; + + list($article, $editlang) = array_slice($url_next, 0); + if(!isset($editlang)) + $editlang = $data["user"]->language; + if(isset($article)) + $ste->vars["article_editurl"] = urlencode($article) . "/" . urlencode($editlang); + else + $ste->vars["article_editurl"] = ""; + + $url_next = array(); + + $default_section = Section::by_id($ratatoeskr_settings["default_section"]); + + $ste->vars["section"] = "content"; + $ste->vars["submenu"] = isset($article) ? "articles" : "newarticle"; + + $ste->vars["textprocessors"] = array(); + foreach($textprocessors as $txtproc => $properties) + if($properties[1]) + $ste->vars["textprocessors"][] = $txtproc; + + $ste->vars["sections"] = array(); + foreach(Section::all() as $section) + $ste->vars["sections"][] = $section->name; + $ste->vars["article_section"] = $default_section->name; + + /* Check Form */ + $fail_reasons = array(); + + if(isset($_POST["save_article"])) + { + if(!Article::test_urlname($_POST["urlname"])) + $fail_reasons[] = $translation["invalid_urlname"]; + else + $inputs["urlname"] = $_POST["urlname"]; + if(!Article::test_status(@$_POST["article_status"])) + $fail_reasons[] = $translation["invalid_article_status"]; + else + $inputs["article_status"] = (int) $_POST["article_status"]; + if(!isset($textprocessors[@$_POST["content_txtproc"]])) + $fail_reasons[] = $translation["unknown_txtproc"]; + else + $inputs["content_txtproc"] = $_POST["content_txtproc"]; + if(!isset($textprocessors[@$_POST["excerpt_txtproc"]])) + $fail_reasons[] = $translation["unknown_txtproc"]; + else + $inputs["excerpt_txtproc"] = $_POST["excerpt_txtproc"]; + if(!empty($_POST["date"])) + { + if(($time_tmp = @DateTime::createFromFormat("Y-m-d H:i:s", @$_POST["date"])) === False) + $fail_reasons[] = $translation["invalid_date"]; + else + $inputs["date"] = @$time_tmp->getTimestamp(); + } + else + $inputs["date"] = time(); + $inputs["allow_comments"] = !(empty($_POST["allow_comments"]) or ($_POST["allow_comments"] != "yes")); + + try + { + $inputs["article_section"] = Section::by_name($_POST["section"]); + } + catch(DoesNotExistError $e) + { + $fail_reasons[] = $translation["unknown_section"]; + } + + $inputs["title"] = $_POST["title"]; + $inputs["content"] = $_POST["content"]; + $inputs["excerpt"] = $_POST["excerpt"]; + $inputs["tags"] = array_filter(array_map("trim", explode(",", $_POST["tags"])), function($t) { return !empty($t); }); + if(isset($_POST["saveaslang"])) + $editlang = $_POST["saveaslang"]; + } + else + { + /* Call articleeditor plugins */ + $article = empty($article) ? NULL : Article::by_urlname($article); + foreach($articleeditor_plugins as $plugin) + call_user_func($plugin["fx"], $article, False); + } + + function fill_article(&$article, $inputs, $editlang) + { + $article->urlname = $inputs["urlname"]; + $article->status = $inputs["article_status"]; + $article->timestamp = $inputs["date"]; + $article->title[$editlang] = new Translation($inputs["title"], ""); + $article->text[$editlang] = new Translation($inputs["content"], $inputs["content_txtproc"]); + $article->excerpt[$editlang] = new Translation($inputs["excerpt"], $inputs["excerpt_txtproc"]); + $article->set_tags(maketags($inputs["tags"], $editlang)); + $article->set_section($inputs["article_section"]); + $article->allow_comments = $inputs["allow_comments"]; + } + + if(empty($article)) + { + /* New Article */ + $ste->vars["pagetitle"] = $translation["new_article"]; + if(empty($fail_reasons) and isset($_POST["save_article"])) + { + $article = Article::create($inputs["urlname"]); + fill_article($article, $inputs, $editlang); + + /* Calling articleeditor plugins */ + $call_after_save = array(); + foreach($articleeditor_plugins as $plugin) + { + $result = call_user_func($plugin["fx"], $article, True); + if(is_string($result)) + $fail_reasons[] = $result; + elseif($result !== NULL) + $call_after_save[] = $result; + } + + if(empty($fail_reasons)) + { + try + { + $article->save(); + foreach($call_after_save as $cb) + call_user_func($cb, $article); + $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang); + $ste->vars["success"] = htmlesc($translation["article_save_success"]); + } + catch(AlreadyExistsError $e) + { + $fail_reasons[] = $translation["article_name_already_in_use"]; + } + } + } + } + else + { + try + { + if(!($article instanceof Article)) + $article = Article::by_urlname($article); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + if(empty($fail_reasons) and isset($_POST["save_article"])) + { + fill_article($article, $inputs, $editlang); + + /* Calling articleeditor plugins */ + $call_after_save = array(); + foreach($articleeditor_plugins as $plugin) + { + $result = call_user_func($plugin["fx"], $article, True); + if(is_string($result)) + $fail_reasons[] = $result; + elseif($result !== NULL) + $call_after_save[] = $result; + } + + if(empty($fail_reasons)) + { + try + { + $article->save(); + foreach($call_after_save as $cb) + call_user_func($cb, $article); + $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang); + $ste->vars["success"] = htmlesc($translation["article_save_success"]); + } + catch(AlreadyExistsError $e) + { + $fail_reasons[] = $translation["article_name_already_in_use"]; + } + } + } + + if(!isset($article->title[$editlang])) + { + $langs_available = array(); + foreach($article->title as $lang => $_) + $langs_available[] = $lang; + $editlang = $langs_available[0]; + } + + foreach(array( + "urlname" => "urlname", + "status" => "article_status", + "timestamp" => "date", + "allow_comments" => "allow_comments" + ) as $prop => $k_out) + { + if(!isset($inputs[$k_out])) + $inputs[$k_out] = $article->$prop; + } + if(!isset($inputs["title"])) + $inputs["title"] = $article->title[$editlang]->text; + if(!isset($inputs["content"])) + { + $translation_obj = $article->text[$editlang]; + $inputs["content"] = $translation_obj->text; + $inputs["content_txtproc"] = $translation_obj->texttype; + } + if(!isset($inputs["excerpt"])) + { + $translation_obj = $article->excerpt[$editlang]; + $inputs["excerpt"] = $translation_obj->text; + $inputs["excerpt_txtproc"] = $translation_obj->texttype; + } + if(!isset($inputs["article_section"])) + $inputs["article_section"] = $article->get_section(); + if(!isset($inputs["tags"])) + $inputs["tags"] = array_map(function($tag) use ($editlang) { return $tag->name; }, $article->get_tags()); + $ste->vars["morelangs"] = array(); + $ste->vars["pagetitle"] = $article->title[$editlang]->text; + foreach($article->title as $lang => $_) + { + if($lang != $editlang) + $ste->vars["morelangs"][] = array("url" => urlencode($article->urlname) . "/$lang", "full" => "($lang) " . $languages[$lang]["language"]); + } + } + + if(!isset($inputs["date"])) + $inputs["date"] = time(); + if(!isset($inputs["article_status"])) + $inputs["article_status"] = ARTICLE_STATUS_LIVE; + + /* Push data back to template */ + if(isset($inputs["tags"])) + $ste->vars["tags"] = implode(", ", $inputs["tags"]); + if(isset($inputs["article_section"])) + $ste->vars["article_section"] = $inputs["article_section"]->name; + $ste->vars["editlang"] = $editlang; + foreach(array( + "urlname" => "urlname", + "article_status" => "article_status", + "title" => "title", + "content_txtproc" => "content_txtproc", + "content" => "content", + "excerpt_txtproc" => "excerpt_txtproc", + "excerpt" => "excerpt", + "date" => "date", + "allow_comments" => "allow_comments" + ) as $k_in => $k_out) + { + if(isset($inputs[$k_in])) + $ste->vars[$k_out] = $inputs[$k_in]; + } + + /* Displaying article editor plugins */ + $ste->vars["displayed_plugins"] = array_map(function($x) { return array("label" => $x["label"], "template" => $x["template"]); }, array_filter($articleeditor_plugins, function($x) { return $x["display"]; })); + + if(!empty($fail_reasons)) + $ste->vars["failed"] = $fail_reasons; + + echo $ste->exectemplate("/systemtemplates/content_write.html"); + }, + "tags" => function(&$data, $url_now, &$url_next) + { + global $translation, $languages, $ste, $rel_path_to_root; + + $url_next = array(); + + $ste->vars["section"] = "content"; + $ste->vars["submenu"] = "tags"; + $ste->vars["pagetitle"] = $translation["tags_overview"]; + + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["tag_multiselect"] as $tagid) + { + try + { + $tag = Tag::by_id($tagid); + $tag->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $ste->vars["success"] = $translation["tags_successfully_deleted"]; + } + + if(isset($_POST["save_changes"])) + { + $newlang = (!empty($_POST["new_language"])) ? $_POST["new_language"] : NULL; + $newtag = NULL; + + if(!empty($_POST["newtagname"])) + { + if(!Tag::test_name(@$_POST["newtagname"])) + $ste->vars["error"] = $translation["invalid_tag_name"]; + else + $newtag = $_POST["newtagname"]; + } + + if(($newlang !== NULL) and (!isset($languages[$newlang]))) + $newlang = NULL; + if($newtag !== NULL) + { + try + { + $newtag = Tag::create($newtag); + } + catch(AlreadyExistsError $e) + { + $newtag = NULL; + } + } + + $translations = array(); + foreach($_POST as $k => $v) + { + if(preg_match('/tagtrans_(NEW|[a-z]{2})_(.*)/', $k, $matches) == 1) + { + $lang = ($matches[1] == "NEW") ? $newlang : $matches[1]; + $tag = $matches[2]; + if($lang === NULL) + continue; + $translations[$tag][$lang] = $v; + } + } + + foreach($translations as $tag => $langmap) + { + if($tag == "NEW") + { + if($newtag === NULL) + continue; + $tag = $newtag; + } + else + { + try + { + $tag = Tag::by_id($tag); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + foreach($langmap as $l => $text) + { + if(empty($text)) + unset($tag->title[$l]); + else + $tag->title[$l] = new Translation($text, ""); + } + + $tag->save(); + } + + $ste->vars["success"] = $translation["tags_successfully_edited"]; + } + + $ste->vars["alltags"] = array(); + $taglangs = array(); + + $alltags = Tag::all(); + foreach($alltags as $tag) + { + $transls = array(); + foreach($tag->title as $l => $t) + { + if(!in_array($l, $taglangs)) + $taglangs[] = $l; + $transls[$l] = $t->text; + } + + $ste->vars["alltags"][] = array( + "id" => $tag->get_id(), + "name" => $tag->name, + "translations" => $transls + ); + } + + $unused_langs = array_diff(array_keys($languages), $taglangs); + + $ste->vars["all_tag_langs"] = array(); + foreach($taglangs as $l) + $ste->vars["all_tag_langs"][$l] = $languages[$l]["language"]; + $ste->vars["unused_languages"] = array(); + foreach($unused_langs as $l) + $ste->vars["unused_languages"][$l] = $languages[$l]["language"]; + + echo $ste->exectemplate("/systemtemplates/tags_overview.html"); + }, + "articles" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + $url_next = array(); + + $ste->vars["section"] = "content"; + $ste->vars["submenu"] = "articles"; + $ste->vars["pagetitle"] = $translation["menu_articles"]; + + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["article_multiselect"] as $article_urlname) + { + try + { + $article = Article::by_urlname($article_urlname); + $article->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $ste->vars["success"] = $translation["articles_deleted"]; + } + + $articles = Article::all(); + + /* Filtering */ + $filterquery = array(); + if(!empty($_GET["filter_urlname"])) + { + $searchfor = strtolower($_GET["filter_urlname"]); + $articles = array_filter($articles, function($a) use ($searchfor) { return strpos(strtolower($a->urlname), $searchfor) !== False; }); + $filterquery[] = "filter_urlname=" . urlencode($_GET["filter_urlname"]); + $ste->vars["filter_urlname"] = $_GET["filter_urlname"]; + } + if(!empty($_GET["filter_tag"])) + { + $searchfor = $_GET["filter_tag"]; + $articles = array_filter($articles, function($a) use ($searchfor) { foreach($a->get_tags() as $t) { if($t->name==$searchfor) return True; } return False; }); + $filterquery[] = "filter_tag=" . urlencode($searchfor); + $ste->vars["filter_tag"] = $searchfor; + } + if(!empty($_GET["filter_section"])) + { + $searchfor = $_GET["filter_section"]; + $articles = array_filter($articles, function($a) use ($searchfor) { return $a->get_section()->name == $searchfor; }); + $filterquery[] = "filter_section=" . urlencode($searchfor); + $ste->vars["filter_section"] = $searchfor; + } + $ste->vars["filterquery"] = implode("&", $filterquery); + + /* Sorting */ + if(isset($_GET["sort_asc"])) + { + switch($_GET["sort_asc"]) + { + case "date": + $ste->vars["sortquery"] = "sort_asc=date"; + $ste->vars["sort_asc_date"] = True; + $ste->vars["sorting"] = array("dir" => "asc", "by" => "date"); + usort($articles, function($a, $b) { return intcmp($a->timestamp, $b->timestamp); }); + break; + case "section": + $ste->vars["sortquery"] = "sort_asc=section"; + $ste->vars["sort_asc_section"] = True; + $ste->vars["sorting"] = array("dir" => "asc", "by" => "section"); + usort($articles, function($a, $b) { return strcmp($a->get_section()->name, $b->get_section()->name); }); + break; + case "urlname": + $ste->vars["sortquery"] = "sort_asc=urlname"; + default: + $ste->vars["sort_asc_urlname"] = True; + $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); + usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); + break; + } + } + elseif(isset($_GET["sort_desc"])) + { + switch($_GET["sort_desc"]) + { + case "date": + $ste->vars["sortquery"] = "sort_desc=date"; + $ste->vars["sort_desc_date"] = True; + $ste->vars["sorting"] = array("dir" => "desc", "by" => "date"); + usort($articles, function($a, $b) { return intcmp($b->timestamp, $a->timestamp); }); + break; + case "section": + $ste->vars["sortquery"] = "sort_desc=section"; + $ste->vars["sort_desc_section"] = True; + $ste->vars["sorting"] = array("dir" => "desc", "by" => "section"); + usort($articles, function($a, $b) { return strcmp($b->get_section()->name, $a->get_section()->name); }); + break; + case "urlname": + $ste->vars["sortquery"] = "sort_desc=urlname"; + $ste->vars["sort_desc_urlname"] = True; + $ste->vars["sorting"] = array("dir" => "desc", "by" => "urlname"); + usort($articles, function($a, $b) { return strcmp($b->urlname, $a->urlname); }); + break; + default: + $ste->vars["sort_asc_urlname"] = True; + $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); + usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); + break; + } + } + else + { + $ste->vars["sort_asc_urlname"] = True; + $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname"); + usort($articles, function($a, $b) { return strcmp($a->urlname, $b->urlname); }); + } + + $ste->vars["articles"] = array_map(function($article) { + $avail_langs = array(); + foreach($article->title as $lang => $_) + $avail_langs[] = $lang; + sort($avail_langs); + $a_section = $article->get_section(); + return array( + "urlname" => $article->urlname, + "languages" => $avail_langs, + "date" => $article->timestamp, + "tags" => array_map(function($tag) { return $tag->name; }, $article->get_tags()), + "section" => array("id" => $a_section->get_id(), "name" => $a_section->name) + ); + }, $articles); + + echo $ste->exectemplate("/systemtemplates/articles.html"); + }, + "images" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + list($imgid, $imageaction) = $url_next; + + $url_next = array(); + + $ste->vars["section"] = "content"; + $ste->vars["submenu"] = "images"; + $ste->vars["pagetitle"] = $translation["menu_images"]; + + if(!empty($imgid) and is_numeric($imgid)) + { + try + { + $image = Image::by_id($imgid); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + if(empty($imageaction)) + throw new NotFoundError(); + else + { + if(($imageaction == "markdown") or ($imageaction == "html") or ($imageaction == "ste")) + { + $ste->vars["pagetitle"] = $translation["generate_embed_code"]; + $ste->vars["image_id"] = $image->get_id(); + $ste->vars["markup_variant"] = $imageaction; + if(isset($_POST["img_alt"])) + { + if($imageaction == "markdown") + $ste->vars["embed_code"] = "![" . str_replace("]", "\\]", $_POST["img_alt"]) . "](%root%/images/" . str_replace(")", "\\)", urlencode($image->get_filename())) . ")"; + elseif($imageaction == "html") + $ste->vars["embed_code"] = "<img src=\"%root%/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />"; + elseif($imageaction == "ste") + $ste->vars["embed_code"] = "<img src=\"\$rel_path_to_root/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />"; + } + + echo $ste->exectemplate("/systemtemplates/image_embed.html"); + } + else + throw new NotFoundError(); + } + return; + } + + /* Upload Form */ + if(isset($_POST["upload"])) + { + try + { + $image = Image::create((!empty($_POST["upload_name"])) ? $_POST["upload_name"] : $_FILES["upload_img"]["name"], $_FILES["upload_img"]["tmp_name"]); + $image->save(); + $ste->vars["success"] = $translation["upload_success"]; + } + catch(IOError $e) + { + $ste->vars["error"] = $translation["upload_failed"]; + } + catch(UnknownFileFormat $e) + { + $ste->vars["error"] = $translation["unknown_file_format"]; + } + } + + /* Mass delete */ + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["image_multiselect"] as $image_id) + { + try + { + $image = Image::by_id($image_id); + $image->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $ste->vars["success"] = $translation["images_deleted"]; + } + + $images = Image::all(); + + $ste->vars["images"] = array_map(function($img) { return array( + "id" => $img->get_id(), + "name" => $img->name, + "file" => $img->get_filename() + ); }, $images); + + echo $ste->exectemplate("/systemtemplates/image_list.html"); + }, + "comments" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + list($comment_id) = $url_next; + + $url_next = array(); + + $ste->vars["section"] = "content"; + $ste->vars["submenu"] = "comments"; + $ste->vars["pagetitle"] = $translation["menu_comments"]; + + /* Single comment? */ + if(!empty($comment_id)) + { + try + { + $comment = Comment::by_id($comment_id); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + if(!$comment->read_by_admin) + { + $comment->read_by_admin = True; + $comment->save(); + } + + if(isset($_POST["action_on_comment"])) + { + switch($_POST["action_on_comment"]) + { + case "delete": + $comment->delete(); + $ste->vars["success"] = $translation["comment_successfully_deleted"]; + goto backend_content_comments_overview; + break; + case "make_visible": + $comment->visible = True; + $comment->save(); + $ste->vars["success"] = $translation["comment_successfully_made_visible"]; + break; + case "make_invisible": + $comment->visible = False; + $comment->save(); + $ste->vars["success"] = $translation["comment_successfully_made_invisible"]; + break; + } + } + + $ste->vars["id"] = $comment->get_id(); + $ste->vars["visible"] = $comment->visible; + $ste->vars["article"] = $comment->get_article()->urlname; + $ste->vars["language"] = $comment->get_language(); + $ste->vars["date"] = $comment->get_timestamp(); + $ste->vars["author"] = "\"{$comment->author_name}\" <{$comment->author_mail}>"; + $ste->vars["comment_text"] = $comment->create_html(); + $ste->vars["comment_raw"] = $comment->text; + + echo $ste->exectemplate("/systemtemplates/single_comment.html"); + return; + } + + backend_content_comments_overview: + + /* Perform an action on all selected comments */ + if(!empty($_POST["action_on_comments"])) + { + switch($_POST["action_on_comments"]) + { + case "delete": + $commentaction = function($c) { $c->delete(); }; + $ste->vars["success"] = $translation["comments_successfully_deleted"]; + break; + case "mark_read": + $commentaction = function($c) { $c->read_by_admin = True; $c->save(); }; + $ste->vars["success"] = $translation["comments_successfully_marked_read"]; + break; + case "mark_unread": + $commentaction = function($c) { $c->read_by_admin = False; $c->save(); }; + $ste->vars["success"] = $translation["comments_successfully_marked_unread"]; + break; + case "make_visible": + $commentaction = function($c) { $c->visible = True; $c->save(); }; + $ste->vars["success"] = $translation["comments_successfully_made_visible"]; + break; + case "make_invisible": + $commentaction = function($c) { $c->visible = False; $c->save(); }; + $ste->vars["success"] = $translation["comments_successfully_made_invisible"]; + break; + default; + $ste->vars["error"] = $translation["unknown_action"]; + break; + } + if(isset($commentaction)) + { + foreach($_POST["comment_multiselect"] as $c_id) + { + try + { + $comment = Comment::by_id($c_id); + $commentaction($comment); + } + catch(DoesNotExistError $e) + { + continue; + } + } + } + } + + $comments = Comment::all(); + + /* Filtering */ + $filterquery = array(); + if(!empty($_GET["filter_article"])) + { + $searchfor = strtolower($_GET["filter_article"]); + $comments = array_filter($comments, function($c) use ($searchfor) { return strpos(strtolower($c->get_article()->urlname), $searchfor) !== False; }); + $filterquery[] = "filter_article=" . urlencode($_GET["filter_article"]); + $ste->vars["filter_article"] = $_GET["filter_article"]; + } + $ste->vars["filterquery"] = implode("&", $filterquery); + + /* Sorting */ + if(isset($_GET["sort_asc"])) + { + $sort_dir = 1; + $sort_by = $_GET["sort_asc"]; + } + elseif(isset($_GET["sort_desc"])) + { + $sort_dir = -1; + $sort_by = $_GET["sort_desc"]; + } + else + { + $sort_dir = 1; + $sort_by = "was_read"; + } + + switch($sort_by) + { + case "language": + usort($comments, function($a, $b) use ($sort_dir) { return strcmp($a->get_language(), $b->get_language()) * $sort_dir; }); + break; + case "date": + usort($comments, function($a, $b) use ($sort_dir) { return intcmp($a->get_timestamp(), $b->get_timestamp()) * $sort_dir; }); + break; + case "was_read": + default: + usort($comments, function($a, $b) use ($sort_dir) { return intcmp((int) $a->read_by_admin, (int) $b->read_by_admin) * $sort_dir; }); + $sort_by = "was_read"; + break; + } + $ste->vars["sortquery"] = "sort_" . ($sort_dir == 1 ? "asc" : "desc") . "=$sort_by"; + $ste->vars["sorting"] = array("dir" => ($sort_dir == 1 ? "asc" : "desc"), "by" => $sort_by); + $ste->vars["sort_" . ($sort_dir == 1 ? "asc" : "desc") . "_$sort_by"] = True; + + $ste->vars["comments"] = array_map(function($c) { return array( + "id" => $c->get_id(), + "visible" => $c->visible, + "read_by_admin" => $c->read_by_admin, + "article" => $c->get_article()->urlname, + "excerpt" => substr(str_replace(array("\r\n", "\n", "\r"), " ", $c->text), 0, 50), + "language" => $c->get_language(), + "date" => $c->get_timestamp(), + "author" => "\"{$c->author_name}\" <{$c->author_mail}>" + ); }, $comments); + + echo $ste->exectemplate("/systemtemplates/comments_list.html"); + } + )), + "design" => url_action_subactions(array( + "templates" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + list($template) = $url_next; + + $url_next = array(); + + $ste->vars["section"] = "design"; + $ste->vars["submenu"] = "templates"; + $ste->vars["pagetitle"] = $translation["menu_templates"]; + + if(isset($template)) + { + if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $template) == 0) /* Prevent a possible LFI attack. */ + throw new NotFoundError(); + if(!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$template")) + throw new NotFoundError(); + $ste->vars["template_name"] = $template; + $ste->vars["template_code"] = file_get_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$template"); + } + + /* Was there a delete request? */ + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["templates_multiselect"] as $tplname) + { + if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $tplname) == 0) /* Prevent a possible LFI attack. */ + continue; + if(is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$tplname")) + @unlink(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/$tplname"); + } + $ste->vars["success"] = $translation["templates_successfully_deleted"]; + } + + /* A write request? */ + if(isset($_POST["save_template"])) + { + if(preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["template_name"]) == 1) + { + $ste->vars["template_name"] = $_POST["template_name"]; + $ste->vars["template_code"] = $_POST["template_code"]; + + try + { + \ste\transcompile(\ste\parse(\ste\precompile($_POST["template_code"]), $_POST["template_name"])); + file_put_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/" . $_POST["template_name"], $_POST["template_code"]); + $ste->vars["success"] = $translation["template_successfully_saved"]; + } + catch(\ste\ParseCompileError $e) + { + $e->rewrite($_POST["template_code"]); + $ste->vars["error"] = $translation["could_not_compile_template"] . $e->getMessage(); + } + } + else + $ste->vars["error"] = $translation["invalid_template_name"]; + } + + /* Get all templates */ + $ste->vars["templates"] = array(); + $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates"); + foreach($tpldir as $fo) + { + if($fo->isFile()) + $ste->vars["templates"][] = $fo->getFilename(); + } + sort($ste->vars["templates"]); + + echo $ste->exectemplate("/systemtemplates/templates.html"); + }, + "styles" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + list($style) = $url_next; + + $url_next = array(); + + $ste->vars["section"] = "design"; + $ste->vars["submenu"] = "styles"; + $ste->vars["pagetitle"] = $translation["menu_styles"]; + + if(isset($style)) + { + try + { + $style = Style::by_name($style); + $ste->vars["style_name"] = $style->name; + $ste->vars["style_code"] = $style->code; + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + } + + /* Was there a delete request? */ + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["styles_multiselect"] as $stylename) + { + try + { + $style = Style::by_name($stylename); + $style->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + $ste->vars["success"] = $translation["styles_successfully_deleted"]; + } + + /* A write request? */ + if(isset($_POST["save_style"])) + { + if(Style::test_name($_POST["style_name"])) + { + $ste->vars["style_name"] = $_POST["style_name"]; + $ste->vars["style_code"] = $_POST["style_code"]; + + try + { + $style = Style::by_name($_POST["style_name"]); + } + catch(DoesNotExistError $e) + { + $style = Style::create($_POST["style_name"]); + } + + $style->code = $_POST["style_code"]; + $style->save(); + + $ste->vars["success"] = $translation["style_successfully_saved"]; + } + else + $ste->vars["error"] = $translation["invalid_style_name"]; + } + + /* Get all styles */ + $ste->vars["styles"] = array_map(function($s) { return $s->name; }, Style::all()); + sort($ste->vars["styles"]); + + echo $ste->exectemplate("/systemtemplates/styles.html"); + }, + "sections" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings; + + list($style) = $url_next; + + $url_next = array(); + + $ste->vars["section"] = "design"; + $ste->vars["submenu"] = "sections"; + $ste->vars["pagetitle"] = $translation["menu_pagesections"]; + + /* New section? */ + if(isset($_POST["new_section"])) + { + try + { + Section::by_name($_POST["section_name"]); + $ste->vars["error"] = $translation["section_already_exists"]; + } + catch(DoesNotExistError $e) + { + if((preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["template"]) == 0) or (!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['template']}"))) + $ste->vars["error"] = $translation["unknown_template"]; + else if(!Section::test_name($_POST["section_name"])) + $ste->vars["error"] = $translation["invalid_section_name"]; + else + { + $section = Section::create($_POST["section_name"]); + $section->template = $_POST["template"]; + $section->title[$data["user"]->language] = new Translation($_POST["section_name"], ""); + $section->save(); + $ste->vars["success"] = $translation["section_created_successfully"]; + } + } + } + + /* Remove a style? */ + if(isset($_GET["rmstyle"]) and isset($_GET["rmfrom"])) + { + try + { + $section = Section::by_name($_GET["rmfrom"]); + $style = Style::by_name($_GET["rmstyle"]); + $section->remove_style($style); + $section->save(); + $ste->vars["success"] = $translation["style_removed"]; + } + catch(DoesNotExistError $e) + { + } + } + + /* Delete a section? */ + if(isset($_POST["delete"]) and (@$_POST["really_delete"] == "yes") and isset($_POST["section_select"])) + { + try + { + $section = Section::by_name($_POST["section_select"]); + if($section->get_id() == $ratatoeskr_settings["default_section"]) + $ste->vars["error"] = $translation["cannot_delete_default_section"]; + else + { + $default_section = Section::by_id($ratatoeskr_settings["default_section"]); + foreach($section->get_articles() as $article) + { + $article->set_section($default_section); + $article->save(); + } + $section->delete(); + $ste->vars["success"] = $translation["section_successfully_deleted"]; + } + } + catch(DoesNotExistError $e) + { + } + } + + /* Make section default? */ + if(isset($_POST["make_default"]) and isset($_POST["section_select"])) + { + try + { + $section = Section::by_name($_POST["section_select"]); + $ratatoeskr_settings["default_section"] = $section->get_id(); + $ste->vars["success"] = $translation["default_section_changed_successfully"]; + } + catch(DoesNotExistError $e) + { + } + } + + /* Set template? */ + if(isset($_POST["set_template"]) and isset($_POST["section_select"])) + { + try + { + $section = Section::by_name($_POST["section_select"]); + if((preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $_POST["set_template_to"]) == 0) or (!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['set_template_to']}"))) + $ste->vars["error"] = $translation["unknown_template"]; + else + { + $section->template = $_POST["set_template_to"]; + $section->save(); + $ste->vars["success"] = $translation["successfully_set_template"]; + } + } + catch(DoesNotExistError $e) + { + } + } + + /* Adding a style? */ + if(isset($_POST["add_style"]) and isset($_POST["section_select"])) + { + try + { + $section = Section::by_name($_POST["section_select"]); + $style = Style::by_name($_POST["style_to_add"]); + $section->add_style($style); + $ste->vars["success"] = $translation["successfully_added_style"]; + } + catch(DoesNotExistError $e) + { + } + } + + /* Set/unset title? */ + if(isset($_POST["set_title"]) and isset($_POST["section_select"])) + { + if(!isset($languages[$_POST["set_title_lang"]])) + $ste->vars["error"] = $translation["language_unknown"]; + else + { + try + { + $section = Section::by_name($_POST["section_select"]); + if(!empty($_POST["set_title_text"])) + $section->title[$_POST["set_title_lang"]] = new Translation($_POST["set_title_text"], ""); + else if(isset($section->title[$_POST["set_title_lang"]])) + unset($section->title[$_POST["set_title_lang"]]); + $section->save(); + $ste->vars["success"] = $translation["successfully_set_section_title"]; + } + catch(DoesNotExistError $e) + { + } + } + } + + /* Get all templates */ + $ste->vars["templates"] = array(); + $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates"); + foreach($tpldir as $fo) + { + if($fo->isFile()) + $ste->vars["templates"][] = $fo->getFilename(); + } + sort($ste->vars["templates"]); + + /* Get all styles */ + $ste->vars["styles"] = array_map(function($s) { return $s->name; }, Style::all()); + sort($ste->vars["styles"]); + + /* Get all sections */ + $sections = Section::all(); + $ste->vars["sections"] = array_map(function($section) use ($ratatoeskr_settings) { + $titles = array(); + foreach($section->title as $l => $t) + $titles[$l] = $t->text; + return array( + "name" => $section->name, + "title" => $titles, + "template" => $section->template, + "styles" => array_map(function($style) { return $style->name; }, $section->get_styles()), + "default" => ($section->get_id() == $ratatoeskr_settings["default_section"]) + ); + }, $sections); + + echo $ste->exectemplate("/systemtemplates/sections.html"); + } + )), + "admin" => url_action_subactions(array( + "settings" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors; + + $url_next = array(); + + $ste->vars["section"] = "admin"; + $ste->vars["submenu"] = "settings"; + $ste->vars["pagetitle"] = $translation["menu_settings"]; + + $ste->vars["textprocessors"] = array(); + foreach($textprocessors as $txtproc => $properties) + if($properties[1]) + $ste->vars["textprocessors"][] = $txtproc; + + /* Toggle debugmode value? */ + if(isset($_POST["toggle_debugmode"])) + { + if(isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]) + { + $ratatoeskr_settings["debugmode"] = False; + $ste->vars["success"] = $translation["debugmode_now_disabled"]; + } + else + { + $ratatoeskr_settings["debugmode"] = True; + $ste->vars["success"] = $translation["debugmode_now_enabled"]; + } + } + + /* Save comment settings? */ + if(isset($_POST["save_comment_settings"])) + { + if(!in_array(@$_POST["comment_textprocessor"], $ste->vars["textprocessors"])) + $ste->vars["error"] = $translation["unknown_txtproc"]; + else + { + $ratatoeskr_settings["comment_textprocessor"] = $_POST["comment_textprocessor"]; + $ratatoeskr_settings["comment_visible_default"] = (isset($_POST["comment_auto_visible"]) and ($_POST["comment_auto_visible"] == "yes")); + $ste->vars["success"] = $translation["comment_settings_successfully_saved"]; + } + } + + /* Delete language? */ + if(isset($_POST["delete"]) and ($_POST["really_delete"] == "yes") and isset($_POST["language_select"])) + { + if($ratatoeskr_settings["default_language"] == $_POST["language_select"]) + $ste->vars["error"] = $translation["cannot_delete_default_language"]; + else + { + $ratatoeskr_settings["languages"] = array_filter($ratatoeskr_settings["languages"], function($l) { return $l != $_POST["language_select"]; }); + $ste->vars["success"] = $translation["language_successfully_deleted"]; + } + } + + /* Set default language */ + if(isset($_POST["make_default"]) and isset($_POST["language_select"])) + { + if(in_array($_POST["language_select"], $ratatoeskr_settings["languages"])) + { + $ratatoeskr_settings["default_language"] = $_POST["language_select"]; + $ste->vars["success"] = $translation["successfully_set_default_language"]; + } + } + + /* Add a language */ + if(isset($_POST["add_language"])) + { + if(!isset($languages[$_POST["language_to_add"]])) + $ste->vars["error"] = $translation["language_unknown"]; + else + { + if(!in_array($_POST["language_to_add"], $ratatoeskr_settings["languages"])) + { + $ls = $ratatoeskr_settings["languages"]; + $ls[] = $_POST["language_to_add"]; + $ratatoeskr_settings["languages"] = $ls; + } + $ste->vars["success"] = $translation["language_successfully_added"]; + } + } + + $ste->vars["debugmode_enabled"] = (isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]); + $ste->vars["comment_auto_visible"] = $ratatoeskr_settings["comment_visible_default"]; + $ste->vars["comment_textprocessor"] = $ratatoeskr_settings["comment_textprocessor"]; + $ste->vars["used_langs"] = array_map(function ($l) use ($ratatoeskr_settings, $languages) { return array( + "code" => $l, + "name" => $languages[$l]["language"], + "default" => ($l == $ratatoeskr_settings["default_language"]) + );}, $ratatoeskr_settings["languages"]); + + echo $ste->exectemplate("/systemtemplates/settings.html"); + }, + "users" => url_action_subactions(array( + "_index" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors; + + $url_next = array(); + + $ste->vars["section"] = "admin"; + $ste->vars["submenu"] = "users"; + $ste->vars["pagetitle"] = $translation["menu_users_groups"]; + + /* Add a new group? */ + if(isset($_POST["new_group"])) + { + if(empty($_POST["group_name"])) + $ste->vars["error"] = $translation["empty_group_name"]; + else + { + try + { + Group::by_name($_POST["group_name"]); + $ste->vars["error"] = $translation["group_already_exists"]; + } + catch(DoesNotExistError $e) + { + $group = Group::create($_POST["group_name"]); + $ste->vars["success"] = $translation["successfully_created_group"]; + } + } + } + + /* Add a new user? */ + if(isset($_POST["new_user"])) + { + if(empty($_POST["username"])) + $ste->vars["error"] = $translation["empty_username"]; + else + { + try + { + User::by_name($_POST["username"]); + $ste->vars["error"] = $translation["user_already_exists"]; + } + catch(DoesNotExistError $e) + { + $group = User::create($_POST["username"], PasswordHash::create($_POST["initial_password"])); + $ste->vars["success"] = $translation["successfully_created_user"]; + } + } + } + + /* Delete groups? */ + if(isset($_POST["delete_groups"]) and ($_POST["really_delete"] == "yes") and (!empty($_POST["groups_multiselect"]))) + { + $deleted = 0; + foreach($_POST["groups_multiselect"] as $gid) + { + try + { + $group = Group::by_id($gid); + if($group->name == "admins") + { + $ste->vars["error"] = $translation["cannot_delete_admin_group"]; + } + else + { + $group->delete(); + ++$deleted; + } + } + catch(DoesNotExistError $e) + { + continue; + } + } + if($deleted > 0) + $ste->vars["success"] = $translation["successfully_deleted_groups"]; + } + + /* Delete users? */ + if(isset($_POST["delete_users"]) and ($_POST["really_delete"] == "yes") and (!empty($_POST["users_multiselect"]))) + { + $deleted = 0; + foreach($_POST["users_multiselect"] as $uid) + { + if($uid == $data["user"]->get_id()) + $ste->vars["error"] = $translation["cannot_delete_yourself"]; + else + { + try + { + $user = User::by_id($uid); + $user->delete(); + ++$deleted; + } + catch(DoesNotExistError $e) + { + continue; + } + } + } + if($deleted > 0) + $ste->vars["success"] = $translation["successfully_deleted_users"]; + } + + /* Get all groups */ + $ste->vars["groups"] = array_map(function($g) { return array( + "id" => $g->get_id(), + "name" => $g->name + ); }, Group::all()); + + /* Get all users */ + $ste->vars["users"] = array_map(function($u) { return array( + "id" => $u->get_id(), + "name" => $u->username, + "memberof" => array_map(function($g) { return $g->name; }, $u->get_groups()), + "fullname" => $u->fullname, + "mail" => $u->mail + ); }, User::all()); + + echo $ste->exectemplate("/systemtemplates/users.html"); + }, + "u" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $admin_grp; + + try + { + $user = User::by_id($url_next[0]); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + $url_next = array(); + + $ste->vars["section"] = "admin"; + $ste->vars["submenu"] = "users"; + $ste->vars["pagetitle"] = $user->username; + + /* Modify data? */ + if(isset($_POST["change_data"])) + { + $user->fullname = $_POST["fullname"]; + $user->mail = $_POST["mail"]; + $user->language = $_POST["lang"]; + + $current_groups = array_map(function($g) { return $g->get_id(); }, $user->get_groups()); + $new_groups = empty($_POST[groups_multiselect]) ? array() : $_POST["groups_multiselect"]; + $groups_exclude = array_diff($current_groups, $new_groups); + $groups_include = array_diff($new_groups, $current_groups); + + foreach($groups_exclude as $gid) + { + try + { + $g = Group::by_id($gid); + $g->exclude_user($user); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + foreach($groups_include as $gid) + { + try + { + $g = Group::by_id($gid); + $g->include_user($user); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $user->save(); + + $ste->vars["success"] = $translation["successfully_modified_user"]; + } + + /* New Password? */ + if(isset($_POST["new_password"])) + { + $pwhash = PasswordHash::create($_POST["password"]); + $user->pwhash = $pwhash; + if($user->get_id() == $data["user"]->get_id()) + $_SESSION["ratatoeskr_pwhash"] = $pwhash; + $user->save(); + + $ste->vars["success"] = $translation["successfully_set_new_password"]; + } + + /* Put data to STE */ + $ste->vars["u"] = array( + "id" => $user->get_id(), + "name" => $user->username, + "fullname" => $user->fullname, + "mail" => $user->mail, + "lang" => $user->language + ); + $ste->vars["groups"] = array_map(function($g) use ($user) { return array( + "id" => $g->get_id(), + "name" => $g->name, + "member" => $user->member_of($g) + ); }, Group::all()); + + echo $ste->exectemplate("/systemtemplates/user.html"); + } + )), + "repos" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + $url_next = array(); + + $ste->vars["section"] = "admin"; + $ste->vars["submenu"] = "repos"; + $ste->vars["pagetitle"] = $translation["menu_plugin_repos"]; + + /* Add a repo? */ + if(isset($_POST["add_repo"])) + { + try + { + $repo = Repository::create($_POST["repo_baseurl"]); + $ste->vars["success"] = $translation["successfully_added_repo"]; + } + catch(RepositoryUnreachableOrInvalid $e) + { + $ste->vars["error"] = $translation["repository_unreachable_or_invalid"]; + } + } + + /* Delete repos? */ + if(isset($_POST["delete_repos"]) and ($_POST["really_delete"] == "yes")) + { + foreach($_POST["repos_multiselect"] as $repo_id) + { + try + { + $repo = Repository::by_id($repo_id); + $repo->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + $ste->vars["success"] = $translation["repos_deleted"]; + } + + /* Force refresh? */ + if(isset($_POST["force_repo_refresh"])) + { + $failed = array(); + foreach($_POST["repos_multiselect"] as $repo_id) + { + try + { + $repo = Repository::by_id($repo_id); + $repo->refresh(True); + } + catch(DoesNotExistError $e) + { + continue; + } + catch(RepositoryUnreachableOrInvalid $e) + { + $failed[] = $repo->get_name(); + } + } + $ste->vars["success"] = $translation["successfully_refreshed_repos"]; + if(!empty($failed)) + $ste->vars["error"] = str_replace("[[REPOS]]", implode(", ", $failed), $translation["repo_refresh_failed_on"]); + } + + /* Fill data */ + $all_repos = Repository::all(); + $ste->vars["repos"] = array_map( + function($r) + { + try + { + $r->refresh(); + } + catch(RepositoryUnreachableOrInvalid $e){} + return array( + "id" => $r->get_id(), + "name" => $r->get_name(), + "description" => $r->get_description(), + "baseurl" => $r->get_baseurl() + ); + }, $all_repos); + + echo $ste->exectemplate("/systemtemplates/repos.html"); + } + )), + "plugin" => url_action_subactions(array( + "list" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $plugin_objs, $api_compat; + + $url_next = array(); + + $ste->vars["section"] = "plugins"; + $ste->vars["submenu"] = "pluginlist"; + $ste->vars["pagetitle"] = $translation["menu_pluginlist"]; + + /* Delete plugins? */ + if(isset($_POST["delete"]) and (($_POST["really_delete"] == "yes") or ($_POST["really_delete"] == "force")) and (!empty($_POST["plugins_multiselect"]))) + { + foreach($_POST["plugins_multiselect"] as $pid) + { + try + { + $plugin = Plugin::by_id($pid); + if($_POST["really_delete"] != "force") + { + if(!isset($plugin_objs[$pid])) + { + eval($plugin->code); + $plugin_objs[$pid] = new $plugin->classname($pid); + } + $plugin_objs[$pid]->uninstall(); + } + $plugin->delete(); + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $ste->vars["success"] = $translation["successfully_deleted_plugins"]; + } + + /* Activate or deactivate plugins? */ + if((isset($_POST["activate"]) or isset($_POST["deactivate"])) and (!empty($_POST["plugins_multiselect"]))) + { + $api_incompat = array(); + $newstatus = isset($_POST["activate"]); + foreach($_POST["plugins_multiselect"] as $pid) + { + try + { + $plugin = Plugin::by_id($pid); + if(!$plugin->installed) + continue; + if($newstatus and (!in_array($plugin->api, $api_compat))) + { + $api_incompat[] = $plugin->name . ("(ID: " . $plugin->get_id() . ")"); + continue; + } + $plugin->active = $newstatus; + $plugin->save(); + if($newstatus and (!isset($plugin_objs[$pid]))) + { + eval($plugin->code); + $plugin_objs[$pid] = new $plugin->classname($pid); + $plugin_objs[$pid]->init(); + } + } + catch(DoesNotExistError $e) + { + continue; + } + } + + $ste->vars["success"] = $translation[$newstatus ? "plugins_activated" : "plugins_deactivated"]; + + if(!empty($api_incompat)) + $ste->vars["error"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["could_not_activate_plugin_api_incompat"])); + } + + $stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); + + /* Update plugins? */ + if(isset($_POST["update"]) and (!empty($_POST["plugins_multiselect"]))) + { + $updated = array(); + foreach($_POST["plugins_multiselect"] as $pid) + { + try + { + $plugin = Plugin::by_id($pid); + if(!empty($plugin->updatepath)) + { + $update_info = @unserialize(@file_get_contents($plugin->updatepath, False, $stream_ctx)); + if(is_array($update_info) and (($update_info["current-version"]+0) > ($plugin->versioncount+0))) + { + $pkg = PluginPackage::load(@file_get_contents($update_info["dl-path"], False, $stream_ctx)); + $plugin->fill_from_pluginpackage($pkg); + $plugin->update = True; + $plugin->save(); + $updated[] = $plugin->name; + } + } + } + catch(DoesNotExistError $e) + { + continue; + } + catch(InvalidPackage $e) + { + continue; + } + } + + if(empty($updated)) + $ste->vars["success"] = $translation["nothing_to_update"]; + else + $ste->vars["success"] = str_replace("[[PLUGINS]]", implode(", ", $updated), $translation["successfully_updated_plugins"]); + } + + /* Load plugin data */ + $all_plugins = Plugin::all(); + $ste->vars["plugins"] = array(); + $api_incompat = array(); + foreach($all_plugins as $p) + { + if(!$p->installed) + continue; + + if(!in_array($p->api, $api_compat)) + $api_incompat[] = $p->name . ("(ID: " . $p->get_id() . ")"); + + $ste->vars["plugins"][] = array( + "id" => $p->get_id(), + "name" => $p->name, + "versiontext" => $p->versiontext, + "active" => $p->active, + "description" => $p->short_description, + "web" => $p->web, + "author" => $p->author, + "help" => !empty($p->help) + ); + } + + if(!empty($api_incompat)) + $ste->vars["notice"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["plugins_incompat"])); + + echo $ste->exectemplate("/systemtemplates/pluginlist.html"); + }, + "help" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + try + { + $plugin = Plugin::by_id($url_next[0]); + if(empty($plugin->help)) + throw new NotFoundError(); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + $url_next = array(); + + $ste->vars["section"] = "plugins"; + $ste->vars["submenu"] = ""; + $ste->vars["pagetitle"] = $plugin->name; + $ste->vars["help"] = $plugin->help; + + echo $ste->exectemplate("/systemtemplates/pluginhelp.html"); + }, + "install" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root, $api_compat; + + $url_next = array(); + + $ste->vars["section"] = "plugins"; + $ste->vars["submenu"] = "installplugins"; + $ste->vars["pagetitle"] = $translation["menu_plugininstall"]; + + $all_repos = Repository::all(); + foreach($all_repos as $repo) + { + try + { + $repo->refresh(); + } + catch(RepositoryUnreachableOrInvalid $e) + { + continue; + } + } + + if(isset($_POST["installpackage"])) + { + if(is_uploaded_file($_FILES["pluginpackage"]["tmp_name"])) + { + try + { + $package = PluginPackage::load(file_get_contents($_FILES["pluginpackage"]["tmp_name"])); + unlink($_FILES["pluginpackage"]["tmp_name"]); + if(in_array($package->api, $api_compat)) + { + $plugin = Plugin::create(); + $plugin->fill_from_pluginpackage($package); + $plugin->installed = False; + $plugin->active = False; + $plugin->save(); + $url_next = array("confirminstall", (string) $plugin->get_id()); + return; + } + else + $ste->vars["error"] = str_replace("[[API]]", $package->api, $translation["incompatible_plugin"]); + } + catch(InvalidPackage $e) + { + $ste->vars["error"] = $translation["invalid_package"]; + unlink($_FILES["pluginpackage"]["tmp_name"]); + } + } + else + $ste->vars["error"] = $translation["upload_failed"]; + } + + if(isset($_POST["search_in_repos"])) + { + $ste->vars["searchresults"] = array(); + $repos_to_scan = ($_POST["searchin"] == "*") ? $all_repos : Repository::by_id($_POST["searchin"]); + $searchfor = strtolower($_POST["searchfor"]); + foreach($repos_to_scan as $repo) + { + foreach($repo->packages as $pkg) + { + if(empty($searchfor) or (strpos(strtolower($pkg[0]), $searchfor) !== False) or (strpos(strtolower($pkg[2]), $searchfor) !== False)) + $ste->vars["searchresults"][] = array( + "name" => $pkg[0], + "description" => $pkg[2], + "reponame" => $repo->get_name(), + "repoid" => $repo->get_id() + ); + } + } + } + + $ste->vars["repos"] = array_map(function($r) { return array( + "id" => $r->get_id(), + "name" => $r->get_name() + ); }, $all_repos); + + echo $ste->exectemplate("/systemtemplates/plugininstall.html"); + }, + "repoinstall" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $rel_path_to_root; + + $stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); + + try + { + $repo = Repository::by_id($_GET["repo"]); + $pkg = $repo->download_package($_GET["pkg"]); + $plugin = Plugin::create(); + $plugin->fill_from_pluginpackage($pkg); + $plugin->installed = False; + $plugin->active = False; + $plugin->save(); + $url_next = array("confirminstall", (string) $plugin->get_id()); + } + catch(DoesNotExistError $e) + { + $ste->vars["error"] = $translation["package_or_repo_not_found"]; + $url_next = array("install"); + } + catch(InvalidPackage $e) + { + $ste->vars["error"] = $translation["invalid_package"]; + $url_next = array("install"); + } + }, + "confirminstall" => function(&$data, $url_now, &$url_next) + { + global $ste, $translation, $languages, $rel_path_to_root; + + list($plugin_id) = $url_next; + $url_next = array(); + + $ste->vars["section"] = "plugins"; + $ste->vars["submenu"] = "installplugins"; + $ste->vars["pagetitle"] = $translation["menu_plugininstall"]; + + try + { + $plugin = Plugin::by_id($plugin_id); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + + if($plugin->installed) + throw new NotFoundError(); + + $ste->vars["plugin_id"] = $plugin->get_id(); + $ste->vars["name"] = $plugin->name; + $ste->vars["description"] = $plugin->short_description; + $ste->vars["code"] = $plugin->code; + $ste->vars["license"] = $plugin->license; + + if(isset($_POST["yes"])) + { + $plugin->installed = True; + $plugin->save(); + eval($plugin->code); + $plugin_instance = new $plugin->classname($plugin->get_id()); + $plugin_instance->install(); + $ste->vars["success"] = $translation["plugin_installed_successfully"]; + $url_next = array("list"); + return; + } + + if(isset($_POST["no"])) + { + $plugin->delete(); + $url_next = array("install"); + return; + } + + echo $ste->exectemplate("/systemtemplates/confirminstall.html"); + } + )), + "pluginpages" => url_action_subactions($pluginpages_handlers) )); } diff --git a/ratatoeskr/frontend.php b/ratatoeskr/frontend.php index 9c43ec5..71e940e 100644 --- a/ratatoeskr/frontend.php +++ b/ratatoeskr/frontend.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/frontend.php * All the stuff for the frontend (i.e. what the visitor of the website sees). - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -18,137 +18,137 @@ require_once(dirname(__FILE__) . "/libs/kses.php"); /* * Function: section_transform_ste * Transforms an <Section> object to an array, so it can be accessed via a STE template. - * + * * Parameters: - * $section - <Section> object. - * $lang - The current language. - * + * $section - <Section> object. + * $lang - The current language. + * * Returns: - * Array with these fields: - * * id - The ID of the section. - * * name - The name of the section. - * * title - The title of the section in the current language - * * __obj - The <Section> object. Useful for plugins, so they do not need to fetch the object from the database again. + * Array with these fields: + * * id - The ID of the section. + * * name - The name of the section. + * * title - The title of the section in the current language + * * __obj - The <Section> object. Useful for plugins, so they do not need to fetch the object from the database again. */ function section_transform_ste($section, $lang) { - return array( - "id" => $section->get_id(), - "name" => $section->name, - "title" => $section->title[$lang]->text, - "__obj" => $section - ); + return array( + "id" => $section->get_id(), + "name" => $section->name, + "title" => $section->title[$lang]->text, + "__obj" => $section + ); } /* * Function: tag_transform_ste * Transforms an <Tag> object to an array, so it can be accessed via a STE template. - * + * * Parameters: - * $section - <Tag> object. - * $lang - The current language. - * + * $section - <Tag> object. + * $lang - The current language. + * * Returns: - * Array with these fields: - * * id - The ID of the tag. - * * name - The name of the tag. - * * title - The title in the current language. - * * __obj - The <Tag> object. Useful for plugins, so they do not need to fetch the object from the database again. + * Array with these fields: + * * id - The ID of the tag. + * * name - The name of the tag. + * * title - The title in the current language. + * * __obj - The <Tag> object. Useful for plugins, so they do not need to fetch the object from the database again. */ function tag_transform_ste($tag, $lang) { - try - { - return array( - "id" => $tag->get_id(), - "name" => $tag->name, - "title" => $tag->title[$lang]->text, - "__obj" => $tag - ); - } - catch(DoesNotExistError $e) - { - return False; - } + try + { + return array( + "id" => $tag->get_id(), + "name" => $tag->name, + "title" => $tag->title[$lang]->text, + "__obj" => $tag + ); + } + catch(DoesNotExistError $e) + { + return False; + } } /* * Function: article_transform_ste * Transforms an <Article> object to an array, so it can be accessed via a STE template. - * + * * Parameters: - * $article - <Article> object. - * $lang - The current language. - * + * $article - <Article> object. + * $lang - The current language. + * * Returns: - * Array with these fields: - * * id - * * urlname - * * fullurl - * * title - * * text - * * excerpt - * * custom (array: name=>value) - * * status (numeric) - * * section (sub-fields: <section_transform_ste>) - * * timestamp - * * tags (array(sub-fields: <tag_transform_ste>)) - * * languages (array: language name=>url) - * * comments_allowed - * * __obj - Useful for plugins, so they do not need to fetch the object from the database again. + * Array with these fields: + * * id + * * urlname + * * fullurl + * * title + * * text + * * excerpt + * * custom (array: name=>value) + * * status (numeric) + * * section (sub-fields: <section_transform_ste>) + * * timestamp + * * tags (array(sub-fields: <tag_transform_ste>)) + * * languages (array: language name=>url) + * * comments_allowed + * * __obj - Useful for plugins, so they do not need to fetch the object from the database again. */ function article_transform_ste($article, $lang) { - global $rel_path_to_root; - - $languages = array(); - $a_section = $article->get_section(); - foreach($article->title as $language => $_) - $languages[$language] = "$rel_path_to_root/$language/{$a_section->name}/{$article->urlname}"; - - return array( - "id" => $article->get_id(), - "urlname" => $article->urlname, - "fullurl" => htmlesc("$rel_path_to_root/$lang/{$a_section->name}/{$article->urlname}"), - "title" => htmlesc($article->title[$lang]->text), - "text" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->text[$lang]->text), $article->text[$lang]->texttype), - "excerpt" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->excerpt[$lang]->text), $article->excerpt[$lang]->texttype), - "custom" => $article->custom, - "status" => $article->status, - "section" => section_transform_ste($a_section, $lang), - "timestamp" => $article->timestamp, - "tags" => array_filter(array_map(function($tag) use ($lang) { return tag_transform_ste($tag, $lang); }, $article->get_tags())), - "languages" => $languages, - "comments_allowed" => $article->allow_comments, - "__obj" => $article - ); + global $rel_path_to_root; + + $languages = array(); + $a_section = $article->get_section(); + foreach($article->title as $language => $_) + $languages[$language] = "$rel_path_to_root/$language/{$a_section->name}/{$article->urlname}"; + + return array( + "id" => $article->get_id(), + "urlname" => $article->urlname, + "fullurl" => htmlesc("$rel_path_to_root/$lang/{$a_section->name}/{$article->urlname}"), + "title" => htmlesc($article->title[$lang]->text), + "text" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->text[$lang]->text), $article->text[$lang]->texttype), + "excerpt" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->excerpt[$lang]->text), $article->excerpt[$lang]->texttype), + "custom" => $article->custom, + "status" => $article->status, + "section" => section_transform_ste($a_section, $lang), + "timestamp" => $article->timestamp, + "tags" => array_filter(array_map(function($tag) use ($lang) { return tag_transform_ste($tag, $lang); }, $article->get_tags())), + "languages" => $languages, + "comments_allowed" => $article->allow_comments, + "__obj" => $article + ); } /* * Function: comment_transform_ste * Transforms an <Comment> object to an array, so it can be accessed via a STE template. - * + * * Parameters: - * $comment - <Comment> object. - * + * $comment - <Comment> object. + * * Returns: - * Array with these fields: - * * id - * * text - * * author - * * timestamp + * Array with these fields: + * * id + * * text + * * author + * * timestamp */ function comment_transform_ste($comment) { - global $rel_path_to_root, $ratatoeskr_settings; - - return array( - "id" => $comment->get_id(), - "text" => $comment->create_html(), - "author" => htmlesc($comment->author_name), - "timestamp" => $comment->get_timestamp(), - "__obj" => $comment - ); + global $rel_path_to_root, $ratatoeskr_settings; + + return array( + "id" => $comment->get_id(), + "text" => $comment->create_html(), + "author" => htmlesc($comment->author_name), + "timestamp" => $comment->get_timestamp(), + "__obj" => $comment + ); } /* Register some tags for the template engine */ @@ -156,522 +156,522 @@ function comment_transform_ste($comment) * STETag: articles_get * Get articles by custom criterias. Will only get articles, that are available in the current language ($language). * The fields of an article can be looked up at <article_transform_ste>. - * + * * Parameters: - * var - (mandatory) The name of the variable, where the current article should be stored at. - * id - (optional) Filter by ID. - * urlname - (optional) Filter by urlname. - * section - (optional) Filter by section (section name). - * sectionvar - (optional) Filter by section (Name of variable that contains a section). - * status - (optional) Filter by status (numeric, <ARTICLE_STATUS_>). - * tag - (optional) Filter by tag (tag name). - * tagvar - (optional) Filter by tag (Name of variable that contains a tag). - * 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. - * skip - (optional) How many articles should be skipped? (Default: none) - * count - (optional) How many articles to output. (Default unlimited) + * var - (mandatory) The name of the variable, where the current article should be stored at. + * id - (optional) Filter by ID. + * urlname - (optional) Filter by urlname. + * section - (optional) Filter by section (section name). + * sectionvar - (optional) Filter by section (Name of variable that contains a section). + * status - (optional) Filter by status (numeric, <ARTICLE_STATUS_>). + * tag - (optional) Filter by tag (tag name). + * tagvar - (optional) Filter by tag (Name of variable that contains a tag). + * 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. + * skip - (optional) How many articles should be skipped? (Default: none) + * count - (optional) How many articles to output. (Default unlimited) * * Tag Content: - * The tag's content will be executed for every article. The current article will be written to the variable specified by the var parameter before. + * The tag's content will be executed for every article. The current article will be written to the variable specified by the var parameter before. * * Returns: - * All results from the tag content. + * All results from the tag content. */ $ste->register_tag("articles_get", function($ste, $params, $sub) { - $lang = $ste->vars["language"]; - - if(!isset($params["var"])) - throw new \ste\RuntimeError("Parameter var is needed in article_get!"); - - $criterias = array("langavail" => $lang, "onlyvisible" => True); - if(isset($params["id"])) - $criterias["id"] = $params["id"]; - if(isset($params["urlname"])) - $criterias["urlname"]; - if(isset($params["status"])) - $criterias["status"] = $params["status"]; - if(isset($params["sectionvar"])) - { - $sectionvar = $ste->get_var_by_name($params["sectionvar"]); - $criterias["section"] = $sectionvar["__obj"]; - } - else if(isset($params["section"])) - { - try - { - $criterias["section"] = Section::by_name($params["section"]); - } - catch(DoesNotExistError $e) {} - } - if(isset($params["tagvar"])) - { - $tagvar = $ste->get_var_by_name($params["tagvar"]); - $criterias["tag"] = $tagvar["__obj"]; - } - if(isset($params["tag"])) - { - try - { - $criterias["tag"] = Tag::by_name($params["tag"]); - } - catch(DoesNotExistError $e) {} - } - - $field = NULL; - $direction = NULL; - if(isset($params["sort"])) - { - list($field, $direction) = explode(" ", $params["sort"]); - if($direction === NULL) - $field = NULL; - $direction = strtoupper($direction); - } - - $result = Article::by_multi($criterias, $field, $direction, @$params["count"], @$params["skip"], @$params["perpage"], @$params["page"], $maxpage); - - $result = array_map(function($article) use ($lang) { return article_transform_ste($article, $lang); }, $result); - - if(isset($params["perpage"]) and isset($params["maxpage"])) - $ste->set_var_by_name($params["maxpage"], $maxpage == 0 ? 1 : $maxpage); - - $output = ""; - foreach($result as $article) - { - $ste->set_var_by_name($params["var"], $article); - $output .= $sub($ste); - } - return $output; + $lang = $ste->vars["language"]; + + if(!isset($params["var"])) + throw new \ste\RuntimeError("Parameter var is needed in article_get!"); + + $criterias = array("langavail" => $lang, "onlyvisible" => True); + if(isset($params["id"])) + $criterias["id"] = $params["id"]; + if(isset($params["urlname"])) + $criterias["urlname"]; + if(isset($params["status"])) + $criterias["status"] = $params["status"]; + if(isset($params["sectionvar"])) + { + $sectionvar = $ste->get_var_by_name($params["sectionvar"]); + $criterias["section"] = $sectionvar["__obj"]; + } + else if(isset($params["section"])) + { + try + { + $criterias["section"] = Section::by_name($params["section"]); + } + catch(DoesNotExistError $e) {} + } + if(isset($params["tagvar"])) + { + $tagvar = $ste->get_var_by_name($params["tagvar"]); + $criterias["tag"] = $tagvar["__obj"]; + } + if(isset($params["tag"])) + { + try + { + $criterias["tag"] = Tag::by_name($params["tag"]); + } + catch(DoesNotExistError $e) {} + } + + $field = NULL; + $direction = NULL; + if(isset($params["sort"])) + { + list($field, $direction) = explode(" ", $params["sort"]); + if($direction === NULL) + $field = NULL; + $direction = strtoupper($direction); + } + + $result = Article::by_multi($criterias, $field, $direction, @$params["count"], @$params["skip"], @$params["perpage"], @$params["page"], $maxpage); + + $result = array_map(function($article) use ($lang) { return article_transform_ste($article, $lang); }, $result); + + if(isset($params["perpage"]) and isset($params["maxpage"])) + $ste->set_var_by_name($params["maxpage"], $maxpage == 0 ? 1 : $maxpage); + + $output = ""; + foreach($result as $article) + { + $ste->set_var_by_name($params["var"], $article); + $output .= $sub($ste); + } + return $output; }); /* * STETag: section_list * Iterate over all sections. * The fields of a section can be looked up at <section_transform_ste>. - * + * * Parameters: - * var - (mandatory) The name of the variable, where the current section should be stored at. - * exclude - (optional) Sections to exclude - * include_default - (optional) Should the default section be included (default: No). - * + * var - (mandatory) The name of the variable, where the current section should be stored at. + * exclude - (optional) Sections to exclude + * include_default - (optional) Should the default section be included (default: No). + * * Tag Content: - * The tag's content will be executed for every section. The current section will be written to the variable specified by the var parameter before. + * The tag's content will be executed for every section. The current section will be written to the variable specified by the var parameter before. * * Returns: - * All results from the tag content. + * All results from the tag content. */ $ste->register_tag("section_list", function($ste, $params, $sub) { - global $ratatoeskr_settings; - $lang = $ste->vars["language"]; - - $default_section = $ratatoeskr_settings["default_section"]; - - if(!isset($params["var"])) - throw new \ste\RuntimeException("Parameter var is needed in article_get!"); - - $result = Section::all(); - - if(isset($params["exclude"])) - { - $exclude = explode(",", $params["exclude"]); - $result = array_filter($result, function($section) use ($exclude) { return !in_array($section->name, $exclude); }); - } - - $result = array_filter($result, function($section) use ($default_section) { return $section->get_id() != $default_section; }); - - $result = array_map(function($section) use ($lang) { return section_transform_ste($section, $lang); }, $result); - - if($ste->evalbool($params["include_default"])) - { - $default = section_transform_ste(Section::by_id($default_section), $lang); - array_unshift($result, $default); - } - - $output = ""; - foreach($result as $section) - { - $ste->set_var_by_name($params["var"], $section); - $output .= $sub($ste); - } - return $output; + global $ratatoeskr_settings; + $lang = $ste->vars["language"]; + + $default_section = $ratatoeskr_settings["default_section"]; + + if(!isset($params["var"])) + throw new \ste\RuntimeException("Parameter var is needed in article_get!"); + + $result = Section::all(); + + if(isset($params["exclude"])) + { + $exclude = explode(",", $params["exclude"]); + $result = array_filter($result, function($section) use ($exclude) { return !in_array($section->name, $exclude); }); + } + + $result = array_filter($result, function($section) use ($default_section) { return $section->get_id() != $default_section; }); + + $result = array_map(function($section) use ($lang) { return section_transform_ste($section, $lang); }, $result); + + if($ste->evalbool($params["include_default"])) + { + $default = section_transform_ste(Section::by_id($default_section), $lang); + array_unshift($result, $default); + } + + $output = ""; + foreach($result as $section) + { + $ste->set_var_by_name($params["var"], $section); + $output .= $sub($ste); + } + return $output; }); /* * STETag: article_comments_count * Get the number of comments for an article. - * + * * Parameters: - * article - (mandatory) The name of the variable, where the article is stored at. - * + * article - (mandatory) The name of the variable, where the article is stored at. + * * Returns: - * The number of comments. + * The number of comments. */ $ste->register_tag("article_comments_count", function($ste, $params, $sub) { - if(!isset($params["article"])) - throw new \ste\RuntimeException("Need parameter 'article' in ste:article_comments_count."); - $tpl_article = $ste->get_var_reference($params["article"], False); - $lang = $ste->vars["language"]; - - if(isset($tpl_article["__obj"])) - $article = $tpl_article["__obj"]; - else - { - try - { - $article = Article::by_id(@$tpl_article["id"]); - } - catch(DoesNotExistError $e) - { - return 0; - } - } - $comments = $article->get_comments($lang, True); - $tpl_article["__comments"] = $comments; - return count($comments); + if(!isset($params["article"])) + throw new \ste\RuntimeException("Need parameter 'article' in ste:article_comments_count."); + $tpl_article = $ste->get_var_reference($params["article"], False); + $lang = $ste->vars["language"]; + + if(isset($tpl_article["__obj"])) + $article = $tpl_article["__obj"]; + else + { + try + { + $article = Article::by_id(@$tpl_article["id"]); + } + catch(DoesNotExistError $e) + { + return 0; + } + } + $comments = $article->get_comments($lang, True); + $tpl_article["__comments"] = $comments; + return count($comments); }); /* * STETag: article_comments * List all comments for an article. * The fields of a comment can be looked up at <comment_transform_ste>. - * + * * 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 - * + * 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. - * + * 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. + * * Returns: - * All results from the tag content. + * All results from the tag content. */ $ste->register_tag("article_comments", function($ste, $params, $sub) { - if(!isset($params["var"])) - throw new \ste\RuntimeException("Need parameter 'var' in ste:article_comments."); - if(!isset($params["article"])) - throw new \ste\RuntimeException("Need parameter 'article' in ste:article_comments."); - $tpl_article = $ste->get_var_reference($params["article"], False); - $lang = $ste->vars["language"]; - - if(isset($tpl_article["__comments"])) - $comments = $tpl_article["__comments"]; - else - { - if(isset($tpl_article["__obj"])) - $article = $tpl_article["__obj"]; - else - { - try - { - $article = Article::by_id(@$tpl_article["id"]); - } - catch(DoesNotExistError $e) - { - return ""; - } - } - - $comments = $article->get_comments($lang, True); - } - - $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); - - $output = ""; - foreach($comments as $comment) - { - $ste->set_var_by_name($params["var"], $comment); - $output .= $sub($ste); - } - return $output; + if(!isset($params["var"])) + throw new \ste\RuntimeException("Need parameter 'var' in ste:article_comments."); + if(!isset($params["article"])) + throw new \ste\RuntimeException("Need parameter 'article' in ste:article_comments."); + $tpl_article = $ste->get_var_reference($params["article"], False); + $lang = $ste->vars["language"]; + + if(isset($tpl_article["__comments"])) + $comments = $tpl_article["__comments"]; + else + { + if(isset($tpl_article["__obj"])) + $article = $tpl_article["__obj"]; + else + { + try + { + $article = Article::by_id(@$tpl_article["id"]); + } + catch(DoesNotExistError $e) + { + return ""; + } + } + + $comments = $article->get_comments($lang, True); + } + + $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); + + $output = ""; + foreach($comments as $comment) + { + $ste->set_var_by_name($params["var"], $comment); + $output .= $sub($ste); + } + return $output; }); /* * STETag: comment_form * Generates a HTML form tag that allows the visitor to write a comment. - * + * * Parameters: - * article - (mandatory) The name of the variable, where the article is stored at. - * default - (optional) If not empty, a default formular with the mandatory fields will be generated. - * previewbtn - (optional) If not empty and default form is choosen, a preview button will also be generated. - * + * article - (mandatory) The name of the variable, where the article is stored at. + * default - (optional) If not empty, a default formular with the mandatory fields will be generated. + * previewbtn - (optional) If not empty and default form is choosen, a preview button will also be generated. + * * Tag Content: - * The tag's content will be written into the HTML form tag. - * You have at least to define these fields: - * - * * <input type="text" name="author_name" /> - The Name of the author. - * * <input type="text" name="author_mail" /> - The E-Mailaddress of the author. - * * <textarea name="comment_text"></textarea> - The Text of the comment. - * * <input type="submit" name="post_comment" /> - Submit button. - * - * You might also want to define this: - * - * * <input type="submit" name="preview_comment" /> - For a preview of the comment. - * - * If the parameter default is not empty, the tag's content will be thrown away. - * + * The tag's content will be written into the HTML form tag. + * You have at least to define these fields: + * + * * <input type="text" name="author_name" /> - The Name of the author. + * * <input type="text" name="author_mail" /> - The E-Mailaddress of the author. + * * <textarea name="comment_text"></textarea> - The Text of the comment. + * * <input type="submit" name="post_comment" /> - Submit button. + * + * You might also want to define this: + * + * * <input type="submit" name="preview_comment" /> - For a preview of the comment. + * + * If the parameter default is not empty, the tag's content will be thrown away. + * * Returns: - * The finished HTML form. - * + * The finished HTML form. + * * See Also: - * The "prevcomment" field in <$current>. + * The "prevcomment" field in <$current>. */ $ste->register_tag("comment_form", function($ste, $params, $sub) { - global $translation; - if(!isset($params["article"])) - throw new \ste\RuntimeException("Need parameter 'article' in ste:comment_form."); - $tpl_article = $ste->get_var_reference($params["article"], False); - - if(isset($tpl_article["__obj"])) - $article = $tpl_article["__obj"]; - else - { - try - { - $article = Article::by_id(@$tpl_article["id"]); - } - catch(DoesNotExistError $e) - { - return ""; - } - } - - if(!$article->allow_comments) - return ""; - - /* 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\" />"; - - $previewbtn = $ste->evalbool(@$params["previewbtn"]) ? " <input type=\"submit\" name=\"preview_comment\" value=\"{$translation["comment_form_preview"]}\" />" : ""; - - if($ste->evalbool(@$params["default"])) - $form_body = "<p>{$translation["comment_form_name"]}: <input type=\"text\" name=\"author_name\" value=\"" . htmlesc(@$_POST["author_name"]) . "\" /></p> + global $translation; + if(!isset($params["article"])) + throw new \ste\RuntimeException("Need parameter 'article' in ste:comment_form."); + $tpl_article = $ste->get_var_reference($params["article"], False); + + if(isset($tpl_article["__obj"])) + $article = $tpl_article["__obj"]; + else + { + try + { + $article = Article::by_id(@$tpl_article["id"]); + } + catch(DoesNotExistError $e) + { + return ""; + } + } + + if(!$article->allow_comments) + return ""; + + /* 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\" />"; + + $previewbtn = $ste->evalbool(@$params["previewbtn"]) ? " <input type=\"submit\" name=\"preview_comment\" value=\"{$translation["comment_form_preview"]}\" />" : ""; + + if($ste->evalbool(@$params["default"])) + $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\" value=\"{$translation["comment_form_submit"]}\" />$previewbtn</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>"; + 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>"; }); /* * STETags: Page control * These tags can create links to the previous/next page. - * + * * page_prev - Link to the previous page (if available). * page_next - Link to the next page (if available). - * + * * Parameters: - * current - (mandatory) The current page number. - * maxpage - (mandatory) How many pages in total? - * default - (optional) If not empty, a default localized link text will be used. - * + * current - (mandatory) The current page number. + * maxpage - (mandatory) How many pages in total? + * default - (optional) If not empty, a default localized link text will be used. + * * Tag Content: - * The tag's content will be used as the link text. - * + * The tag's content will be used as the link text. + * * Returns: - * A Link to the previous / next page. + * A Link to the previous / next page. */ $ste->register_tag("page_prev", function($ste, $params, $sub) { - global $translation; - if(!isset($params["current"])) - throw new \ste\RuntimeException("Need parameter 'current' in ste:page_prev."); - if(!isset($params["maxpage"])) - throw new \ste\RuntimeException("Need parameter 'maxpage' in ste:page_prev."); - - if($params["current"] == 1) - return ""; - - parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query); - $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>"; + global $translation; + if(!isset($params["current"])) + throw new \ste\RuntimeException("Need parameter 'current' in ste:page_prev."); + if(!isset($params["maxpage"])) + throw new \ste\RuntimeException("Need parameter 'maxpage' in ste:page_prev."); + + if($params["current"] == 1) + return ""; + + parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query); + $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 \ste\RuntimeException("Need parameter 'current' in ste:page_next."); - if(!isset($params["maxpage"])) - throw new \ste\RuntimeException("Need parameter 'maxpage' in ste:page_next."); - - if($params["current"] == $params["maxpage"]) - return ""; - - parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query); - $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>"; + global $translation; + if(!isset($params["current"])) + throw new \ste\RuntimeException("Need parameter 'current' in ste:page_next."); + if(!isset($params["maxpage"])) + throw new \ste\RuntimeException("Need parameter 'maxpage' in ste:page_next."); + + if($params["current"] == $params["maxpage"]) + return ""; + + parse_str(parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY), $query); + $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>"; }); /* * STETag: languages * List all languages available in the current context. - * + * * Parameters: - * var - (mandatory) The name of the variable, where the current language information should be stored at. - * + * var - (mandatory) The name of the variable, where the current language information should be stored at. + * * Sub-fields of var: - * short - 2 letter code of language - * fullname - The full name of the language - * url - URL to the current page in this language + * short - 2 letter code of language + * fullname - The full name of the language + * url - URL to the current page in this language * * Tag Content: - * The tag's content will be executed for every language. The current language will be written to the variable specified by the var parameter before. - * + * The tag's content will be executed for every language. The current language will be written to the variable specified by the var parameter before. + * * Returns: - * All results from the tag content. + * All results from the tag content. */ $ste->register_tag("languages", function($ste, $params, $sub) { - global $languages, $ratatoeskr_settings, $rel_path_to_root; - - if(!isset($params["var"])) - throw new Exception("Need parameter 'var' in ste:languages."); - - $langs = array(); - if(isset($ste->vars["current"]["article"])) - { - if(isset($ste->vars["current"]["article"]["__obj"])) - $article = $ste->vars["current"]["article"]["__obj"]; - else - { - try - { - $article = Article::by_id($ste->vars["current"]["article"]["id"]); - } - catch(DoesNotExistError $e) {} - } - foreach($article->title as $lang => $_) - $langs[] = $lang; - } - else - { - - foreach($ratatoeskr_settings["languages"] as $lang) - $langs[] = $lang; - } - - $output = ""; - foreach($langs as $lang) - { - $ste->set_var_by_name($params["var"], array( - "short" => $lang, - "fullname" => htmlesc($languages[$lang]["language"]), - "url" => htmlesc("$rel_path_to_root/$lang/" . implode("/", array_slice($ste->vars["current"]["url_fragments"], 1))) - )); - $output .= $sub($ste); - } - return $output; + global $languages, $ratatoeskr_settings, $rel_path_to_root; + + if(!isset($params["var"])) + throw new Exception("Need parameter 'var' in ste:languages."); + + $langs = array(); + if(isset($ste->vars["current"]["article"])) + { + if(isset($ste->vars["current"]["article"]["__obj"])) + $article = $ste->vars["current"]["article"]["__obj"]; + else + { + try + { + $article = Article::by_id($ste->vars["current"]["article"]["id"]); + } + catch(DoesNotExistError $e) {} + } + foreach($article->title as $lang => $_) + $langs[] = $lang; + } + else + { + + foreach($ratatoeskr_settings["languages"] as $lang) + $langs[] = $lang; + } + + $output = ""; + foreach($langs as $lang) + { + $ste->set_var_by_name($params["var"], array( + "short" => $lang, + "fullname" => htmlesc($languages[$lang]["language"]), + "url" => htmlesc("$rel_path_to_root/$lang/" . implode("/", array_slice($ste->vars["current"]["url_fragments"], 1))) + )); + $output .= $sub($ste); + } + return $output; }); /* * STETag: styles_load * Load all current styles. - * + * * Parameters: - * mode - (optional) Either "embed" or "link". Default: link - * + * mode - (optional) Either "embed" or "link". Default: link + * * Returns: - * The current styles (either linked or embedded) + * The current styles (either linked or embedded) */ $ste->register_tag("styles_load", function($ste, $params, $sub) { - global $rel_path_to_root; - if(isset($params["mode"]) and (($params["mode"] == "embed") or ($params["mode"] == "link"))) - $mode = $params["mode"]; - else - $mode = "link"; - - if($mode == "embed") - { - $output = ""; - if(isset($ste->vars["current"]["__style_objs"])) - { - foreach($ste->vars["current"]["__style_objs"] as $style) - $output .= "/* Style: {$style->name} */\n" . $style->code . "\n"; - } - else - { - foreach($ste->vars["current"]["styles"] as $stylename) - { - try - { - $style = Style::by_name($stylename); - $output .= "/* Style: $stylename */\n" . str_replace("%root%", $rel_path_to_root, $style->code) . "\n"; - } - catch(DoesNotExistError $e) - { - $output .= "/* Warning: Failed to load style: $stylename */\n"; - } - } - } - $output = "<style type=\"text/css\">\n" . htmlesc($output) . "</style>"; - } - else - { - $output = ""; - foreach($ste->vars["current"]["styles"] as $stylename) - $output .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$rel_path_to_root/css.php?name=" . htmlesc($stylename) . "\" />\n"; - } - return $output; + global $rel_path_to_root; + if(isset($params["mode"]) and (($params["mode"] == "embed") or ($params["mode"] == "link"))) + $mode = $params["mode"]; + else + $mode = "link"; + + if($mode == "embed") + { + $output = ""; + if(isset($ste->vars["current"]["__style_objs"])) + { + foreach($ste->vars["current"]["__style_objs"] as $style) + $output .= "/* Style: {$style->name} */\n" . $style->code . "\n"; + } + else + { + foreach($ste->vars["current"]["styles"] as $stylename) + { + try + { + $style = Style::by_name($stylename); + $output .= "/* Style: $stylename */\n" . str_replace("%root%", $rel_path_to_root, $style->code) . "\n"; + } + catch(DoesNotExistError $e) + { + $output .= "/* Warning: Failed to load style: $stylename */\n"; + } + } + } + $output = "<style type=\"text/css\">\n" . htmlesc($output) . "</style>"; + } + else + { + $output = ""; + foreach($ste->vars["current"]["styles"] as $stylename) + $output .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$rel_path_to_root/css.php?name=" . htmlesc($stylename) . "\" />\n"; + } + return $output; }); /* * STETag: title * Generate a HTML title tag for your site. - * + * * Tag Content: - * The name of your site. - * + * The name of your site. + * * Returns: - * A HTML title tag that describes the current (sub)page. + * A HTML title tag that describes the current (sub)page. */ $ste->register_tag("title", function($ste, $params, $sub) { - $pagetitle = $sub($ste); - if(isset($ste->vars["current"]["article"])) - return "<title>" . htmlesc($ste->vars["current"]["article"]["title"]) . " – $pagetitle" . "</title>"; - if(isset($ste->vars["current"]["section"])) - return "<title>" . htmlesc($ste->vars["current"]["section"]["title"]) . " – $pagetitle" . "</title>"; - return "<title>$pagetitle</title>"; + $pagetitle = $sub($ste); + if(isset($ste->vars["current"]["article"])) + return "<title>" . htmlesc($ste->vars["current"]["article"]["title"]) . " – $pagetitle" . "</title>"; + if(isset($ste->vars["current"]["section"])) + return "<title>" . htmlesc($ste->vars["current"]["section"]["title"]) . " – $pagetitle" . "</title>"; + return "<title>$pagetitle</title>"; }); function make_on_anything_tag($field) { - return function($ste, $params, $sub) use ($field) - { - if($ste->evalbool(@$ste->vars["current"][$field])) - { - if(!empty($params["var"])) - $ste->set_var_by_name($params["var"], $ste->vars["current"][$field]); - return $sub($ste); - } - }; + return function($ste, $params, $sub) use ($field) + { + if($ste->evalbool(@$ste->vars["current"][$field])) + { + if(!empty($params["var"])) + $ste->set_var_by_name($params["var"], $ste->vars["current"][$field]); + return $sub($ste); + } + }; } /* @@ -679,10 +679,10 @@ function make_on_anything_tag($field) * Execute tag content, if currently an article is requested. * * Parameters: - * var - (optional) If set, the article will be stored in the variable with that name (see <article_transform_ste> for sub-fields). + * var - (optional) If set, the article will be stored in the variable with that name (see <article_transform_ste> for sub-fields). * * Returns: - * The executed tag content, if an article was requested. + * The executed tag content, if an article was requested. */ $ste->register_tag("on_article", make_on_anything_tag("article")); @@ -691,10 +691,10 @@ $ste->register_tag("on_article", make_on_anything_tag("article")); * Execute tag content, if currently a tag is requested. * * Parameters: - * var - (optional) If set, the tag will be stored in the variable with that name (see <tag_transform_ste> for sub-fields). + * var - (optional) If set, the tag will be stored in the variable with that name (see <tag_transform_ste> for sub-fields). * * Returns: - * The executed tag content, if a tag was requested. + * The executed tag content, if a tag was requested. */ $ste->register_tag("on_tag", make_on_anything_tag("tag")); @@ -703,30 +703,30 @@ $ste->register_tag("on_tag", make_on_anything_tag("tag")); * Execute tag content, if currently a section is requested. * * Parameters: - * var - (optional) If set, the section will be stored in the variable with that name (see <section_transform_ste> for sub-fields). + * var - (optional) If set, the section will be stored in the variable with that name (see <section_transform_ste> for sub-fields). * * Returns: - * The executed tag content, if a section was requested. + * The executed tag content, if a section was requested. */ $ste->register_tag("on_section", make_on_anything_tag("section")); /* * STEVar: $current * Holds information about the current page in the frontend (the part of the webpage, the visitor sees). - * + * * $current has these fields: - * * article - Only set if a single article is shown. Holds information about an article. (sub-fields are described at <article_transform_ste>). - * * section - Only set if a whole section is shown. Holds information about an section. (sub-fields are described at <section_transform_ste>). - * * tag - Only set if all articles with the same tag should be shown (pseudo section _tags). Holds information about a tag. (sub-fields are described at <tag_transform_ste>). - * * page - Which subpage is shown? Useful with <page_prev>, <page_next> and the page parameter of <articles_get>. Default: 1 - * * commented - True, if the visitor has successfully written a comment. - * * comment_fail - If the user tried to comment, but the system rejected the comment, this will be set and will contain the error message. - * * 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. + * * article - Only set if a single article is shown. Holds information about an article. (sub-fields are described at <article_transform_ste>). + * * section - Only set if a whole section is shown. Holds information about an section. (sub-fields are described at <section_transform_ste>). + * * tag - Only set if all articles with the same tag should be shown (pseudo section _tags). Holds information about a tag. (sub-fields are described at <tag_transform_ste>). + * * page - Which subpage is shown? Useful with <page_prev>, <page_next> and the page parameter of <articles_get>. Default: 1 + * * commented - True, if the visitor has successfully written a comment. + * * comment_fail - If the user tried to comment, but the system rejected the comment, this will be set and will contain the error message. + * * 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. */ /* @@ -735,23 +735,23 @@ $ste->register_tag("on_section", make_on_anything_tag("section")); */ $comment_validators = array( - 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_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"]]); - } + 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_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"]]); + } ); $on_comment_store = array(); @@ -761,123 +761,123 @@ $on_comment_store = array(); */ function frontend_url_handler(&$data, $url_now, &$url_next) { - global $ste, $ratatoeskr_settings, $languages, $metasections, $comment_validators, $on_comment_store; - $path = array_merge(array($url_now), $url_next); - $url_next = array(); - - /* If no language or an invalid language was given, fix it. */ - if((count($path) == 0) or (!isset($languages[$path[0]]))) - { - if(count($path > 0)) - array_shift($path); - array_unshift($path, $ratatoeskr_settings["default_language"]); - } - - $ste->vars["current"]["url_fragments"] = $path; - - $lang = array_shift($path); - $ste->vars["language"] = $lang; - load_language($languages[$lang]["translation_exist"] ? $lang : "en"); /* English is always available */ - - if(count($path) != 0) - $section_name = array_shift($path); - else - $section_name = NULL; - - if($section_name == "_tags") - { - try - { - $tag = Tag::by_name(array_shift($path)); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - $ste->vars["current"]["tag"] = tag_transform_ste($tag, $lang); - } - else - { - if($section_name === NULL) - $section = Section::by_id($ratatoeskr_settings["default_section"]); - else - { - try - { - $section = Section::by_name($section_name); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - } - - if(count($path)== 0) - $ste->vars["current"]["section"] = section_transform_ste($section, $lang); - else - { - try - { - $article = Article::by_urlname(array_shift($path)); - } - catch(DoesNotExistError $e) - { - throw new NotFoundError(); - } - $ste->vars["current"]["article"] = article_transform_ste($article, $lang); - - if(isset($_GET["comment"])) - { - if(isset($_POST["preview_comment"])) - $ste->vars["current"]["comment_prev"] = Comment::htmlize_comment_text($_POST["comment_text"]); - else if(isset($_POST["post_comment"])) - { - $rejected = False; - try - { - foreach($comment_validators as $validator) - call_user_func($validator); - } - catch(CommentRejected $e) - { - $ste->vars["current"]["comment_fail"] = htmlesc($e->getMessage()); - $rejected = True; - } - if(!$rejected) - { - $comment = Comment::create($article, $lang); - $comment->author_name = $_POST["author_name"]; - $comment->author_mail = $_POST["author_mail"]; - $comment->text = $_POST["comment_text"]; - $comment->save(); - $ste->vars["current"]["commented"] = "Yes"; - foreach($on_comment_store as $ocs_fx) - call_user_func($ocs_fx, $comment); - } - } - } - } - } - - $ste->vars["current"]["page"] = (isset($_GET["page"]) and is_numeric($_GET["page"])) ? $_GET["page"] : 1; - - if(!isset($section)) - $section = Section::by_id($ratatoeskr_settings["default_section"]); - - foreach($section->get_styles() as $style) - { - $ste->vars["current"]["styles"][] = $style->name; - $ste->vars["current"]["__style_objs"][] = $style; - } - echo $ste->exectemplate("/usertemplates/" . $section->template); + global $ste, $ratatoeskr_settings, $languages, $metasections, $comment_validators, $on_comment_store; + $path = array_merge(array($url_now), $url_next); + $url_next = array(); + + /* If no language or an invalid language was given, fix it. */ + if((count($path) == 0) or (!isset($languages[$path[0]]))) + { + if(count($path > 0)) + array_shift($path); + array_unshift($path, $ratatoeskr_settings["default_language"]); + } + + $ste->vars["current"]["url_fragments"] = $path; + + $lang = array_shift($path); + $ste->vars["language"] = $lang; + load_language($languages[$lang]["translation_exist"] ? $lang : "en"); /* English is always available */ + + if(count($path) != 0) + $section_name = array_shift($path); + else + $section_name = NULL; + + if($section_name == "_tags") + { + try + { + $tag = Tag::by_name(array_shift($path)); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + $ste->vars["current"]["tag"] = tag_transform_ste($tag, $lang); + } + else + { + if($section_name === NULL) + $section = Section::by_id($ratatoeskr_settings["default_section"]); + else + { + try + { + $section = Section::by_name($section_name); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + } + + if(count($path)== 0) + $ste->vars["current"]["section"] = section_transform_ste($section, $lang); + else + { + try + { + $article = Article::by_urlname(array_shift($path)); + } + catch(DoesNotExistError $e) + { + throw new NotFoundError(); + } + $ste->vars["current"]["article"] = article_transform_ste($article, $lang); + + if(isset($_GET["comment"])) + { + if(isset($_POST["preview_comment"])) + $ste->vars["current"]["comment_prev"] = Comment::htmlize_comment_text($_POST["comment_text"]); + else if(isset($_POST["post_comment"])) + { + $rejected = False; + try + { + foreach($comment_validators as $validator) + call_user_func($validator); + } + catch(CommentRejected $e) + { + $ste->vars["current"]["comment_fail"] = htmlesc($e->getMessage()); + $rejected = True; + } + if(!$rejected) + { + $comment = Comment::create($article, $lang); + $comment->author_name = $_POST["author_name"]; + $comment->author_mail = $_POST["author_mail"]; + $comment->text = $_POST["comment_text"]; + $comment->save(); + $ste->vars["current"]["commented"] = "Yes"; + foreach($on_comment_store as $ocs_fx) + call_user_func($ocs_fx, $comment); + } + } + } + } + } + + $ste->vars["current"]["page"] = (isset($_GET["page"]) and is_numeric($_GET["page"])) ? $_GET["page"] : 1; + + if(!isset($section)) + $section = Section::by_id($ratatoeskr_settings["default_section"]); + + foreach($section->get_styles() as $style) + { + $ste->vars["current"]["styles"][] = $style->name; + $ste->vars["current"]["__style_objs"][] = $style; + } + echo $ste->exectemplate("/usertemplates/" . $section->template); } /* * Class: CommentRejected * An Exeption a comment validator can throw, if the validation failed. - * + * * See Also: - * <register_comment_validator> + * <register_comment_validator> */ class CommentRejected extends Exception {} diff --git a/ratatoeskr/js/backend.js b/ratatoeskr/js/backend.js index d131bfe..8b60c2d 100644 --- a/ratatoeskr/js/backend.js +++ b/ratatoeskr/js/backend.js @@ -1,19 +1,19 @@ $(function() { - $("div.articleeditor-metabar-element h2").addClass("metabar_element_expanded").click(function() - { - self = $(this); - if(self.hasClass("metabar_element_expanded")) - { - self.removeClass("metabar_element_expanded"); - self.addClass("metabar_element_collapsed"); - $("div.articleeditor-metabar-element-content", self.parent()).hide("fast"); - } - else - { - self.removeClass("metabar_element_collapsed"); - self.addClass("metabar_element_expanded"); - $("div.articleeditor-metabar-element-content", self.parent()).show("fast"); - } - }); + $("div.articleeditor-metabar-element h2").addClass("metabar_element_expanded").click(function() + { + self = $(this); + if(self.hasClass("metabar_element_expanded")) + { + self.removeClass("metabar_element_expanded"); + self.addClass("metabar_element_collapsed"); + $("div.articleeditor-metabar-element-content", self.parent()).hide("fast"); + } + else + { + self.removeClass("metabar_element_collapsed"); + self.addClass("metabar_element_expanded"); + $("div.articleeditor-metabar-element-content", self.parent()).show("fast"); + } + }); });
\ No newline at end of file diff --git a/ratatoeskr/languages.php b/ratatoeskr/languages.php index 7b2f515..be59e09 100644 --- a/ratatoeskr/languages.php +++ b/ratatoeskr/languages.php @@ -7,200 +7,200 @@ /* * Array: $languages * Information about a lot of languages. - * + * * $languages is a global array. The array keys represent the ISO 639-1 code of the language. * The values are arrays with these keys: - * + * * "language" - The Name of the language in this language (UTF-8 encoded) * "translation_exist" - True, if there is a translation file for this language. * * Source: - * http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + * http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes */ $languages = array( - "aa" => array("language" => "Afaraf", "translation_exist" => False), - "ab" => array("language" => "аҧсуа", "translation_exist" => False), - "ae" => array("language" => "avesta", "translation_exist" => False), - "af" => array("language" => "Afrikaans", "translation_exist" => False), - "ak" => array("language" => "Akan", "translation_exist" => False), - "am" => array("language" => "አማርኛ", "translation_exist" => False), - "an" => array("language" => "Aragonés", "translation_exist" => False), - "ar" => array("language" => "العربية", "translation_exist" => False), - "as" => array("language" => "অসমীয়া", "translation_exist" => False), - "av" => array("language" => "авар мацӀ, магӀарул мацӀ", "translation_exist" => False), - "ay" => array("language" => "aymar aru", "translation_exist" => False), - "az" => array("language" => "azərbaycan dili", "translation_exist" => False), - "ba" => array("language" => "башҡорт теле", "translation_exist" => False), - "be" => array("language" => "Беларуская", "translation_exist" => False), - "bg" => array("language" => "български език", "translation_exist" => False), - "bh" => array("language" => "भोजपुरी", "translation_exist" => False), - "bi" => array("language" => "Bislama", "translation_exist" => False), - "bm" => array("language" => "bamanankan", "translation_exist" => False), - "bn" => array("language" => "বাংলা", "translation_exist" => False), - "bo" => array("language" => "བོད་ཡིག", "translation_exist" => False), - "br" => array("language" => "brezhoneg", "translation_exist" => False), - "bs" => array("language" => "bosanski jezik", "translation_exist" => False), - "ca" => array("language" => "Català", "translation_exist" => False), - "ce" => array("language" => "нохчийн мотт", "translation_exist" => False), - "ch" => array("language" => "Chamoru", "translation_exist" => False), - "co" => array("language" => "corsu, lingua corsa", "translation_exist" => False), - "cr" => array("language" => "ᓀᐦᐃᔭᐍᐏᐣ", "translation_exist" => False), - "cs" => array("language" => "česky, čeština", "translation_exist" => False), - "cu" => array("language" => "ѩзыкъ словѣньскъ", "translation_exist" => False), - "cv" => array("language" => "чӑваш чӗлхи", "translation_exist" => False), - "cy" => array("language" => "Cymraeg", "translation_exist" => False), - "da" => array("language" => "dansk", "translation_exist" => False), - "de" => array("language" => "Deutsch", "translation_exist" => True), - "dv" => array("language" => "ދިވެހި", "translation_exist" => False), - "dz" => array("language" => "རྫོང་ཁ", "translation_exist" => False), - "ee" => array("language" => "Eʋegbe", "translation_exist" => False), - "el" => array("language" => "Ελληνικά", "translation_exist" => False), - "en" => array("language" => "English", "translation_exist" => True), - "eo" => array("language" => "Esperanto", "translation_exist" => False), - "es" => array("language" => "español, castellano", "translation_exist" => False), - "et" => array("language" => "eesti, eesti keel", "translation_exist" => False), - "eu" => array("language" => "euskara, euskera", "translation_exist" => False), - "fa" => array("language" => "فارسی", "translation_exist" => False), - "ff" => array("language" => "Fulfulde, Pulaar, Pular", "translation_exist" => False), - "fi" => array("language" => "suomi, suomen kieli", "translation_exist" => False), - "fj" => array("language" => "vosa Vakaviti", "translation_exist" => False), - "fo" => array("language" => "føroyskt", "translation_exist" => False), - "fr" => array("language" => "français, langue française", "translation_exist" => False), - "fy" => array("language" => "Frysk", "translation_exist" => False), - "ga" => array("language" => "Gaeilge", "translation_exist" => False), - "gd" => array("language" => "Gàidhlig", "translation_exist" => False), - "gl" => array("language" => "Galego", "translation_exist" => False), - "gn" => array("language" => "Avañe'ẽ", "translation_exist" => False), - "gu" => array("language" => "ગુજરાતી", "translation_exist" => False), - "gv" => array("language" => "Gaelg, Gailck", "translation_exist" => False), - "ha" => array("language" => "Hausa, هَوُسَ", "translation_exist" => False), - "he" => array("language" => "עברית", "translation_exist" => False), - "hi" => array("language" => "हिन्दी, हिंदी", "translation_exist" => False), - "ho" => array("language" => "Hiri Motu", "translation_exist" => False), - "hr" => array("language" => "hrvatski", "translation_exist" => False), - "ht" => array("language" => "Kreyòl ayisyen", "translation_exist" => False), - "hu" => array("language" => "Magyar", "translation_exist" => False), - "hy" => array("language" => "Հայերեն", "translation_exist" => False), - "hz" => array("language" => "Otjiherero", "translation_exist" => False), - "ia" => array("language" => "Interlingua", "translation_exist" => False), - "id" => array("language" => "Bahasa Indonesia", "translation_exist" => False), - "ie" => array("language" => "Originally called ", "translation_exist" => False), - "ig" => array("language" => "Asụsụ Igbo", "translation_exist" => False), - "ii" => array("language" => "ꆈꌠ꒿ Nuosuhxop", "translation_exist" => False), - "ik" => array("language" => "Iñupiaq, Iñupiatun", "translation_exist" => False), - "io" => array("language" => "Ido", "translation_exist" => False), - "is" => array("language" => "Íslenska", "translation_exist" => False), - "it" => array("language" => "Italiano", "translation_exist" => False), - "iu" => array("language" => "ᐃᓄᒃᑎᑐᑦ", "translation_exist" => False), - "ja" => array("language" => "日本語 (にほんご)", "translation_exist" => False), - "jv" => array("language" => "basa Jawa", "translation_exist" => False), - "ka" => array("language" => "ქართული", "translation_exist" => False), - "kg" => array("language" => "KiKongo", "translation_exist" => False), - "ki" => array("language" => "Gĩkũyũ", "translation_exist" => False), - "kj" => array("language" => "Kuanyama", "translation_exist" => False), - "kk" => array("language" => "Қазақ тілі", "translation_exist" => False), - "kl" => array("language" => "kalaallisut, kalaallit oqaasii", "translation_exist" => False), - "km" => array("language" => "ភាសាខ្មែរ", "translation_exist" => False), - "kn" => array("language" => "ಕನ್ನಡ", "translation_exist" => False), - "ko" => array("language" => "한국어 (韓國語), 조선어 (朝鮮語)", "translation_exist" => False), - "kr" => array("language" => "Kanuri", "translation_exist" => False), - "ks" => array("language" => "कश्मीरी, كشميري", "translation_exist" => False), - "ku" => array("language" => "Kurdî, كوردی", "translation_exist" => False), - "kv" => array("language" => "коми кыв", "translation_exist" => False), - "kw" => array("language" => "Kernewek", "translation_exist" => False), - "ky" => array("language" => "кыргыз тили", "translation_exist" => False), - "la" => array("language" => "latine, lingua latina", "translation_exist" => False), - "lb" => array("language" => "Lëtzebuergesch", "translation_exist" => False), - "lg" => array("language" => "Luganda", "translation_exist" => False), - "li" => array("language" => "Limburgs", "translation_exist" => False), - "ln" => array("language" => "Lingála", "translation_exist" => False), - "lo" => array("language" => "ພາສາລາວ", "translation_exist" => False), - "lt" => array("language" => "lietuvių kalba", "translation_exist" => False), - "lu" => array("language" => "Luba-Katanga", "translation_exist" => False), - "lv" => array("language" => "latviešu valoda", "translation_exist" => False), - "mg" => array("language" => "Malagasy fiteny", "translation_exist" => False), - "mh" => array("language" => "Kajin M̧ajeļ", "translation_exist" => False), - "mi" => array("language" => "te reo Māori", "translation_exist" => False), - "mk" => array("language" => "македонски јазик", "translation_exist" => False), - "ml" => array("language" => "മലയാളം", "translation_exist" => False), - "mn" => array("language" => "монгол", "translation_exist" => False), - "mr" => array("language" => "मराठी", "translation_exist" => False), - "ms" => array("language" => "bahasa Melayu, بهاس ملايو", "translation_exist" => False), - "mt" => array("language" => "Malti", "translation_exist" => False), - "my" => array("language" => "ဗမာစာ", "translation_exist" => False), - "na" => array("language" => "Ekakairũ Naoero", "translation_exist" => False), - "nb" => array("language" => "Norsk bokmål", "translation_exist" => False), - "nd" => array("language" => "isiNdebele", "translation_exist" => False), - "ne" => array("language" => "नेपाली", "translation_exist" => False), - "ng" => array("language" => "Owambo", "translation_exist" => False), - "nl" => array("language" => "Nederlands, Vlaams", "translation_exist" => False), - "nn" => array("language" => "Norsk nynorsk", "translation_exist" => False), - "no" => array("language" => "Norsk", "translation_exist" => False), - "nr" => array("language" => "isiNdebele", "translation_exist" => False), - "nv" => array("language" => "Diné bizaad, Dinékʼehǰí", "translation_exist" => False), - "ny" => array("language" => "chiCheŵa, chinyanja", "translation_exist" => False), - "oc" => array("language" => "Occitan", "translation_exist" => False), - "oj" => array("language" => "ᐊᓂᔑᓈᐯᒧᐎᓐ", "translation_exist" => False), - "om" => array("language" => "Afaan Oromoo", "translation_exist" => False), - "or" => array("language" => "ଓଡ଼ିଆ", "translation_exist" => False), - "os" => array("language" => "ирон æвзаг", "translation_exist" => False), - "pa" => array("language" => "ਪੰਜਾਬੀ, پنجابی", "translation_exist" => False), - "pi" => array("language" => "पाऴि", "translation_exist" => False), - "pl" => array("language" => "polski", "translation_exist" => False), - "ps" => array("language" => "پښتو", "translation_exist" => False), - "pt" => array("language" => "Português", "translation_exist" => False), - "qu" => array("language" => "Runa Simi, Kichwa", "translation_exist" => False), - "rm" => array("language" => "rumantsch grischun", "translation_exist" => False), - "rn" => array("language" => "Ikirundi", "translation_exist" => False), - "ro" => array("language" => "română", "translation_exist" => False), - "ru" => array("language" => "русский язык", "translation_exist" => False), - "rw" => array("language" => "Ikinyarwanda", "translation_exist" => False), - "sa" => array("language" => "संस्कृतम्", "translation_exist" => False), - "sc" => array("language" => "sardu", "translation_exist" => False), - "sd" => array("language" => "yângâ tî sängö", "translation_exist" => False), - "se" => array("language" => "Davvisámegiella", "translation_exist" => False), - "sg" => array("language" => "yângâ tî sängö", "translation_exist" => False), - "si" => array("language" => "සිංහල", "translation_exist" => False), - "sk" => array("language" => "slovenčina", "translation_exist" => False), - "sl" => array("language" => "slovenščina", "translation_exist" => False), - "sm" => array("language" => "gagana fa'a Samoa", "translation_exist" => False), - "sn" => array("language" => "chiShona", "translation_exist" => False), - "so" => array("language" => "Soomaaliga, af Soomaali", "translation_exist" => False), - "sq" => array("language" => "Shqip", "translation_exist" => False), - "sr" => array("language" => "српски језик", "translation_exist" => False), - "ss" => array("language" => "SiSwati", "translation_exist" => False), - "st" => array("language" => "Sesotho", "translation_exist" => False), - "su" => array("language" => "Basa Sunda", "translation_exist" => False), - "sv" => array("language" => "svenska", "translation_exist" => False), - "sw" => array("language" => "Kiswahili", "translation_exist" => False), - "ta" => array("language" => "தமிழ்", "translation_exist" => False), - "te" => array("language" => "తెలుగు", "translation_exist" => False), - "tg" => array("language" => " тоҷикӣ, toğikī, تاجیکی", "translation_exist" => False), - "th" => array("language" => "ไทย", "translation_exist" => False), - "ti" => array("language" => "ትግርኛ", "translation_exist" => False), - "tk" => array("language" => "Türkmen, Түркмен", "translation_exist" => False), - "tl" => array("language" => "Wikang Tagalog", "translation_exist" => False), - "tn" => array("language" => "Setswana", "translation_exist" => False), - "to" => array("language" => "faka Tonga", "translation_exist" => False), - "tr" => array("language" => "Türkçe", "translation_exist" => False), - "ts" => array("language" => "Xitsonga", "translation_exist" => False), - "tt" => array("language" => "татарча, tatarça, تاتارچا", "translation_exist" => False), - "tw" => array("language" => "Twi", "translation_exist" => False), - "ty" => array("language" => "Reo Tahiti", "translation_exist" => False), - "ug" => array("language" => "Uyƣurqə, ئۇيغۇرچە", "translation_exist" => False), - "uk" => array("language" => "українська", "translation_exist" => False), - "ur" => array("language" => "اردو", "translation_exist" => False), - "uz" => array("language" => "O'zbek, Ўзбек, أۇزبېك", "translation_exist" => False), - "ve" => array("language" => "Tshivenḓa", "translation_exist" => False), - "vi" => array("language" => "Tiếng Việt", "translation_exist" => False), - "vo" => array("language" => "Volapük", "translation_exist" => False), - "wa" => array("language" => "Walon", "translation_exist" => False), - "wo" => array("language" => "Wollof", "translation_exist" => False), - "xh" => array("language" => "isiXhosa", "translation_exist" => False), - "yi" => array("language" => "ייִדיש", "translation_exist" => False), - "yo" => array("language" => "Yorùbá", "translation_exist" => False), - "za" => array("language" => "Saɯ cueŋƅ, Saw cuengh", "translation_exist" => False), - "zh" => array("language" => "中文, 汉语, 漢語", "translation_exist" => False), - "zu" => array("language" => "isiZulu", "translation_exist" => False) + "aa" => array("language" => "Afaraf", "translation_exist" => False), + "ab" => array("language" => "аҧсуа", "translation_exist" => False), + "ae" => array("language" => "avesta", "translation_exist" => False), + "af" => array("language" => "Afrikaans", "translation_exist" => False), + "ak" => array("language" => "Akan", "translation_exist" => False), + "am" => array("language" => "አማርኛ", "translation_exist" => False), + "an" => array("language" => "Aragonés", "translation_exist" => False), + "ar" => array("language" => "العربية", "translation_exist" => False), + "as" => array("language" => "অসমীয়া", "translation_exist" => False), + "av" => array("language" => "авар мацӀ, магӀарул мацӀ", "translation_exist" => False), + "ay" => array("language" => "aymar aru", "translation_exist" => False), + "az" => array("language" => "azərbaycan dili", "translation_exist" => False), + "ba" => array("language" => "башҡорт теле", "translation_exist" => False), + "be" => array("language" => "Беларуская", "translation_exist" => False), + "bg" => array("language" => "български език", "translation_exist" => False), + "bh" => array("language" => "भोजपुरी", "translation_exist" => False), + "bi" => array("language" => "Bislama", "translation_exist" => False), + "bm" => array("language" => "bamanankan", "translation_exist" => False), + "bn" => array("language" => "বাংলা", "translation_exist" => False), + "bo" => array("language" => "བོད་ཡིག", "translation_exist" => False), + "br" => array("language" => "brezhoneg", "translation_exist" => False), + "bs" => array("language" => "bosanski jezik", "translation_exist" => False), + "ca" => array("language" => "Català", "translation_exist" => False), + "ce" => array("language" => "нохчийн мотт", "translation_exist" => False), + "ch" => array("language" => "Chamoru", "translation_exist" => False), + "co" => array("language" => "corsu, lingua corsa", "translation_exist" => False), + "cr" => array("language" => "ᓀᐦᐃᔭᐍᐏᐣ", "translation_exist" => False), + "cs" => array("language" => "česky, čeština", "translation_exist" => False), + "cu" => array("language" => "ѩзыкъ словѣньскъ", "translation_exist" => False), + "cv" => array("language" => "чӑваш чӗлхи", "translation_exist" => False), + "cy" => array("language" => "Cymraeg", "translation_exist" => False), + "da" => array("language" => "dansk", "translation_exist" => False), + "de" => array("language" => "Deutsch", "translation_exist" => True), + "dv" => array("language" => "ދިވެހި", "translation_exist" => False), + "dz" => array("language" => "རྫོང་ཁ", "translation_exist" => False), + "ee" => array("language" => "Eʋegbe", "translation_exist" => False), + "el" => array("language" => "Ελληνικά", "translation_exist" => False), + "en" => array("language" => "English", "translation_exist" => True), + "eo" => array("language" => "Esperanto", "translation_exist" => False), + "es" => array("language" => "español, castellano", "translation_exist" => False), + "et" => array("language" => "eesti, eesti keel", "translation_exist" => False), + "eu" => array("language" => "euskara, euskera", "translation_exist" => False), + "fa" => array("language" => "فارسی", "translation_exist" => False), + "ff" => array("language" => "Fulfulde, Pulaar, Pular", "translation_exist" => False), + "fi" => array("language" => "suomi, suomen kieli", "translation_exist" => False), + "fj" => array("language" => "vosa Vakaviti", "translation_exist" => False), + "fo" => array("language" => "føroyskt", "translation_exist" => False), + "fr" => array("language" => "français, langue française", "translation_exist" => False), + "fy" => array("language" => "Frysk", "translation_exist" => False), + "ga" => array("language" => "Gaeilge", "translation_exist" => False), + "gd" => array("language" => "Gàidhlig", "translation_exist" => False), + "gl" => array("language" => "Galego", "translation_exist" => False), + "gn" => array("language" => "Avañe'ẽ", "translation_exist" => False), + "gu" => array("language" => "ગુજરાતી", "translation_exist" => False), + "gv" => array("language" => "Gaelg, Gailck", "translation_exist" => False), + "ha" => array("language" => "Hausa, هَوُسَ", "translation_exist" => False), + "he" => array("language" => "עברית", "translation_exist" => False), + "hi" => array("language" => "हिन्दी, हिंदी", "translation_exist" => False), + "ho" => array("language" => "Hiri Motu", "translation_exist" => False), + "hr" => array("language" => "hrvatski", "translation_exist" => False), + "ht" => array("language" => "Kreyòl ayisyen", "translation_exist" => False), + "hu" => array("language" => "Magyar", "translation_exist" => False), + "hy" => array("language" => "Հայերեն", "translation_exist" => False), + "hz" => array("language" => "Otjiherero", "translation_exist" => False), + "ia" => array("language" => "Interlingua", "translation_exist" => False), + "id" => array("language" => "Bahasa Indonesia", "translation_exist" => False), + "ie" => array("language" => "Originally called ", "translation_exist" => False), + "ig" => array("language" => "Asụsụ Igbo", "translation_exist" => False), + "ii" => array("language" => "ꆈꌠ꒿ Nuosuhxop", "translation_exist" => False), + "ik" => array("language" => "Iñupiaq, Iñupiatun", "translation_exist" => False), + "io" => array("language" => "Ido", "translation_exist" => False), + "is" => array("language" => "Íslenska", "translation_exist" => False), + "it" => array("language" => "Italiano", "translation_exist" => False), + "iu" => array("language" => "ᐃᓄᒃᑎᑐᑦ", "translation_exist" => False), + "ja" => array("language" => "日本語 (にほんご)", "translation_exist" => False), + "jv" => array("language" => "basa Jawa", "translation_exist" => False), + "ka" => array("language" => "ქართული", "translation_exist" => False), + "kg" => array("language" => "KiKongo", "translation_exist" => False), + "ki" => array("language" => "Gĩkũyũ", "translation_exist" => False), + "kj" => array("language" => "Kuanyama", "translation_exist" => False), + "kk" => array("language" => "Қазақ тілі", "translation_exist" => False), + "kl" => array("language" => "kalaallisut, kalaallit oqaasii", "translation_exist" => False), + "km" => array("language" => "ភាសាខ្មែរ", "translation_exist" => False), + "kn" => array("language" => "ಕನ್ನಡ", "translation_exist" => False), + "ko" => array("language" => "한국어 (韓國語), 조선어 (朝鮮語)", "translation_exist" => False), + "kr" => array("language" => "Kanuri", "translation_exist" => False), + "ks" => array("language" => "कश्मीरी, كشميري", "translation_exist" => False), + "ku" => array("language" => "Kurdî, كوردی", "translation_exist" => False), + "kv" => array("language" => "коми кыв", "translation_exist" => False), + "kw" => array("language" => "Kernewek", "translation_exist" => False), + "ky" => array("language" => "кыргыз тили", "translation_exist" => False), + "la" => array("language" => "latine, lingua latina", "translation_exist" => False), + "lb" => array("language" => "Lëtzebuergesch", "translation_exist" => False), + "lg" => array("language" => "Luganda", "translation_exist" => False), + "li" => array("language" => "Limburgs", "translation_exist" => False), + "ln" => array("language" => "Lingála", "translation_exist" => False), + "lo" => array("language" => "ພາສາລາວ", "translation_exist" => False), + "lt" => array("language" => "lietuvių kalba", "translation_exist" => False), + "lu" => array("language" => "Luba-Katanga", "translation_exist" => False), + "lv" => array("language" => "latviešu valoda", "translation_exist" => False), + "mg" => array("language" => "Malagasy fiteny", "translation_exist" => False), + "mh" => array("language" => "Kajin M̧ajeļ", "translation_exist" => False), + "mi" => array("language" => "te reo Māori", "translation_exist" => False), + "mk" => array("language" => "македонски јазик", "translation_exist" => False), + "ml" => array("language" => "മലയാളം", "translation_exist" => False), + "mn" => array("language" => "монгол", "translation_exist" => False), + "mr" => array("language" => "मराठी", "translation_exist" => False), + "ms" => array("language" => "bahasa Melayu, بهاس ملايو", "translation_exist" => False), + "mt" => array("language" => "Malti", "translation_exist" => False), + "my" => array("language" => "ဗမာစာ", "translation_exist" => False), + "na" => array("language" => "Ekakairũ Naoero", "translation_exist" => False), + "nb" => array("language" => "Norsk bokmål", "translation_exist" => False), + "nd" => array("language" => "isiNdebele", "translation_exist" => False), + "ne" => array("language" => "नेपाली", "translation_exist" => False), + "ng" => array("language" => "Owambo", "translation_exist" => False), + "nl" => array("language" => "Nederlands, Vlaams", "translation_exist" => False), + "nn" => array("language" => "Norsk nynorsk", "translation_exist" => False), + "no" => array("language" => "Norsk", "translation_exist" => False), + "nr" => array("language" => "isiNdebele", "translation_exist" => False), + "nv" => array("language" => "Diné bizaad, Dinékʼehǰí", "translation_exist" => False), + "ny" => array("language" => "chiCheŵa, chinyanja", "translation_exist" => False), + "oc" => array("language" => "Occitan", "translation_exist" => False), + "oj" => array("language" => "ᐊᓂᔑᓈᐯᒧᐎᓐ", "translation_exist" => False), + "om" => array("language" => "Afaan Oromoo", "translation_exist" => False), + "or" => array("language" => "ଓଡ଼ିଆ", "translation_exist" => False), + "os" => array("language" => "ирон æвзаг", "translation_exist" => False), + "pa" => array("language" => "ਪੰਜਾਬੀ, پنجابی", "translation_exist" => False), + "pi" => array("language" => "पाऴि", "translation_exist" => False), + "pl" => array("language" => "polski", "translation_exist" => False), + "ps" => array("language" => "پښتو", "translation_exist" => False), + "pt" => array("language" => "Português", "translation_exist" => False), + "qu" => array("language" => "Runa Simi, Kichwa", "translation_exist" => False), + "rm" => array("language" => "rumantsch grischun", "translation_exist" => False), + "rn" => array("language" => "Ikirundi", "translation_exist" => False), + "ro" => array("language" => "română", "translation_exist" => False), + "ru" => array("language" => "русский язык", "translation_exist" => False), + "rw" => array("language" => "Ikinyarwanda", "translation_exist" => False), + "sa" => array("language" => "संस्कृतम्", "translation_exist" => False), + "sc" => array("language" => "sardu", "translation_exist" => False), + "sd" => array("language" => "yângâ tî sängö", "translation_exist" => False), + "se" => array("language" => "Davvisámegiella", "translation_exist" => False), + "sg" => array("language" => "yângâ tî sängö", "translation_exist" => False), + "si" => array("language" => "සිංහල", "translation_exist" => False), + "sk" => array("language" => "slovenčina", "translation_exist" => False), + "sl" => array("language" => "slovenščina", "translation_exist" => False), + "sm" => array("language" => "gagana fa'a Samoa", "translation_exist" => False), + "sn" => array("language" => "chiShona", "translation_exist" => False), + "so" => array("language" => "Soomaaliga, af Soomaali", "translation_exist" => False), + "sq" => array("language" => "Shqip", "translation_exist" => False), + "sr" => array("language" => "српски језик", "translation_exist" => False), + "ss" => array("language" => "SiSwati", "translation_exist" => False), + "st" => array("language" => "Sesotho", "translation_exist" => False), + "su" => array("language" => "Basa Sunda", "translation_exist" => False), + "sv" => array("language" => "svenska", "translation_exist" => False), + "sw" => array("language" => "Kiswahili", "translation_exist" => False), + "ta" => array("language" => "தமிழ்", "translation_exist" => False), + "te" => array("language" => "తెలుగు", "translation_exist" => False), + "tg" => array("language" => " тоҷикӣ, toğikī, تاجیکی", "translation_exist" => False), + "th" => array("language" => "ไทย", "translation_exist" => False), + "ti" => array("language" => "ትግርኛ", "translation_exist" => False), + "tk" => array("language" => "Türkmen, Түркмен", "translation_exist" => False), + "tl" => array("language" => "Wikang Tagalog", "translation_exist" => False), + "tn" => array("language" => "Setswana", "translation_exist" => False), + "to" => array("language" => "faka Tonga", "translation_exist" => False), + "tr" => array("language" => "Türkçe", "translation_exist" => False), + "ts" => array("language" => "Xitsonga", "translation_exist" => False), + "tt" => array("language" => "татарча, tatarça, تاتارچا", "translation_exist" => False), + "tw" => array("language" => "Twi", "translation_exist" => False), + "ty" => array("language" => "Reo Tahiti", "translation_exist" => False), + "ug" => array("language" => "Uyƣurqə, ئۇيغۇرچە", "translation_exist" => False), + "uk" => array("language" => "українська", "translation_exist" => False), + "ur" => array("language" => "اردو", "translation_exist" => False), + "uz" => array("language" => "O'zbek, Ўзбек, أۇزبېك", "translation_exist" => False), + "ve" => array("language" => "Tshivenḓa", "translation_exist" => False), + "vi" => array("language" => "Tiếng Việt", "translation_exist" => False), + "vo" => array("language" => "Volapük", "translation_exist" => False), + "wa" => array("language" => "Walon", "translation_exist" => False), + "wo" => array("language" => "Wollof", "translation_exist" => False), + "xh" => array("language" => "isiXhosa", "translation_exist" => False), + "yi" => array("language" => "ייִדיש", "translation_exist" => False), + "yo" => array("language" => "Yorùbá", "translation_exist" => False), + "za" => array("language" => "Saɯ cueŋƅ, Saw cuengh", "translation_exist" => False), + "zh" => array("language" => "中文, 汉语, 漢語", "translation_exist" => False), + "zu" => array("language" => "isiZulu", "translation_exist" => False) ); ?> diff --git a/ratatoeskr/main.php b/ratatoeskr/main.php index 4fd22de..9bcbb1d 100644 --- a/ratatoeskr/main.php +++ b/ratatoeskr/main.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/main.php * Initialize and launch Ratatöskr - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -11,7 +11,7 @@ require_once(dirname(__FILE__) . "/config.php"); if(!CONFIG_FILLED_OUT) - die("Config file not filled out!"); + die("Config file not filled out!"); require_once(dirname(__FILE__) . "/sys/db.php"); require_once(dirname(__FILE__) . "/sys/models.php"); @@ -26,88 +26,88 @@ $plugin_objs = array(); function ratatoeskr() { - global $ste; - try - { - _ratatoeskr(); - } - catch(Exception $e) - { - header("HTTP/1.1 500 Internal Server Error"); - $ste->vars["title"] = "500 Internal Server Error"; - if(__DEBUG__) - $ste->vars["details"] = $e->__toString(); - echo $ste->exectemplate("/systemtemplates/error.html"); - } + global $ste; + try + { + _ratatoeskr(); + } + catch(Exception $e) + { + header("HTTP/1.1 500 Internal Server Error"); + $ste->vars["title"] = "500 Internal Server Error"; + if(__DEBUG__) + $ste->vars["details"] = $e->__toString(); + echo $ste->exectemplate("/systemtemplates/error.html"); + } } function _ratatoeskr() { - global $backend_subactions, $ste, $url_handlers, $ratatoeskr_settings, $plugin_objs, $api_compat; - - $ts_start = microtime(True); - - session_start(); - db_connect(); - clean_database(); - - if(isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]) - define("__DEBUG__", True); - - if(PLUGINS_ENABLED) - { - $activeplugins = array_filter(Plugin::all(), function($plugin) { return $plugin->active; }); - foreach($activeplugins as $plugin) - { - if(!in_array($plugin->api, $api_compat)) - { - $plugin->active = False; - $plugin->save(); - continue; - } - - eval($plugin->code); - $plugin_obj = new $plugin->classname($plugin->get_id()); - if($plugin->update) - { - $plugin_obj->update(); - $plugin->update = False; - $plugin->save(); - } - $plugin_obj->init(); - $plugin_objs[$plugin->get_id()] = $plugin_obj; - } - } - - /* Register URL handlers */ - build_backend_subactions(); - register_url_handler("_default", "frontend_url_handler"); - register_url_handler("_index", "frontend_url_handler"); - register_url_handler("index", "frontend_url_handler"); - register_url_handler("backend", $backend_subactions); - register_url_handler("_notfound", url_action_simple(function($data) - { - global $ste; - header("HTTP/1.1 404 Not Found"); - $ste->vars["title"] = "404 Not Found"; - $ste->vars["details"] = str_replace("[[URL]]", $_SERVER["REQUEST_URI"], (isset($translation) ? $translation["e404_details"] : "The page [[URL]] could not be found. Sorry.")); - echo $ste->exectemplate("/systemtemplates/error.html"); - })); - - $urlpath = explode("/", @$_GET["action"]); - $rel_path_to_root = implode("/", array_merge(array("."), array_repeat("..", count($urlpath) - 1))); - $GLOBALS["rel_path_to_root"] = $rel_path_to_root; - $data = array("rel_path_to_root" => $rel_path_to_root); - $ste->vars["rel_path_to_root"] = $rel_path_to_root; - - url_process($urlpath, $url_handlers, $data); - - if(PLUGINS_ENABLED) - { - foreach($plugin_objs as $plugin_obj) - $plugin_obj->atexit(); - } - $ratatoeskr_settings->save(); + global $backend_subactions, $ste, $url_handlers, $ratatoeskr_settings, $plugin_objs, $api_compat; + + $ts_start = microtime(True); + + session_start(); + db_connect(); + clean_database(); + + if(isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]) + define("__DEBUG__", True); + + if(PLUGINS_ENABLED) + { + $activeplugins = array_filter(Plugin::all(), function($plugin) { return $plugin->active; }); + foreach($activeplugins as $plugin) + { + if(!in_array($plugin->api, $api_compat)) + { + $plugin->active = False; + $plugin->save(); + continue; + } + + eval($plugin->code); + $plugin_obj = new $plugin->classname($plugin->get_id()); + if($plugin->update) + { + $plugin_obj->update(); + $plugin->update = False; + $plugin->save(); + } + $plugin_obj->init(); + $plugin_objs[$plugin->get_id()] = $plugin_obj; + } + } + + /* Register URL handlers */ + build_backend_subactions(); + register_url_handler("_default", "frontend_url_handler"); + register_url_handler("_index", "frontend_url_handler"); + register_url_handler("index", "frontend_url_handler"); + register_url_handler("backend", $backend_subactions); + register_url_handler("_notfound", url_action_simple(function($data) + { + global $ste; + header("HTTP/1.1 404 Not Found"); + $ste->vars["title"] = "404 Not Found"; + $ste->vars["details"] = str_replace("[[URL]]", $_SERVER["REQUEST_URI"], (isset($translation) ? $translation["e404_details"] : "The page [[URL]] could not be found. Sorry.")); + echo $ste->exectemplate("/systemtemplates/error.html"); + })); + + $urlpath = explode("/", @$_GET["action"]); + $rel_path_to_root = implode("/", array_merge(array("."), array_repeat("..", count($urlpath) - 1))); + $GLOBALS["rel_path_to_root"] = $rel_path_to_root; + $data = array("rel_path_to_root" => $rel_path_to_root); + $ste->vars["rel_path_to_root"] = $rel_path_to_root; + + url_process($urlpath, $url_handlers, $data); + + if(PLUGINS_ENABLED) + { + foreach($plugin_objs as $plugin_obj) + $plugin_obj->atexit(); + } + $ratatoeskr_settings->save(); } ?> diff --git a/ratatoeskr/setup/create_tables.php b/ratatoeskr/setup/create_tables.php index ef226d8..b0c2075 100644 --- a/ratatoeskr/setup/create_tables.php +++ b/ratatoeskr/setup/create_tables.php @@ -1,7 +1,7 @@ <?php if(!defined("SETUP")) - die(); + die(); require_once(dirname(__FILE__) . "/../sys/db.php"); @@ -166,16 +166,16 @@ SQL; function create_mysql_tables() { - global $sql_tables; - - $queries = explode(";", $sql_tables); - foreach($queries as $q) - { - if(!empty($q)) - qdb($q); - } - - qdb("INSERT INTO `PREFIX_meta` (`key`, `value`) VALUES ('dbversion', ?)", base64_encode(serialize(1))); + global $sql_tables; + + $queries = explode(";", $sql_tables); + foreach($queries as $q) + { + if(!empty($q)) + qdb($q); + } + + qdb("INSERT INTO `PREFIX_meta` (`key`, `value`) VALUES ('dbversion', ?)", base64_encode(serialize(1))); } ?> diff --git a/ratatoeskr/setup/setup.php b/ratatoeskr/setup/setup.php index ef2c510..f51f1a9 100644 --- a/ratatoeskr/setup/setup.php +++ b/ratatoeskr/setup/setup.php @@ -15,240 +15,240 @@ $ste->vars["rel_path_to_root"] = $rel_path_to_root; $ste->vars["translations"] = array(); foreach($languages as $langcode => $langinfo) { - if($langinfo["translation_exist"]) - $ste->vars["translations"][$langcode] = $langinfo["language"]; + if($langinfo["translation_exist"]) + $ste->vars["translations"][$langcode] = $langinfo["language"]; } if(isset($_GET["lang"]) and (@$languages[$_GET["lang"]]["translation_exist"])) { - load_language($_GET["lang"]); - $lang = $_GET["lang"]; - $ste->vars["lang"] = $_GET["lang"]; + load_language($_GET["lang"]); + $lang = $_GET["lang"]; + $ste->vars["lang"] = $_GET["lang"]; } else - die($ste->exectemplate("/systemtemplates/setup_select_lang.html")); + die($ste->exectemplate("/systemtemplates/setup_select_lang.html")); if(isset($_POST["apply_setup"])) { - if(empty($_POST["admin_username"]) or empty($_POST["admin_init_password"])) - $ste->vars["error"] = $translation["admin_data_must_be_filled_out"]; - else - { - $config["mysql"]["server"] = $_POST["mysql_host"]; - $config["mysql"]["db"] = $_POST["mysql_database"]; - $config["mysql"]["user"] = $_POST["mysql_user"]; - $config["mysql"]["passwd"] = $_POST["mysql_password"]; - $config["mysql"]["prefix"] = $_POST["table_prefix"]; - - try - { - db_connect(); - create_mysql_tables(); - - /* Writing some demo data to database */ - require_once(dirname(__FILE__) . "/../sys/models.php"); - - $ratatoeskr_settings["default_language"] = $lang; - $ratatoeskr_settings["comment_visible_defaut"] = True; - $ratatoeskr_settings["allow_comments_default"] = True; - $ratatoeskr_settings["comment_textprocessor"] = "Markdown"; - $ratatoeskr_settings["languages"] = $lang == "en" ? array("en") : array($lang, "en"); - $ratatoeskr_settings["last_db_cleanup"] = time(); - $ratatoeskr_settings["debugmode"] = False; - - $style = Style::create("default"); - $style->code = <<<STYLE + if(empty($_POST["admin_username"]) or empty($_POST["admin_init_password"])) + $ste->vars["error"] = $translation["admin_data_must_be_filled_out"]; + else + { + $config["mysql"]["server"] = $_POST["mysql_host"]; + $config["mysql"]["db"] = $_POST["mysql_database"]; + $config["mysql"]["user"] = $_POST["mysql_user"]; + $config["mysql"]["passwd"] = $_POST["mysql_password"]; + $config["mysql"]["prefix"] = $_POST["table_prefix"]; + + try + { + db_connect(); + create_mysql_tables(); + + /* Writing some demo data to database */ + require_once(dirname(__FILE__) . "/../sys/models.php"); + + $ratatoeskr_settings["default_language"] = $lang; + $ratatoeskr_settings["comment_visible_defaut"] = True; + $ratatoeskr_settings["allow_comments_default"] = True; + $ratatoeskr_settings["comment_textprocessor"] = "Markdown"; + $ratatoeskr_settings["languages"] = $lang == "en" ? array("en") : array($lang, "en"); + $ratatoeskr_settings["last_db_cleanup"] = time(); + $ratatoeskr_settings["debugmode"] = False; + + $style = Style::create("default"); + $style->code = <<<STYLE * { - font-family: sans-serif; - font-size: 10pt; + font-family: sans-serif; + font-size: 10pt; } html { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } body { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } #maincontainer { - width: 80%; - margin: 0px auto 0px; - padding: 0px; + width: 80%; + margin: 0px auto 0px; + padding: 0px; } #heading { - text-align: center; - border-bottom: 1px solid black; - margin: 0px auto 0px; - padding: 10mm 3mm 5mm + text-align: center; + border-bottom: 1px solid black; + margin: 0px auto 0px; + padding: 10mm 3mm 5mm } h1 { - font-size: 24pt; - font-weight: bold; - padding: 0px; - margin: 0px auto 2mm; + font-size: 24pt; + font-weight: bold; + padding: 0px; + margin: 0px auto 2mm; } h2 { - font-size: 14pt; - font-weight: bold; + font-size: 14pt; + font-weight: bold; } h3 { - font-size: 14pt; - font-weight: normal; + font-size: 14pt; + font-weight: normal; } h4 { - font-size: 12pt; - font-weight: bold; + font-size: 12pt; + font-weight: bold; } h5 { - font-size: 12pt; - font-weight: normal + font-size: 12pt; + font-weight: normal } h6 { - font-size: 10pt; - font-weight: bold; - text-decoration: underline; + font-size: 10pt; + font-weight: bold; + text-decoration: underline; } #mainmenu { - border-bottom: 1px solid black; - list-style: none; - height: 10mm; - padding: 0px; - margin: 0px 0px 2mm; + border-bottom: 1px solid black; + list-style: none; + height: 10mm; + padding: 0px; + margin: 0px 0px 2mm; } #mainmenu li { - float: left; - margin: 0px 0px 2mm; - height: 10mm; - overflow: hidden; + float: left; + margin: 0px 0px 2mm; + height: 10mm; + overflow: hidden; } #mainmenu li a { - color: #444; - text-decoration: none; - font-size: 12pt; - margin: 0px; - padding: 2mm 7.5mm 0px; - background: white; - display: block; - height: 10mm; + color: #444; + text-decoration: none; + font-size: 12pt; + margin: 0px; + padding: 2mm 7.5mm 0px; + background: white; + display: block; + height: 10mm; } #mainmenu li.active a { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } #mainmenu li a:hover { - background: #eee; - color: #000; + background: #eee; + color: #000; } #metabar { - float: right; - width: 50mm; - margin: 0px; - padding: 0px 0px 0px 5mm; - border-left: 1px solid black; + float: right; + width: 50mm; + margin: 0px; + padding: 0px 0px 0px 5mm; + border-left: 1px solid black; } div.metabar_module { - border-top: 1px solid black; - padding: 2mm 0px 0px; - margin: 2mm 0px 0px; + border-top: 1px solid black; + padding: 2mm 0px 0px; + margin: 2mm 0px 0px; } div.metabar_module:first-child { - border-top: none; - margin: 0px; - padding: 0px; + border-top: none; + margin: 0px; + padding: 0px; } div.metabar_module h2 { - font-size: 10pt; - font-weight: bold; - padding: 0px; - margin: 0px 0px 2mm; + font-size: 10pt; + font-weight: bold; + padding: 0px; + margin: 0px 0px 2mm; } #content { - border-right: 1px solid black; - margin: 0px 55mm 0px 0px; - padding: 0px 2mm 0px 0px; + border-right: 1px solid black; + margin: 0px 55mm 0px 0px; + padding: 0px 2mm 0px 0px; } #footer { - clear: both; - margin: 4mm 0mm 4mm; - padding: 2mm 0mm 0mm; - text-align: center; - border-top: 1px solid black; + clear: both; + margin: 4mm 0mm 4mm; + padding: 2mm 0mm 0mm; + text-align: center; + border-top: 1px solid black; } table.listtab { - border-collapse: collapse; + border-collapse: collapse; } STYLE; - $style->save(); - - $section = Section::create("home"); - $section->title["en"] = new Translation("Home", ""); - if($lang != "en") - $section->title[$lang] = new Translation("Home", ""); - $section->template = "standard.html"; - $section->add_style($style); - $section->save(); - - $ratatoeskr_settings["default_section"] = $section->get_id(); - - $ratatoeskr_settings->save(); - - $admingrp = Group::create("admins"); - $admin = user::create($_POST["admin_username"], PasswordHash::create($_POST["admin_init_password"])); - $admin->save(); - $admingrp->include_user($admin); - - $article = Article::create("congratulations"); - $article->title["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", ""); - $article->text["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", "Markdown"); - $article->excerpt["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", "Markdown"); - $article->status = ARTICLE_STATUS_LIVE; - $article->timestamp = time(); - $article->allow_comments = True; - $article->set_section($section); - $article->save(); - - try - { - Repository::create("http://r7r-repo-community.silvasur.net/"); - Repository::create("http://r7r-repo-official.silvasur.net/"); - } - catch(RepositoryUnreachableOrInvalid $e) - { - $ste->vars["notice"] = $translation["could_not_initialize_repos"]; - } - - /* Almost done. Give the user the config file. */ - $config = "<?php\n\ndefine(\"__DEBUG__\", False);\ndefine(\"CONFIG_FILLED_OUT\", True);\ndefine(\"PLUGINS_ENABLED\", True);\n\n\$config[\"mysql\"][\"server\"] = '" . addcslashes($config["mysql"]["server"], "'") . "';\n\$config[\"mysql\"][\"db\"] = '" . addcslashes($config["mysql"]["db"], "'") . "';\n\$config[\"mysql\"][\"user\"] = '" . addcslashes($config["mysql"]["user"], "'") . "';\n\$config[\"mysql\"][\"passwd\"] = '" . addcslashes($config["mysql"]["passwd"], "'") . "';\n\$config[\"mysql\"][\"prefix\"] = '" . addcslashes($config["mysql"]["prefix"], "'") . "';\n\n?>"; - $ste->vars["config"] = $config; - die($ste->exectemplate("/systemtemplates/setup_done.html")); - } - catch(MySQLException $e) - { - $ste->vars["error"] = $e->getMessage(); - } - } + $style->save(); + + $section = Section::create("home"); + $section->title["en"] = new Translation("Home", ""); + if($lang != "en") + $section->title[$lang] = new Translation("Home", ""); + $section->template = "standard.html"; + $section->add_style($style); + $section->save(); + + $ratatoeskr_settings["default_section"] = $section->get_id(); + + $ratatoeskr_settings->save(); + + $admingrp = Group::create("admins"); + $admin = user::create($_POST["admin_username"], PasswordHash::create($_POST["admin_init_password"])); + $admin->save(); + $admingrp->include_user($admin); + + $article = Article::create("congratulations"); + $article->title["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", ""); + $article->text["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", "Markdown"); + $article->excerpt["en"] = new Translation("Congratulations! You have just installed Ratatöskr!", "Markdown"); + $article->status = ARTICLE_STATUS_LIVE; + $article->timestamp = time(); + $article->allow_comments = True; + $article->set_section($section); + $article->save(); + + try + { + Repository::create("http://r7r-repo-community.silvasur.net/"); + Repository::create("http://r7r-repo-official.silvasur.net/"); + } + catch(RepositoryUnreachableOrInvalid $e) + { + $ste->vars["notice"] = $translation["could_not_initialize_repos"]; + } + + /* Almost done. Give the user the config file. */ + $config = "<?php\n\ndefine(\"__DEBUG__\", False);\ndefine(\"CONFIG_FILLED_OUT\", True);\ndefine(\"PLUGINS_ENABLED\", True);\n\n\$config[\"mysql\"][\"server\"] = '" . addcslashes($config["mysql"]["server"], "'") . "';\n\$config[\"mysql\"][\"db\"] = '" . addcslashes($config["mysql"]["db"], "'") . "';\n\$config[\"mysql\"][\"user\"] = '" . addcslashes($config["mysql"]["user"], "'") . "';\n\$config[\"mysql\"][\"passwd\"] = '" . addcslashes($config["mysql"]["passwd"], "'") . "';\n\$config[\"mysql\"][\"prefix\"] = '" . addcslashes($config["mysql"]["prefix"], "'") . "';\n\n?>"; + $ste->vars["config"] = $config; + die($ste->exectemplate("/systemtemplates/setup_done.html")); + } + catch(MySQLException $e) + { + $ste->vars["error"] = $e->getMessage(); + } + } } echo $ste->exectemplate("/systemtemplates/setup_dbsetup.html"); diff --git a/ratatoeskr/sys/db.php b/ratatoeskr/sys/db.php index 36d5348..d122502 100644 --- a/ratatoeskr/sys/db.php +++ b/ratatoeskr/sys/db.php @@ -1,9 +1,9 @@ <?php /* * File: ratatoeskr/sys/db.php - * + * * Helper functions for dealing with MySQL. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -11,7 +11,7 @@ */ if(!defined("SETUP")) - require_once(dirname(__FILE__) . "/../config.php"); + require_once(dirname(__FILE__) . "/../config.php"); require_once(dirname(__FILE__) . "/utils.php"); @@ -24,17 +24,17 @@ $db_con = Null; */ function db_connect() { - global $config; - global $db_con; - - $db_con = new PDO( - "mysql:host=" . $config["mysql"]["server"] . ";dbname=" . $config["mysql"]["db"] . ";charset=utf8", - $config["mysql"]["user"], - $config["mysql"]["passwd"], - array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', - )); - $db_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + global $config; + global $db_con; + + $db_con = new PDO( + "mysql:host=" . $config["mysql"]["server"] . ";dbname=" . $config["mysql"]["db"] . ";charset=utf8", + $config["mysql"]["user"], + $config["mysql"]["passwd"], + array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', + )); + $db_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } /* @@ -44,95 +44,95 @@ function db_connect() */ function sub_prefix($q) { - global $config; - return str_replace("PREFIX_", $config["mysql"]["prefix"], $q); + global $config; + return str_replace("PREFIX_", $config["mysql"]["prefix"], $q); } /* * Function: prep_stmt - * + * * Prepares a SQL statement using the global DB connection. * This will also replace "PREFIX_" with the prefix defined in 'config.php'. - * + * * Parameters: - * $q - The query / statement to prepare. - * + * $q - The query / statement to prepare. + * * Returns: - * A PDOStatement object. + * A PDOStatement object. */ function prep_stmt($q) { - global $db_con; - - return $db_con->prepare(sub_prefix($q)); + global $db_con; + + return $db_con->prepare(sub_prefix($q)); } /* * Function: qdb - * + * * Prepares statement (1st argument) with <prep_stmt> and executes it with the remaining arguments. - * + * * Returns: - * A PDOStatement object. + * A PDOStatement object. */ function qdb() { - $args = func_get_args(); - if(count($args) < 1) - throw new InvalidArgumentException("qdb needs at least 1 argument"); - - $stmt = prep_stmt($args[0]); - $stmt->execute(array_slice($args, 1)); - return $stmt; + $args = func_get_args(); + if(count($args) < 1) + throw new InvalidArgumentException("qdb needs at least 1 argument"); + + $stmt = prep_stmt($args[0]); + $stmt->execute(array_slice($args, 1)); + return $stmt; } /* * Class: Transaction - * + * * Makes using transactions easier. */ class Transaction { - public $startedhere; - - /* - * Constructor: __construct - * - * Start a new transaction. - */ - public function __construct() - { - global $db_con; - $this->startedhere = !($db_con->inTransaction()); - if($this->startedhere) - $db_con->beginTransaction(); - } - - /* - * Function: commit - * - * Commit the transaction. - */ - public function commit() - { - global $db_con; - - if($this->startedhere) - $db_con->commit(); - } - - /* - * Function: rollback - * - * Toll the transaction back. - */ - public function rollback() - { - global $db_con; - - if($this->startedhere) - $db_con->rollBack(); - } + public $startedhere; + + /* + * Constructor: __construct + * + * Start a new transaction. + */ + public function __construct() + { + global $db_con; + $this->startedhere = !($db_con->inTransaction()); + if($this->startedhere) + $db_con->beginTransaction(); + } + + /* + * Function: commit + * + * Commit the transaction. + */ + public function commit() + { + global $db_con; + + if($this->startedhere) + $db_con->commit(); + } + + /* + * Function: rollback + * + * Toll the transaction back. + */ + public function rollback() + { + global $db_con; + + if($this->startedhere) + $db_con->rollBack(); + } } ?> diff --git a/ratatoeskr/sys/init_ste.php b/ratatoeskr/sys/init_ste.php index b0a90d1..e45afa6 100644 --- a/ratatoeskr/sys/init_ste.php +++ b/ratatoeskr/sys/init_ste.php @@ -2,9 +2,9 @@ /* * File: ratatoeskr/sys/init_ste.php - * + * * When included, the file will initialize the global STECore instance. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -17,40 +17,40 @@ $tpl_basedir = dirname(__FILE__) . "/../templates"; if(!isset($ste)) { - /* - * Variable: $ste - * - * The global STECore instance. - */ - $ste = new \ste\STECore(new \ste\FilesystemStorageAccess("$tpl_basedir/src", "$tpl_basedir/transc")); - if(defined("__DEBUG__") && __DEBUG__) - $ste->mute_runtime_errors = False; + /* + * Variable: $ste + * + * The global STECore instance. + */ + $ste = new \ste\STECore(new \ste\FilesystemStorageAccess("$tpl_basedir/src", "$tpl_basedir/transc")); + if(defined("__DEBUG__") && __DEBUG__) + $ste->mute_runtime_errors = False; } $ste->register_tag( - "l10n_replace", - function($ste, $params, $sub) - { - $content = $sub($ste); - foreach($params as $name => $replace) - $content = str_replace("[[$name]]", $replace, $content); - return $content; - } + "l10n_replace", + function($ste, $params, $sub) + { + $content = $sub($ste); + foreach($params as $name => $replace) + $content = str_replace("[[$name]]", $replace, $content); + return $content; + } ); $ste->register_tag( - "capitalize", - function($ste, $params, $sub) - { - return ucwords($sub($ste)); - } + "capitalize", + function($ste, $params, $sub) + { + return ucwords($sub($ste)); + } ); $ste->register_tag( - "loremipsum", - function($ste, $params, $sub) - { - $repeats = empty($params["repeat"]) ? 1 : $params["repeat"] + 0; - return implode("\n\n", array_repeat("<p>Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</p>\n\n<p>Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>\n\n<p>Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>\n\n<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.</p>\n\n<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.</p>\n\n<p>Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>", $repeats)); - } + "loremipsum", + function($ste, $params, $sub) + { + $repeats = empty($params["repeat"]) ? 1 : $params["repeat"] + 0; + return implode("\n\n", array_repeat("<p>Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</p>\n\n<p>Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>\n\n<p>Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>\n\n<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.</p>\n\n<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.</p>\n\n<p>Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>", $repeats)); + } ); ?> diff --git a/ratatoeskr/sys/models.php b/ratatoeskr/sys/models.php index 12ca613..c6b7cee 100644 --- a/ratatoeskr/sys/models.php +++ b/ratatoeskr/sys/models.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/sys/models.php * Data models to make database accesses more comfortable. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -22,19 +22,19 @@ db_connect(); * Array of default file extensions for most IMAGETYPE_* constants */ $imagetype_file_extensions = array( - IMAGETYPE_GIF => "gif", - IMAGETYPE_JPEG => "jpg", - IMAGETYPE_PNG => "png", - IMAGETYPE_BMP => "bmp", - IMAGETYPE_TIFF_II => "tif", - IMAGETYPE_TIFF_MM => "tif", + IMAGETYPE_GIF => "gif", + IMAGETYPE_JPEG => "jpg", + IMAGETYPE_PNG => "png", + IMAGETYPE_BMP => "bmp", + IMAGETYPE_TIFF_II => "tif", + IMAGETYPE_TIFF_MM => "tif", ); /* * Variable: $ratatoeskr_settings * The global <Settings> object. Can be accessed like an array. * Has these fields: - * + * * "default_language" - The Language code of the default language. * "comment_visible_default" - True, if comments should be visible by default. * "allow_comments_default" - True, if comments should be allowed by default. @@ -48,7 +48,7 @@ $ratatoeskr_settings = NULL; /* * Constants: ARTICLE_STATUS_ * Possible <Article>::$status values. - * + * * ARTICLE_STATUS_HIDDEN - Article is hidden (Numeric: 0) * ARTICLE_STATUS_LIVE - Article is visible / live (Numeric: 1) * ARTICLE_STATUS_STICKY - Article is sticky (Numeric: 2) @@ -83,16 +83,16 @@ class InvalidDataError extends Exception { } abstract class BySQLRowEnabled { - protected function __construct() { } - - abstract protected function populate_by_sqlrow($sqlrow); - - protected static function by_sqlrow($sqlrow) - { - $obj = new static(); - $obj->populate_by_sqlrow($sqlrow); - return $obj; - } + protected function __construct() { } + + abstract protected function populate_by_sqlrow($sqlrow); + + protected static function by_sqlrow($sqlrow) + { + $obj = new static(); + $obj->populate_by_sqlrow($sqlrow); + return $obj; + } } /* @@ -100,111 +100,111 @@ abstract class BySQLRowEnabled * An abstract class for a KVStorage. * * See also: - * <PluginKVStorage>, <ArticleExtradata> + * <PluginKVStorage>, <ArticleExtradata> */ abstract class KVStorage implements Countable, ArrayAccess, Iterator { - private $keybuffer; - private $counter; - private $silent_mode; - - private $common_vals; - - private $stmt_get; - private $stmt_unset; - private $stmt_update; - private $stmt_create; - - final protected function init($sqltable, $common) - { - $sqltable = sub_prefix($sqltable); - - $this->silent_mode = False; - $this->keybuffer = array(); - - $selector = "WHERE "; - $fields = ""; - foreach($common as $field => $val) - { - $selector .= "`$field` = ? AND "; - $fields .= ", `$field`"; - $this->common_vals[] = $val; - } - - $this->stmt_get = prep_stmt("SELECT `value` FROM `$sqltable` $selector `key` = ?"); - $this->stmt_unset = prep_stmt("DELETE FROM `$sqltable` $selector `key` = ?"); - $this->stmt_update = prep_stmt("UPDATE `$sqltable` SET `value` = ? $selector `key` = ?"); - $this->stmt_create = prep_stmt("INSERT INTO `$sqltable` (`key`, `value` $fields) VALUES (?,?" . str_repeat(",?", count($common)) . ")"); - - $get_keys = prep_stmt("SELECT `key` FROM `$sqltable` $selector 1"); - $get_keys->execute($this->common_vals); - while($sqlrow = $get_keys->fetch()) - $this->keybuffer[] = $sqlrow["key"]; - - $this->counter = 0; - } - - /* - * Functions: Silent mode - * If the silent mode is enabled, the KVStorage behaves even more like a PHP array, i.e. it just returns NULL, - * if a unknown key was requested and does not throw an DoesNotExistError Exception. - * - * enable_silent_mode - Enable the silent mode. - * disable_silent_mode - Disable the silent mode (default). - */ - final public function enable_silent_mode() { $this->silent_mode = True; } - final public function disable_silent_mode() { $this->silent_mode = False; } - - /* Countable interface implementation */ - final public function count() { return count($this->keybuffer); } - - /* ArrayAccess interface implementation */ - final public function offsetExists($offset) { return in_array($offset, $this->keybuffer); } - final public function offsetGet($offset) - { - if($this->offsetExists($offset)) - { - $this->stmt_get->execute(array_merge($this->common_vals, array($offset))); - $sqlrow = $this->stmt_get->fetch(); - $this->stmt_get->closeCursor(); - return unserialize(base64_decode($sqlrow["value"])); - } - elseif($this->silent_mode) - return NULL; - else - throw new DoesNotExistError(); - } - final public function offsetUnset($offset) - { - if($this->offsetExists($offset)) - { - unset($this->keybuffer[array_search($offset, $this->keybuffer)]); - $this->keybuffer = array_merge($this->keybuffer); - $this->stmt_unset->execute(array_merge($this->common_vals, array($offset))); - $this->stmt_unset->closeCursor(); - } - } - final public function offsetSet($offset, $value) - { - if($this->offsetExists($offset)) - { - $this->stmt_update->execute(array_merge(array(base64_encode(serialize($value))), $this->common_vals, array($offset))); - $this->stmt_update->closeCursor(); - } - else - { - $this->stmt_create->execute(array_merge(array($offset, base64_encode(serialize($value))), $this->common_vals)); - $this->stmt_create->closeCursor(); - $this->keybuffer[] = $offset; - } - } - - /* Iterator interface implementation */ - final public function rewind() { return $this->counter = 0; } - final public function current() { return $this->offsetGet($this->keybuffer[$this->counter]); } - final public function key() { return $this->keybuffer[$this->counter]; } - final public function next() { ++$this->counter; } - final public function valid() { return isset($this->keybuffer[$this->counter]); } + private $keybuffer; + private $counter; + private $silent_mode; + + private $common_vals; + + private $stmt_get; + private $stmt_unset; + private $stmt_update; + private $stmt_create; + + final protected function init($sqltable, $common) + { + $sqltable = sub_prefix($sqltable); + + $this->silent_mode = False; + $this->keybuffer = array(); + + $selector = "WHERE "; + $fields = ""; + foreach($common as $field => $val) + { + $selector .= "`$field` = ? AND "; + $fields .= ", `$field`"; + $this->common_vals[] = $val; + } + + $this->stmt_get = prep_stmt("SELECT `value` FROM `$sqltable` $selector `key` = ?"); + $this->stmt_unset = prep_stmt("DELETE FROM `$sqltable` $selector `key` = ?"); + $this->stmt_update = prep_stmt("UPDATE `$sqltable` SET `value` = ? $selector `key` = ?"); + $this->stmt_create = prep_stmt("INSERT INTO `$sqltable` (`key`, `value` $fields) VALUES (?,?" . str_repeat(",?", count($common)) . ")"); + + $get_keys = prep_stmt("SELECT `key` FROM `$sqltable` $selector 1"); + $get_keys->execute($this->common_vals); + while($sqlrow = $get_keys->fetch()) + $this->keybuffer[] = $sqlrow["key"]; + + $this->counter = 0; + } + + /* + * Functions: Silent mode + * If the silent mode is enabled, the KVStorage behaves even more like a PHP array, i.e. it just returns NULL, + * if a unknown key was requested and does not throw an DoesNotExistError Exception. + * + * enable_silent_mode - Enable the silent mode. + * disable_silent_mode - Disable the silent mode (default). + */ + final public function enable_silent_mode() { $this->silent_mode = True; } + final public function disable_silent_mode() { $this->silent_mode = False; } + + /* Countable interface implementation */ + final public function count() { return count($this->keybuffer); } + + /* ArrayAccess interface implementation */ + final public function offsetExists($offset) { return in_array($offset, $this->keybuffer); } + final public function offsetGet($offset) + { + if($this->offsetExists($offset)) + { + $this->stmt_get->execute(array_merge($this->common_vals, array($offset))); + $sqlrow = $this->stmt_get->fetch(); + $this->stmt_get->closeCursor(); + return unserialize(base64_decode($sqlrow["value"])); + } + elseif($this->silent_mode) + return NULL; + else + throw new DoesNotExistError(); + } + final public function offsetUnset($offset) + { + if($this->offsetExists($offset)) + { + unset($this->keybuffer[array_search($offset, $this->keybuffer)]); + $this->keybuffer = array_merge($this->keybuffer); + $this->stmt_unset->execute(array_merge($this->common_vals, array($offset))); + $this->stmt_unset->closeCursor(); + } + } + final public function offsetSet($offset, $value) + { + if($this->offsetExists($offset)) + { + $this->stmt_update->execute(array_merge(array(base64_encode(serialize($value))), $this->common_vals, array($offset))); + $this->stmt_update->closeCursor(); + } + else + { + $this->stmt_create->execute(array_merge(array($offset, base64_encode(serialize($value))), $this->common_vals)); + $this->stmt_create->closeCursor(); + $this->keybuffer[] = $offset; + } + } + + /* Iterator interface implementation */ + final public function rewind() { return $this->counter = 0; } + final public function current() { return $this->offsetGet($this->keybuffer[$this->counter]); } + final public function key() { return $this->keybuffer[$this->counter]; } + final public function next() { ++$this->counter; } + final public function valid() { return isset($this->keybuffer[$this->counter]); } } /* @@ -213,224 +213,224 @@ abstract class KVStorage implements Countable, ArrayAccess, Iterator */ class User extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class properties - * - * $username - The username. - * $pwhash - <PasswordHash> of the password. - * $mail - E-Mail-address. - * $fullname - The full name of the user. - * $language - Users language - */ - public $username; - public $pwhash; - public $mail; - public $fullname; - public $language; - - /* - * Constructor: create - * Creates a new user. - * - * Parameters: - * $username - The username - * $pwhash - <PasswordHash> of the password - * - * Returns: - * An User object - * - * Throws: - * <AlreadyExistsError> - */ - public static function create($username, $pwhash) - { - global $ratatoeskr_settings; - global $db_con; - try - { - $obj = self::by_name($username); - } - catch(DoesNotExistError $e) - { - global $ratatoeskr_settings; - qdb("INSERT INTO `PREFIX_users` (`username`, `pwhash`, `mail`, `fullname`, `language`) VALUES (?, ?, '', '', ?)", - $username, $pwhash, $ratatoeskr_settings["default_language"]); - $obj = new self(); - - $obj->id = $db_con->lastInsertId(); - $obj->username = $username; - $obj->pwhash = $pwhash; - $obj->mail = ""; - $obj->fullname = ""; - $obj->language = $ratatoeskr_settings["default_language"]; - - return $obj; - } - throw new AlreadyExistsError("\"$name\" is already in database."); - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->username = $sqlrow["username"]; - $this->pwhash = $sqlrow["pwhash"]; - $this->mail = $sqlrow["mail"]; - $this->fullname = $sqlrow["fullname"]; - $this->language = $sqlrow["language"]; - } - - /* - * Constructor: by_id - * Get a User object by ID - * - * Parameters: - * $id - The ID. - * - * Returns: - * An User object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_name - * Get a User object by username - * - * Parameters: - * $username - The username. - * - * Returns: - * An User object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_name($username) - { - $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE `username` = ?", $username); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Function: all - * Returns array of all available users. - */ - public static function all() - { - $rv = array(); - - $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - - return $rv; - } - - /* - * Function: get_id - * Returns: - * The user ID. - */ - public function get_id() - { - return $this->id; - } - - /* - * Function: save - * Saves the object to database - * - * Throws: - * AlreadyExistsError - */ - public function save() - { - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_users` WHERE `username` = ? AND `id` != ?", $this->username, $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] > 0) - throw new AlreadyExistsError(); - - qdb("UPDATE `PREFIX_users` SET `username` = ?, `pwhash` = ?, `mail` = ?, `fullname` = ?, `language` = ? WHERE `id` = ?", - $this->username, $this->pwhash, $this->mail, $this->fullname, $this->language, $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - * Deletes the user from the database. - * WARNING: Do NOT use this object any longer after you called this function! - */ - public function delete() - { - $tx = new Transaction(); - try - { - qdb("DELETE FROM `PREFIX_group_members` WHERE `user` = ?", $this->id); - qdb("DELETE FROM `PREFIX_users` WHERE `id` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: get_groups - * Returns: - * List of all groups where this user is a member (array of <Group> objects). - */ - public function get_groups() - { - $rv = array(); - $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name` FROM `PREFIX_groups` `a` INNER JOIN `PREFIX_group_members` `b` ON `a`.`id` = `b`.`group` WHERE `b`.`user` = ?", $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = Group::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: member_of - * Checks, if the user is a member of a group. - * - * Parameters: - * $group - A Group object - * - * Returns: - * True, if the user is a member of $group. False, if not. - */ - public function member_of($group) - { - $stmt = qdb("SELECT COUNT(*) AS `num` FROM `PREFIX_group_members` WHERE `user` = ? AND `group` = ?", $this->id, $group->get_id()); - $sqlrow = $stmt->fetch(); - return ($sqlrow["num"] > 0); - } + private $id; + + /* + * Variables: Public class properties + * + * $username - The username. + * $pwhash - <PasswordHash> of the password. + * $mail - E-Mail-address. + * $fullname - The full name of the user. + * $language - Users language + */ + public $username; + public $pwhash; + public $mail; + public $fullname; + public $language; + + /* + * Constructor: create + * Creates a new user. + * + * Parameters: + * $username - The username + * $pwhash - <PasswordHash> of the password + * + * Returns: + * An User object + * + * Throws: + * <AlreadyExistsError> + */ + public static function create($username, $pwhash) + { + global $ratatoeskr_settings; + global $db_con; + try + { + $obj = self::by_name($username); + } + catch(DoesNotExistError $e) + { + global $ratatoeskr_settings; + qdb("INSERT INTO `PREFIX_users` (`username`, `pwhash`, `mail`, `fullname`, `language`) VALUES (?, ?, '', '', ?)", + $username, $pwhash, $ratatoeskr_settings["default_language"]); + $obj = new self(); + + $obj->id = $db_con->lastInsertId(); + $obj->username = $username; + $obj->pwhash = $pwhash; + $obj->mail = ""; + $obj->fullname = ""; + $obj->language = $ratatoeskr_settings["default_language"]; + + return $obj; + } + throw new AlreadyExistsError("\"$name\" is already in database."); + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->username = $sqlrow["username"]; + $this->pwhash = $sqlrow["pwhash"]; + $this->mail = $sqlrow["mail"]; + $this->fullname = $sqlrow["fullname"]; + $this->language = $sqlrow["language"]; + } + + /* + * Constructor: by_id + * Get a User object by ID + * + * Parameters: + * $id - The ID. + * + * Returns: + * An User object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_name + * Get a User object by username + * + * Parameters: + * $username - The username. + * + * Returns: + * An User object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_name($username) + { + $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE `username` = ?", $username); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Function: all + * Returns array of all available users. + */ + public static function all() + { + $rv = array(); + + $stmt = qdb("SELECT `id`, `username`, `pwhash`, `mail`, `fullname`, `language` FROM `PREFIX_users` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + + return $rv; + } + + /* + * Function: get_id + * Returns: + * The user ID. + */ + public function get_id() + { + return $this->id; + } + + /* + * Function: save + * Saves the object to database + * + * Throws: + * AlreadyExistsError + */ + public function save() + { + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_users` WHERE `username` = ? AND `id` != ?", $this->username, $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] > 0) + throw new AlreadyExistsError(); + + qdb("UPDATE `PREFIX_users` SET `username` = ?, `pwhash` = ?, `mail` = ?, `fullname` = ?, `language` = ? WHERE `id` = ?", + $this->username, $this->pwhash, $this->mail, $this->fullname, $this->language, $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + * Deletes the user from the database. + * WARNING: Do NOT use this object any longer after you called this function! + */ + public function delete() + { + $tx = new Transaction(); + try + { + qdb("DELETE FROM `PREFIX_group_members` WHERE `user` = ?", $this->id); + qdb("DELETE FROM `PREFIX_users` WHERE `id` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: get_groups + * Returns: + * List of all groups where this user is a member (array of <Group> objects). + */ + public function get_groups() + { + $rv = array(); + $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name` FROM `PREFIX_groups` `a` INNER JOIN `PREFIX_group_members` `b` ON `a`.`id` = `b`.`group` WHERE `b`.`user` = ?", $this->id); + while($sqlrow = $stmt->fetch()) + $rv[] = Group::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: member_of + * Checks, if the user is a member of a group. + * + * Parameters: + * $group - A Group object + * + * Returns: + * True, if the user is a member of $group. False, if not. + */ + public function member_of($group) + { + $stmt = qdb("SELECT COUNT(*) AS `num` FROM `PREFIX_group_members` WHERE `user` = ? AND `group` = ?", $this->id, $group->get_id()); + $sqlrow = $stmt->fetch(); + return ($sqlrow["num"] > 0); + } } /* @@ -439,187 +439,187 @@ class User extends BySQLRowEnabled */ class Group extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class properties - * - * $name - Name of the group. - */ - public $name; - - /* - * Constructor: create - * Creates a new group. - * - * Parameters: - * $name - The name of the group. - * - * Returns: - * An Group object - * - * Throws: - * <AlreadyExistsError> - */ - public static function create($name) - { - global $db_con; - try - { - $obj = self::by_name($name); - } - catch(DoesNotExistError $e) - { - qdb("INSERT INTO `PREFIX_groups` (`name`) VALUES (?)", $name); - $obj = new self(); - - $obj->id = $db_con->lastInsertId(); - $obj->name = $name; - - return $obj; - } - throw new AlreadyExistsError("\"$name\" is already in database."); - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - } - - /* - * Constructor: by_id - * Get a Group object by ID - * - * Parameters: - * $id - The ID. - * - * Returns: - * A Group object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_name - * Get a Group object by name - * - * Parameters: - * $name - The group name. - * - * Returns: - * A Group object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_name($name) - { - $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE `name` = ?", $name); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Function: all - * Returns array of all groups - */ - public static function all() - { - $rv = array(); - - $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - - return $rv; - } - - /* - * Function: get_id - * Returns: - * The group ID. - */ - public function get_id() - { - return $this->id; - } - - /* - * Function: delete - * Deletes the group from the database. - */ - public function delete() - { - $tx = new Transaction(); - try - { - qdb("DELETE FROM `PREFIX_group_members` WHERE `group` = ?", $this->id); - qdb("DELETE FROM `PREFIX_groups` WHERE `id` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: get_members - * Get all members of the group. - * - * Returns: - * Array of <User> objects. - */ - public function get_members() - { - $rv = array(); - $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`username` AS `username`, `a`.`pwhash` AS `pwhash`, `a`.`mail` AS `mail`, `a`.`fullname` AS `fullname`, `a`.`language` AS `language` + private $id; + + /* + * Variables: Public class properties + * + * $name - Name of the group. + */ + public $name; + + /* + * Constructor: create + * Creates a new group. + * + * Parameters: + * $name - The name of the group. + * + * Returns: + * An Group object + * + * Throws: + * <AlreadyExistsError> + */ + public static function create($name) + { + global $db_con; + try + { + $obj = self::by_name($name); + } + catch(DoesNotExistError $e) + { + qdb("INSERT INTO `PREFIX_groups` (`name`) VALUES (?)", $name); + $obj = new self(); + + $obj->id = $db_con->lastInsertId(); + $obj->name = $name; + + return $obj; + } + throw new AlreadyExistsError("\"$name\" is already in database."); + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + } + + /* + * Constructor: by_id + * Get a Group object by ID + * + * Parameters: + * $id - The ID. + * + * Returns: + * A Group object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_name + * Get a Group object by name + * + * Parameters: + * $name - The group name. + * + * Returns: + * A Group object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_name($name) + { + $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE `name` = ?", $name); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Function: all + * Returns array of all groups + */ + public static function all() + { + $rv = array(); + + $stmt = qdb("SELECT `id`, `name` FROM `PREFIX_groups` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + + return $rv; + } + + /* + * Function: get_id + * Returns: + * The group ID. + */ + public function get_id() + { + return $this->id; + } + + /* + * Function: delete + * Deletes the group from the database. + */ + public function delete() + { + $tx = new Transaction(); + try + { + qdb("DELETE FROM `PREFIX_group_members` WHERE `group` = ?", $this->id); + qdb("DELETE FROM `PREFIX_groups` WHERE `id` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: get_members + * Get all members of the group. + * + * Returns: + * Array of <User> objects. + */ + public function get_members() + { + $rv = array(); + $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`username` AS `username`, `a`.`pwhash` AS `pwhash`, `a`.`mail` AS `mail`, `a`.`fullname` AS `fullname`, `a`.`language` AS `language` FROM `PREFIX_users` `a` INNER JOIN `PREFIX_group_members` `b` ON `a`.`id` = `b`.`user` WHERE `b`.`group` = ?", $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = User::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: exclude_user - * Excludes user from group. - * - * Parameters: - * $user - <User> object. - */ - public function exclude_user($user) - { - qdb("DELETE FROM `PREFIX_group_members` WHERE `user` = ? AND `group` = ?", $user->get_id(), $this->id); - } - - /* - * Function: include_user - * Includes user to group. - * - * Parameters: - * $user - <User> object. - */ - public function include_user($user) - { - if(!$user->member_of($this)) - qdb("INSERT INTO `PREFIX_group_members` (`user`, `group`) VALUES (?, ?)", $user->get_id(), $this->id); - } + while($sqlrow = $stmt->fetch()) + $rv[] = User::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: exclude_user + * Excludes user from group. + * + * Parameters: + * $user - <User> object. + */ + public function exclude_user($user) + { + qdb("DELETE FROM `PREFIX_group_members` WHERE `user` = ? AND `group` = ?", $user->get_id(), $this->id); + } + + /* + * Function: include_user + * Includes user to group. + * + * Parameters: + * $user - <User> object. + */ + public function include_user($user) + { + if(!$user->member_of($this)) + qdb("INSERT INTO `PREFIX_group_members` (`user`, `group`) VALUES (?, ?)", $user->get_id(), $this->id); + } } /* @@ -628,220 +628,220 @@ WHERE `b`.`group` = ?", $this->id); */ class Translation { - /* - * Variables: Public class variables. - * - * $text - The translated text. - * $texttype - The type of the text. Has only a meaning in a context. - */ - public $text; - public $texttype; - - /* - * Constructor: __construct - * Creates a new Translation object. - * IT WILL NOT BE STORED TO DATABASE! - * - * Parameters: - * $text - The translated text. - * $texttype - The type of the text. Has only a meaning in a context. - * - * See also: - * <Multilingual> - */ - public function __construct($text, $texttype) - { - $this->text = $text; - $this->texttype = $texttype; - } + /* + * Variables: Public class variables. + * + * $text - The translated text. + * $texttype - The type of the text. Has only a meaning in a context. + */ + public $text; + public $texttype; + + /* + * Constructor: __construct + * Creates a new Translation object. + * IT WILL NOT BE STORED TO DATABASE! + * + * Parameters: + * $text - The translated text. + * $texttype - The type of the text. Has only a meaning in a context. + * + * See also: + * <Multilingual> + */ + public function __construct($text, $texttype) + { + $this->text = $text; + $this->texttype = $texttype; + } } /* * Class: Multilingual * Container for <Translation> objects. * Translations can be accessed array-like. So, if you want the german translation: $translation = $my_multilingual["de"]; - * + * * See also: - * <languages.php> + * <languages.php> */ class Multilingual implements Countable, ArrayAccess, IteratorAggregate { - private $translations; - private $id; - private $to_be_deleted; - private $to_be_created; - - private function __construct() - { - $this->translations = array(); - $this->to_be_deleted = array(); - $this->to_be_created = array(); - } - - /* - * Function: get_id - * Retuurns the ID of the object. - */ - public function get_id() - { - return $this->id; - } - - /* - * Constructor: create - * Creates a new Multilingual object - * - * Returns: - * An Multilingual object. - */ - public static function create() - { - global $db_con; - - $obj = new self(); - qdb("INSERT INTO `PREFIX_multilingual` () VALUES ()"); - $obj->id = $db_con->lastInsertId(); - return $obj; - } - - /* - * Constructor: by_id - * Gets an Multilingual object by ID. - * - * Parameters: - * $id - The ID. - * - * Returns: - * An Multilingual object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $obj = new self(); - $stmt = qdb("SELECT `id` FROM `PREFIX_multilingual` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow == False) - throw new DoesNotExistError(); - $obj->id = $id; - - $stmt = qdb("SELECT `language`, `text`, `texttype` FROM `PREFIX_translations` WHERE `multilingual` = ?", $id); - while($sqlrow = $stmt->fetch()) - $obj->translations[$sqlrow["language"]] = new Translation($sqlrow["text"], $sqlrow["texttype"]); - - return $obj; - } - - /* - * Function: save - * Saves the translations to database. - */ - public function save() - { - $tx = new Transaction(); - try - { - foreach($this->to_be_deleted as $deletelang) - qdb("DELETE FROM `PREFIX_translations` WHERE `multilingual` = ? AND `language` = ?", $this->id, $deletelang); - - foreach($this->to_be_created as $lang) - qdb("INSERT INTO `PREFIX_translations` (`multilingual`, `language`, `text`, `texttype`) VALUES (?, ?, ?, ?)", - $this->id, $lang, $this->translations[$lang]->text, $this->translations[$lang]->texttype); - - foreach($this->translations as $lang => $translation) - { - if(!in_array($lang, $this->to_be_created)) - qdb("UPDATE `PREFIX_translations` SET `text` = ?, `texttype` = ? WHERE `multilingual` = ? AND `language` = ?", - $translation->text, $translation->texttype, $this->id, $lang); - } - - $this->to_be_deleted = array(); - $this->to_be_created = array(); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - * Deletes the data from database. - */ - public function delete() - { - $tx = new Transaction(); - try - { - qdb("DELETE FROM `PREFIX_translations` WHERE `multilingual` = ?", $this->id); - qdb("DELETE FROM `PREFIX_multilingual` WHERE `id` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* Countable interface implementation */ - public function count() { return count($this->languages); } - - /* ArrayAccess interface implementation */ - public function offsetExists($offset) { return isset($this->translations[$offset]); } - public function offsetGet($offset) - { - if(isset($this->translations[$offset])) - return $this->translations[$offset]; - else - throw new DoesNotExistError(); - } - public function offsetUnset($offset) - { - unset($this->translations[$offset]); - if(in_array($offset, $this->to_be_created)) - unset($this->to_be_created[array_search($offset, $this->to_be_created)]); - else - $this->to_be_deleted[] = $offset; - } - public function offsetSet($offset, $value) - { - if(!isset($this->translations[$offset])) - { - if(in_array($offset, $this->to_be_deleted)) - unset($this->to_be_deleted[array_search($offset, $this->to_be_deleted)]); - else - $this->to_be_created[] = $offset; - } - $this->translations[$offset] = $value; - } - - /* IteratorAggregate interface implementation */ - public function getIterator() { return new ArrayIterator($this->translations); } + private $translations; + private $id; + private $to_be_deleted; + private $to_be_created; + + private function __construct() + { + $this->translations = array(); + $this->to_be_deleted = array(); + $this->to_be_created = array(); + } + + /* + * Function: get_id + * Retuurns the ID of the object. + */ + public function get_id() + { + return $this->id; + } + + /* + * Constructor: create + * Creates a new Multilingual object + * + * Returns: + * An Multilingual object. + */ + public static function create() + { + global $db_con; + + $obj = new self(); + qdb("INSERT INTO `PREFIX_multilingual` () VALUES ()"); + $obj->id = $db_con->lastInsertId(); + return $obj; + } + + /* + * Constructor: by_id + * Gets an Multilingual object by ID. + * + * Parameters: + * $id - The ID. + * + * Returns: + * An Multilingual object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $obj = new self(); + $stmt = qdb("SELECT `id` FROM `PREFIX_multilingual` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow == False) + throw new DoesNotExistError(); + $obj->id = $id; + + $stmt = qdb("SELECT `language`, `text`, `texttype` FROM `PREFIX_translations` WHERE `multilingual` = ?", $id); + while($sqlrow = $stmt->fetch()) + $obj->translations[$sqlrow["language"]] = new Translation($sqlrow["text"], $sqlrow["texttype"]); + + return $obj; + } + + /* + * Function: save + * Saves the translations to database. + */ + public function save() + { + $tx = new Transaction(); + try + { + foreach($this->to_be_deleted as $deletelang) + qdb("DELETE FROM `PREFIX_translations` WHERE `multilingual` = ? AND `language` = ?", $this->id, $deletelang); + + foreach($this->to_be_created as $lang) + qdb("INSERT INTO `PREFIX_translations` (`multilingual`, `language`, `text`, `texttype`) VALUES (?, ?, ?, ?)", + $this->id, $lang, $this->translations[$lang]->text, $this->translations[$lang]->texttype); + + foreach($this->translations as $lang => $translation) + { + if(!in_array($lang, $this->to_be_created)) + qdb("UPDATE `PREFIX_translations` SET `text` = ?, `texttype` = ? WHERE `multilingual` = ? AND `language` = ?", + $translation->text, $translation->texttype, $this->id, $lang); + } + + $this->to_be_deleted = array(); + $this->to_be_created = array(); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + * Deletes the data from database. + */ + public function delete() + { + $tx = new Transaction(); + try + { + qdb("DELETE FROM `PREFIX_translations` WHERE `multilingual` = ?", $this->id); + qdb("DELETE FROM `PREFIX_multilingual` WHERE `id` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* Countable interface implementation */ + public function count() { return count($this->languages); } + + /* ArrayAccess interface implementation */ + public function offsetExists($offset) { return isset($this->translations[$offset]); } + public function offsetGet($offset) + { + if(isset($this->translations[$offset])) + return $this->translations[$offset]; + else + throw new DoesNotExistError(); + } + public function offsetUnset($offset) + { + unset($this->translations[$offset]); + if(in_array($offset, $this->to_be_created)) + unset($this->to_be_created[array_search($offset, $this->to_be_created)]); + else + $this->to_be_deleted[] = $offset; + } + public function offsetSet($offset, $value) + { + if(!isset($this->translations[$offset])) + { + if(in_array($offset, $this->to_be_deleted)) + unset($this->to_be_deleted[array_search($offset, $this->to_be_deleted)]); + else + $this->to_be_created[] = $offset; + } + $this->translations[$offset] = $value; + } + + /* IteratorAggregate interface implementation */ + public function getIterator() { return new ArrayIterator($this->translations); } } class SettingsIterator implements Iterator { - private $index; - private $keys; - private $settings_obj; - - public function __construct($settings_obj, $keys) - { - $this->index = 0; - $this->settings_obj = $settings_obj; - $this->keys = $keys; - } - - /* Iterator implementation */ - public function current() { return $this->settings_obj[$this->keys[$this->index]]; } - public function key() { return $this->keys[$this->index]; } - public function next() { ++$this->index; } - public function rewind() { $this->index = 0; } - public function valid() { return $this->index < count($this->keys); } + private $index; + private $keys; + private $settings_obj; + + public function __construct($settings_obj, $keys) + { + $this->index = 0; + $this->settings_obj = $settings_obj; + $this->keys = $keys; + } + + /* Iterator implementation */ + public function current() { return $this->settings_obj[$this->keys[$this->index]]; } + public function key() { return $this->keys[$this->index]; } + public function next() { ++$this->index; } + public function rewind() { $this->index = 0; } + public function valid() { return $this->index < count($this->keys); } } /* @@ -851,102 +851,102 @@ class SettingsIterator implements Iterator */ class Settings implements ArrayAccess, IteratorAggregate, Countable { - /* Singleton implementation */ - private function __copy() {} - private static $instance = NULL; - /* - * Constructor: get_instance - * Get an instance of this class. - * All instances are equal (ie. this is a singleton), so you can also use - * the global <$ratatoeskr_settings> instance. - */ - public static function get_instance() - { - if(self::$instance === NULL) - self::$instance = new self; - return self::$instance; - } - - private $buffer; - private $to_be_deleted; - private $to_be_created; - private $to_be_updated; - - private function __construct() - { - $this->buffer = array(); - $stmt = qdb("SELECT `key`, `value` FROM `PREFIX_settings_kvstorage` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $this->buffer[$sqlrow["key"]] = unserialize(base64_decode($sqlrow["value"])); - - $this->to_be_created = array(); - $this->to_be_deleted = array(); - $this->to_be_updated = array(); - } - - public function save() - { - $tx = new Transaction(); - try - { - foreach($this->to_be_deleted as $k) - qdb("DELETE FROM `PREFIX_settings_kvstorage` WHERE `key` = ?", $k); - foreach($this->to_be_updated as $k) - qdb("UPDATE `PREFIX_settings_kvstorage` SET `value` = ? WHERE `key` = ?", base64_encode(serialize($this->buffer[$k])), $k); - foreach($this->to_be_created as $k) - qdb("INSERT INTO `PREFIX_settings_kvstorage` (`key`, `value`) VALUES (?, ?)", $k, base64_encode(serialize($this->buffer[$k]))); - - $this->to_be_created = array(); - $this->to_be_deleted = array(); - $this->to_be_updated = array(); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* ArrayAccess implementation */ - public function offsetExists($offset) - { - return isset($this->buffer[$offset]); - } - public function offsetGet($offset) - { - return $this->buffer[$offset]; - } - public function offsetSet ($offset, $value) - { - if(!$this->offsetExists($offset)) - { - if(in_array($offset, $this->to_be_deleted)) - { - $this->to_be_updated[] = $offset; - unset($this->to_be_deleted[array_search($offset, $this->to_be_deleted)]); - } - else - $this->to_be_created[] = $offset; - } - elseif((!in_array($offset, $this->to_be_created)) and (!in_array($offset, $this->to_be_updated))) - $this->to_be_updated[] = $offset; - $this->buffer[$offset] = $value; - } - public function offsetUnset($offset) - { - if(in_array($offset, $this->to_be_created)) - unset($this->to_be_created[array_search($offset, $this->to_be_created)]); - else - $this->to_be_deleted[] = $offset; - unset($this->buffer[$offset]); - } - - /* IteratorAggregate implementation */ - public function getIterator() { return new SettingsIterator($this, array_keys($this->buffer)); } - - /* Countable implementation */ - public function count() { return count($this->buffer); } + /* Singleton implementation */ + private function __copy() {} + private static $instance = NULL; + /* + * Constructor: get_instance + * Get an instance of this class. + * All instances are equal (ie. this is a singleton), so you can also use + * the global <$ratatoeskr_settings> instance. + */ + public static function get_instance() + { + if(self::$instance === NULL) + self::$instance = new self; + return self::$instance; + } + + private $buffer; + private $to_be_deleted; + private $to_be_created; + private $to_be_updated; + + private function __construct() + { + $this->buffer = array(); + $stmt = qdb("SELECT `key`, `value` FROM `PREFIX_settings_kvstorage` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $this->buffer[$sqlrow["key"]] = unserialize(base64_decode($sqlrow["value"])); + + $this->to_be_created = array(); + $this->to_be_deleted = array(); + $this->to_be_updated = array(); + } + + public function save() + { + $tx = new Transaction(); + try + { + foreach($this->to_be_deleted as $k) + qdb("DELETE FROM `PREFIX_settings_kvstorage` WHERE `key` = ?", $k); + foreach($this->to_be_updated as $k) + qdb("UPDATE `PREFIX_settings_kvstorage` SET `value` = ? WHERE `key` = ?", base64_encode(serialize($this->buffer[$k])), $k); + foreach($this->to_be_created as $k) + qdb("INSERT INTO `PREFIX_settings_kvstorage` (`key`, `value`) VALUES (?, ?)", $k, base64_encode(serialize($this->buffer[$k]))); + + $this->to_be_created = array(); + $this->to_be_deleted = array(); + $this->to_be_updated = array(); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* ArrayAccess implementation */ + public function offsetExists($offset) + { + return isset($this->buffer[$offset]); + } + public function offsetGet($offset) + { + return $this->buffer[$offset]; + } + public function offsetSet ($offset, $value) + { + if(!$this->offsetExists($offset)) + { + if(in_array($offset, $this->to_be_deleted)) + { + $this->to_be_updated[] = $offset; + unset($this->to_be_deleted[array_search($offset, $this->to_be_deleted)]); + } + else + $this->to_be_created[] = $offset; + } + elseif((!in_array($offset, $this->to_be_created)) and (!in_array($offset, $this->to_be_updated))) + $this->to_be_updated[] = $offset; + $this->buffer[$offset] = $value; + } + public function offsetUnset($offset) + { + if(in_array($offset, $this->to_be_created)) + unset($this->to_be_created[array_search($offset, $this->to_be_created)]); + else + $this->to_be_deleted[] = $offset; + unset($this->buffer[$offset]); + } + + /* IteratorAggregate implementation */ + public function getIterator() { return new SettingsIterator($this, array_keys($this->buffer)); } + + /* Countable implementation */ + public function count() { return count($this->buffer); } } $ratatoeskr_settings = Settings::get_instance(); @@ -961,16 +961,16 @@ $ratatoeskr_settings = Settings::get_instance(); */ class PluginKVStorage extends KVStorage { - /* - * Constructor: __construct - * - * Parameters: - * $plugin_id - The ID of the Plugin. - */ - public function __construct($plugin_id) - { - $this->init("PREFIX_plugin_kvstorage", array("plugin" => $plugin_id)); - } + /* + * Constructor: __construct + * + * Parameters: + * $plugin_id - The ID of the Plugin. + */ + public function __construct($plugin_id) + { + $this->init("PREFIX_plugin_kvstorage", array("plugin" => $plugin_id)); + } } /* @@ -979,213 +979,213 @@ class PluginKVStorage extends KVStorage */ class Comment extends BySQLRowEnabled { - private $id; - private $article_id; - private $language; - private $timestamp; - - /* - * Variables: Public class variables. - * - * $author_name - Name of comment author. - * $author_mail - E-Mail of comment author. - * $text - Comment text. - * $visible - Should the comment be visible? - * $read_by_admin - Was the comment read by an admin. - */ - public $author_name; - public $author_mail; - public $text; - public $visible; - public $read_by_admin; - - /* - * Functions: Getters - * - * get_id - Gets the comment ID. - * get_article - Gets the article. - * get_language - Gets the language. - * get_timestamp - Gets the timestamp. - */ - public function get_id() { return $this->id; } - public function get_article() { return Article::by_id($this->article_id); } - public function get_language() { return $this->language; } - public function get_timestamp() { return $this->timestamp; } - - /* - * Constructor: create - * Creates a new comment. - * Automatically sets the $timestamp and $visible (default from setting "comment_visible_default"). - * - * Parameters: - * $article - An <Article> Object. - * $language - Which language? (see <languages.php>) - */ - public static function create($article, $language) - { - global $ratatoeskr_settings; - global $db_con; - - $obj = new self(); - $obj->timestamp = time(); - - qdb("INSERT INTO `PREFIX_comments` (`article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin`) VALUES (?, ?, '', '', '', ?, ?, 0)", - $article->get_id(), $language, $obj->timestamp, $ratatoeskr_settings["comment_visible_default"] ? 1 : 0); - - $obj->id = $db_con->lastInsertId(); - $obj->article_id = $article->get_id(); - $obj->language = $language; - $obj->author_name = ""; - $obj->author_mail = ""; - $obj->text = ""; - $obj->visible = $ratatoeskr_settings["comment_visible_default"]; - $obj->read_by_admin = False; - - return $obj; - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->article_id = $sqlrow["article"]; - $this->language = $sqlrow["language"]; - $this->author_name = $sqlrow["author_name"]; - $this->author_mail = $sqlrow["author_mail"]; - $this->text = $sqlrow["text"]; - $this->timestamp = $sqlrow["timestamp"]; - $this->visible = $sqlrow["visible"] == 1; - $this->read_by_admin = $sqlrow["read_by_admin"] == 1; - } - - /* - * Constructor: by_id - * Gets a Comment by ID. - * - * Parameters: - * $id - The comments ID. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Get all comments - * - * Returns: - * Array of Comment objects - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: htmlize_comment_text - * Creates the HTML representation of a comment text. It applys the page's comment textprocessor on it - * and filters some potentially harmful tags using kses. - * - * Parameters: - * $text - Text to HTMLize. - * - * Returns: - * HTML code. - */ - public static function htmlize_comment_text($text) - { - global $ratatoeskr_settings; - - return kses(textprocessor_apply($text, $ratatoeskr_settings["comment_textprocessor"]), 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: create_html - * Applys <htmlize_comment_text> onto this comment's text. - * - * Returns: - * The HTML representation. - */ - public function create_html() - { - return self::htmlize_comment_text($this->text); - } - - /* - * Function: save - * Save changes to database. - */ - public function save() - { - qdb("UPDATE `PREFIX_comments` SET `author_name` = ?, `author_mail` = ?, `text` = ?, `visible` = ?, `read_by_admin` = ? WHERE `id` = ?", - $this->author_name, $this->author_mail, $this->text, ($this->visible ? 1 : 0), ($this->read_by_admin ? 1 : 0), $this->id); - } - - /* - * Function: delete - */ - public function delete() - { - qdb("DELETE FROM `PREFIX_comments` WHERE `id` = ?", $this->id); - } + private $id; + private $article_id; + private $language; + private $timestamp; + + /* + * Variables: Public class variables. + * + * $author_name - Name of comment author. + * $author_mail - E-Mail of comment author. + * $text - Comment text. + * $visible - Should the comment be visible? + * $read_by_admin - Was the comment read by an admin. + */ + public $author_name; + public $author_mail; + public $text; + public $visible; + public $read_by_admin; + + /* + * Functions: Getters + * + * get_id - Gets the comment ID. + * get_article - Gets the article. + * get_language - Gets the language. + * get_timestamp - Gets the timestamp. + */ + public function get_id() { return $this->id; } + public function get_article() { return Article::by_id($this->article_id); } + public function get_language() { return $this->language; } + public function get_timestamp() { return $this->timestamp; } + + /* + * Constructor: create + * Creates a new comment. + * Automatically sets the $timestamp and $visible (default from setting "comment_visible_default"). + * + * Parameters: + * $article - An <Article> Object. + * $language - Which language? (see <languages.php>) + */ + public static function create($article, $language) + { + global $ratatoeskr_settings; + global $db_con; + + $obj = new self(); + $obj->timestamp = time(); + + qdb("INSERT INTO `PREFIX_comments` (`article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin`) VALUES (?, ?, '', '', '', ?, ?, 0)", + $article->get_id(), $language, $obj->timestamp, $ratatoeskr_settings["comment_visible_default"] ? 1 : 0); + + $obj->id = $db_con->lastInsertId(); + $obj->article_id = $article->get_id(); + $obj->language = $language; + $obj->author_name = ""; + $obj->author_mail = ""; + $obj->text = ""; + $obj->visible = $ratatoeskr_settings["comment_visible_default"]; + $obj->read_by_admin = False; + + return $obj; + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->article_id = $sqlrow["article"]; + $this->language = $sqlrow["language"]; + $this->author_name = $sqlrow["author_name"]; + $this->author_mail = $sqlrow["author_mail"]; + $this->text = $sqlrow["text"]; + $this->timestamp = $sqlrow["timestamp"]; + $this->visible = $sqlrow["visible"] == 1; + $this->read_by_admin = $sqlrow["read_by_admin"] == 1; + } + + /* + * Constructor: by_id + * Gets a Comment by ID. + * + * Parameters: + * $id - The comments ID. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Get all comments + * + * Returns: + * Array of Comment objects + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: htmlize_comment_text + * Creates the HTML representation of a comment text. It applys the page's comment textprocessor on it + * and filters some potentially harmful tags using kses. + * + * Parameters: + * $text - Text to HTMLize. + * + * Returns: + * HTML code. + */ + public static function htmlize_comment_text($text) + { + global $ratatoeskr_settings; + + return kses(textprocessor_apply($text, $ratatoeskr_settings["comment_textprocessor"]), 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: create_html + * Applys <htmlize_comment_text> onto this comment's text. + * + * Returns: + * The HTML representation. + */ + public function create_html() + { + return self::htmlize_comment_text($this->text); + } + + /* + * Function: save + * Save changes to database. + */ + public function save() + { + qdb("UPDATE `PREFIX_comments` SET `author_name` = ?, `author_mail` = ?, `text` = ?, `visible` = ?, `read_by_admin` = ? WHERE `id` = ?", + $this->author_name, $this->author_mail, $this->text, ($this->visible ? 1 : 0), ($this->read_by_admin ? 1 : 0), $this->id); + } + + /* + * Function: delete + */ + public function delete() + { + qdb("DELETE FROM `PREFIX_comments` WHERE `id` = ?", $this->id); + } } /* @@ -1194,185 +1194,185 @@ class Comment extends BySQLRowEnabled */ class Style extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class variables. - * - * $name - The name of the style. - * $code - The CSS code. - */ - public $name; - public $code; - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->code = $sqlrow["code"]; - } - - /* - * Function: test_name - * Test, if a name is a valid Style name. - * - * Parameters: - * $name - The name to test - * - * Returns: - * True, if the name is a valid style name, False if not. - */ - public static function test_name($name) - { - return preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $name) == 1; - } - - /* - * Function: get_id - */ - public function get_id() { return $this->id; } - - /* - * Constructor: create - * Create a new style. - * - * Parameters: - * $name - A name for the new style. - * - * Throws: - * <AlreadyExistsError> - */ - public static function create($name) - { - global $db_con; - - if(!self::test_name($name)) - throw new InvalidDataError("invalid_style_name"); - - try - { - self::by_name($name); - } - catch(DoesNotExistError $e) - { - $obj = new self(); - $obj->name = $name; - $obj->code = ""; - - qdb("INSERT INTO `PREFIX_styles` (`name`, `code`) VALUES (?, '')", $name); - - $obj->id = $db_con->lastInsertId(); - return $obj; - } - - throw new AlreadyExistsError(); - } - - /* - * Constructor: by_id - * Gets a Style object by ID. - * - * Parameters: - * $id - The ID - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_name - * Gets a Style object by name. - * - * Parameters: - * $name - The name. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_name($name) - { - $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE `name` = ?", $name); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Get all styles - * - * Returns: - * Array of Style objects - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: save - * Save changes to database. - * - * Throws: - * <AlreadyExistsError> - */ - public function save() - { - if(!self::test_name($this->name)) - throw new InvalidDataError("invalid_style_name"); - - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_styles` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] > 0) - throw new AlreadyExistsError(); - - qdb("UPDATE `PREFIX_styles` SET `name` = ?, `code` = ? WHERE `id` = ?", - $this->name, $this->code, $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - */ - public function delete() - { - $tx = new Transaction(); - try - { - qdb("DELETE FROM `PREFIX_styles` WHERE `id` = ?", $this->id); - qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `style` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } + private $id; + + /* + * Variables: Public class variables. + * + * $name - The name of the style. + * $code - The CSS code. + */ + public $name; + public $code; + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->code = $sqlrow["code"]; + } + + /* + * Function: test_name + * Test, if a name is a valid Style name. + * + * Parameters: + * $name - The name to test + * + * Returns: + * True, if the name is a valid style name, False if not. + */ + public static function test_name($name) + { + return preg_match("/^[a-zA-Z0-9\\-_\\.]+$/", $name) == 1; + } + + /* + * Function: get_id + */ + public function get_id() { return $this->id; } + + /* + * Constructor: create + * Create a new style. + * + * Parameters: + * $name - A name for the new style. + * + * Throws: + * <AlreadyExistsError> + */ + public static function create($name) + { + global $db_con; + + if(!self::test_name($name)) + throw new InvalidDataError("invalid_style_name"); + + try + { + self::by_name($name); + } + catch(DoesNotExistError $e) + { + $obj = new self(); + $obj->name = $name; + $obj->code = ""; + + qdb("INSERT INTO `PREFIX_styles` (`name`, `code`) VALUES (?, '')", $name); + + $obj->id = $db_con->lastInsertId(); + return $obj; + } + + throw new AlreadyExistsError(); + } + + /* + * Constructor: by_id + * Gets a Style object by ID. + * + * Parameters: + * $id - The ID + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_name + * Gets a Style object by name. + * + * Parameters: + * $name - The name. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_name($name) + { + $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE `name` = ?", $name); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Get all styles + * + * Returns: + * Array of Style objects + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `code` FROM `PREFIX_styles` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: save + * Save changes to database. + * + * Throws: + * <AlreadyExistsError> + */ + public function save() + { + if(!self::test_name($this->name)) + throw new InvalidDataError("invalid_style_name"); + + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_styles` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] > 0) + throw new AlreadyExistsError(); + + qdb("UPDATE `PREFIX_styles` SET `name` = ?, `code` = ? WHERE `id` = ?", + $this->name, $this->code, $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + */ + public function delete() + { + $tx = new Transaction(); + try + { + qdb("DELETE FROM `PREFIX_styles` WHERE `id` = ?", $this->id); + qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `style` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } } /* @@ -1381,205 +1381,205 @@ class Style extends BySQLRowEnabled */ class Plugin extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class variables. - * - * $name - Plugin name. - * $code - Plugin code. - * $classname - Main class of the plugin. - * $active - Is the plugin activated? - * $author - Author of the plugin. - * $versiontext - Version (text) - * $versioncount - Version (counter) - * $short_description - A short description. - * $updatepath - URL for updates. - * $web - Webpage of the plugin. - * $help - Help page. - * $license - License text. - * $installed - Is this plugin installed? Used during the installation process. - * $update - Should the plugin be updated at next start? - * $api - The API version this Plugin needs. - */ - - public $name; - public $code; - public $classname; - public $active; - public $author; - public $versiontext; - public $versioncount; - public $short_description; - public $updatepath; - public $web; - public $help; - public $license; - public $installed; - public $update; - public $api; - - /* - * Function: clean_db - * Performs some datadase cleanup jobs on the plugin table. - */ - public static function clean_db() - { - qdb("DELETE FROM `PREFIX_plugins` WHERE `installed` = 0 AND `added` < ?", (time() - (60*5))); - } - - /* - * Function: get_id - */ - public function get_id() { return $this->id; } - - /* - * Constructor: create - * Creates a new, empty plugin database entry - */ - public static function create() - { - global $db_con; - - $obj = new self(); - qdb("INSERT INTO `PREFIX_plugins` (`added`) VALUES (?)", time()); - $obj->id = $db_con->lastInsertId(); - return $obj; - } - - /* - * Function: fill_from_pluginpackage - * Fills plugin data from an <PluginPackage> object. - * - * Parameters: - * $pkg - The <PluginPackage> object. - */ - public function fill_from_pluginpackage($pkg) - { - $this->name = $pkg->name; - $this->code = $pkg->code; - $this->classname = $pkg->classname; - $this->author = $pkg->author; - $this->versiontext = $pkg->versiontext; - $this->versioncount = $pkg->versioncount; - $this->short_description = $pkg->short_description; - $this->updatepath = $pkg->updatepath; - $this->web = $pkg->web; - $this->license = $pkg->license; - $this->help = $pkg->help; - $this->api = $pkg->api; - - if(!empty($pkg->custompub)) - array2dir($pkg->custompub, dirname(__FILE__) . "/../plugin_extradata/public/" . $this->get_id()); - if(!empty($pkg->custompriv)) - array2dir($pkg->custompriv, dirname(__FILE__) . "/../plugin_extradata/private/" . $this->get_id()); - if(!empty($pkg->tpls)) - array2dir($pkg->tpls, dirname(__FILE__) . "/../templates/src/plugintemplates/" . $this->get_id()); - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->code = $sqlrow["code"]; - $this->classname = $sqlrow["classname"]; - $this->active = ($sqlrow["active"] == 1); - $this->author = $sqlrow["author"]; - $this->versiontext = $sqlrow["versiontext"]; - $this->versioncount = $sqlrow["versioncount"]; - $this->short_description = $sqlrow["short_description"]; - $this->updatepath = $sqlrow["updatepath"]; - $this->web = $sqlrow["web"]; - $this->help = $sqlrow["help"]; - $this->license = $sqlrow["license"]; - $this->installed = ($sqlrow["installed"] == 1); - $this->update = ($sqlrow["update"] == 1); - $this->api = $sqlrow["api"]; - } - - /* - * Constructor: by_id - * Gets plugin by ID. - * - * Parameters: - * $id - The ID - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `author`, `versiontext`, `versioncount`, `short_description`, `updatepath`, `web`, `help`, `code`, `classname`, `active`, `license`, `installed`, `update`, `api` FROM `PREFIX_plugins` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Gets all Plugins - * - * Returns: - * List of <Plugin> objects. - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `author`, `versiontext`, `versioncount`, `short_description`, `updatepath`, `web`, `help`, `code`, `classname`, `active`, `license`, `installed`, `update`, `api` FROM `PREFIX_plugins` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: save - */ - public function save() - { - qdb("UPDATE `PREFIX_plugins` SET `name` = ?, `author` = ?, `code` = ?, `classname` = ?, `active` = ?, `versiontext` = ?, `versioncount` = ?, `short_description` = ?, `updatepath` = ?, `web` = ?, `help` = ?, `installed` = ?, `update` = ?, `license` = ?, `api` = ? WHERE `id` = ?", - $this->name, $this->author, $this->code, $this->classname, ($this->active ? 1 : 0), $this->versiontext, $this->versioncount, $this->short_description, $this->updatepath, $this->web, $this->help, ($this->installed ? 1 : 0), ($this->update ? 1 : 0), $this->license, $this->api, $this->id); - } - - /* - * Function: delete - */ - public function delete() - { - $tx = new Transaction(); - try - { - qdb("DELETE FROM `PREFIX_plugins` WHERE `id` = ?", $this->id); - qdb("DELETE FROM `PREFIX_plugin_kvstorage` WHERE `plugin` = ?", $this->id); - qdb("DELETE FROM `PREFIX_article_extradata` WHERE `plugin` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - - if(is_dir(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id)) - delete_directory(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id); - if(is_dir(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id)) - delete_directory(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id); - if(is_dir(SITE_BASE_PATH . "/ratatoeskr/templates/src/plugintemplates/" . $this->id)) - delete_directory(SITE_BASE_PATH . "/ratatoeskr/templates/src/plugintemplates/" . $this->id); - } - - /* - * Function get_kvstorage - * Get the KeyValue Storage for the plugin. - * - * Returns: - * An <PluginKVStorage> object. - */ - public function get_kvstorage() - { - return new PluginKVStorage($this->id); - } + private $id; + + /* + * Variables: Public class variables. + * + * $name - Plugin name. + * $code - Plugin code. + * $classname - Main class of the plugin. + * $active - Is the plugin activated? + * $author - Author of the plugin. + * $versiontext - Version (text) + * $versioncount - Version (counter) + * $short_description - A short description. + * $updatepath - URL for updates. + * $web - Webpage of the plugin. + * $help - Help page. + * $license - License text. + * $installed - Is this plugin installed? Used during the installation process. + * $update - Should the plugin be updated at next start? + * $api - The API version this Plugin needs. + */ + + public $name; + public $code; + public $classname; + public $active; + public $author; + public $versiontext; + public $versioncount; + public $short_description; + public $updatepath; + public $web; + public $help; + public $license; + public $installed; + public $update; + public $api; + + /* + * Function: clean_db + * Performs some datadase cleanup jobs on the plugin table. + */ + public static function clean_db() + { + qdb("DELETE FROM `PREFIX_plugins` WHERE `installed` = 0 AND `added` < ?", (time() - (60*5))); + } + + /* + * Function: get_id + */ + public function get_id() { return $this->id; } + + /* + * Constructor: create + * Creates a new, empty plugin database entry + */ + public static function create() + { + global $db_con; + + $obj = new self(); + qdb("INSERT INTO `PREFIX_plugins` (`added`) VALUES (?)", time()); + $obj->id = $db_con->lastInsertId(); + return $obj; + } + + /* + * Function: fill_from_pluginpackage + * Fills plugin data from an <PluginPackage> object. + * + * Parameters: + * $pkg - The <PluginPackage> object. + */ + public function fill_from_pluginpackage($pkg) + { + $this->name = $pkg->name; + $this->code = $pkg->code; + $this->classname = $pkg->classname; + $this->author = $pkg->author; + $this->versiontext = $pkg->versiontext; + $this->versioncount = $pkg->versioncount; + $this->short_description = $pkg->short_description; + $this->updatepath = $pkg->updatepath; + $this->web = $pkg->web; + $this->license = $pkg->license; + $this->help = $pkg->help; + $this->api = $pkg->api; + + if(!empty($pkg->custompub)) + array2dir($pkg->custompub, dirname(__FILE__) . "/../plugin_extradata/public/" . $this->get_id()); + if(!empty($pkg->custompriv)) + array2dir($pkg->custompriv, dirname(__FILE__) . "/../plugin_extradata/private/" . $this->get_id()); + if(!empty($pkg->tpls)) + array2dir($pkg->tpls, dirname(__FILE__) . "/../templates/src/plugintemplates/" . $this->get_id()); + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->code = $sqlrow["code"]; + $this->classname = $sqlrow["classname"]; + $this->active = ($sqlrow["active"] == 1); + $this->author = $sqlrow["author"]; + $this->versiontext = $sqlrow["versiontext"]; + $this->versioncount = $sqlrow["versioncount"]; + $this->short_description = $sqlrow["short_description"]; + $this->updatepath = $sqlrow["updatepath"]; + $this->web = $sqlrow["web"]; + $this->help = $sqlrow["help"]; + $this->license = $sqlrow["license"]; + $this->installed = ($sqlrow["installed"] == 1); + $this->update = ($sqlrow["update"] == 1); + $this->api = $sqlrow["api"]; + } + + /* + * Constructor: by_id + * Gets plugin by ID. + * + * Parameters: + * $id - The ID + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `author`, `versiontext`, `versioncount`, `short_description`, `updatepath`, `web`, `help`, `code`, `classname`, `active`, `license`, `installed`, `update`, `api` FROM `PREFIX_plugins` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Gets all Plugins + * + * Returns: + * List of <Plugin> objects. + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `author`, `versiontext`, `versioncount`, `short_description`, `updatepath`, `web`, `help`, `code`, `classname`, `active`, `license`, `installed`, `update`, `api` FROM `PREFIX_plugins` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: save + */ + public function save() + { + qdb("UPDATE `PREFIX_plugins` SET `name` = ?, `author` = ?, `code` = ?, `classname` = ?, `active` = ?, `versiontext` = ?, `versioncount` = ?, `short_description` = ?, `updatepath` = ?, `web` = ?, `help` = ?, `installed` = ?, `update` = ?, `license` = ?, `api` = ? WHERE `id` = ?", + $this->name, $this->author, $this->code, $this->classname, ($this->active ? 1 : 0), $this->versiontext, $this->versioncount, $this->short_description, $this->updatepath, $this->web, $this->help, ($this->installed ? 1 : 0), ($this->update ? 1 : 0), $this->license, $this->api, $this->id); + } + + /* + * Function: delete + */ + public function delete() + { + $tx = new Transaction(); + try + { + qdb("DELETE FROM `PREFIX_plugins` WHERE `id` = ?", $this->id); + qdb("DELETE FROM `PREFIX_plugin_kvstorage` WHERE `plugin` = ?", $this->id); + qdb("DELETE FROM `PREFIX_article_extradata` WHERE `plugin` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + + if(is_dir(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id)) + delete_directory(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id); + if(is_dir(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id)) + delete_directory(SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id); + if(is_dir(SITE_BASE_PATH . "/ratatoeskr/templates/src/plugintemplates/" . $this->id)) + delete_directory(SITE_BASE_PATH . "/ratatoeskr/templates/src/plugintemplates/" . $this->id); + } + + /* + * Function get_kvstorage + * Get the KeyValue Storage for the plugin. + * + * Returns: + * An <PluginKVStorage> object. + */ + public function get_kvstorage() + { + return new PluginKVStorage($this->id); + } } /* @@ -1588,266 +1588,266 @@ class Plugin extends BySQLRowEnabled */ class Section extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class variables - * - * $name - The name of the section. - * $title - The title of the section (a <Multilingual> object). - * $template - Name of the template. - */ - public $name; - public $title; - public $template; - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->title = Multilingual::by_id($sqlrow["title"]); - $this->template = $sqlrow["template"]; - } - - /* - * Function: test_name - * Tests, if a name is a valid section name. - * - * Parameters: - * $name - The name to test. - * - * Returns: - * True, if the name is a valid section name, False otherwise. - */ - public static function test_name($name) - { - return preg_match("/^[a-zA-Z0-9\\-_]+$/", $name) != 0; - } - - /* - * Function: get_id - */ - public function get_id() { return $this->id; } - - /* - * Constructor: create - * Creates a new section. - * - * Parameters: - * $name - The name of the new section. - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public static function create($name) - { - global $db_con; - - if(!self::test_name($name)) - throw new InvalidDataError("invalid_section_name"); - - try - { - $obj = self::by_name($name); - } - catch(DoesNotExistError $e) - { - $obj = new self(); - $obj->name = $name; - $obj->title = Multilingual::create(); - $obj->template = ""; - - qdb("INSERT INTO `PREFIX_sections` (`name`, `title`, `template`) VALUES (?, ?, '')", $name, $obj->title->get_id()); - - $obj->id = $db_con->lastInsertId(); - - return $obj; - } - - throw new AlreadyExistsError(); - } - - /* - * Constructor: by_id - * Gets section by ID. - * - * Parameters: - * $id - The ID. - * - * Returns: - * A <Section> object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_name - * Gets section by name. - * - * Parameters: - * $name - The name. - * - * Returns: - * A <Section> object. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_name($name) - { - $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE `name` = ?", $name); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Gets all sections. - * - * Returns: - * Array of Section objects. - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: get_styles - * Get all styles associated with this section. - * - * Returns: - * List of <Style> objects. - */ - public function get_styles() - { - $rv = array(); - $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name`, `a`.`code` AS `code` FROM `PREFIX_styles` `a` INNER JOIN `PREFIX_section_style_relations` `b` ON `a`.`id` = `b`.`style` WHERE `b`.`section` = ?", $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = Style::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: add_style - * Add a style to this section. - * - * Parameters: - * $style - A <Style> object. - */ - public function add_style($style) - { - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_section_style_relations` WHERE `style` = ? AND `section` = ?", $style->get_id(), $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] == 0) - qdb("INSERT INTO `PREFIX_section_style_relations` (`section`, `style`) VALUES (?, ?)", $this->id, $style->get_id()); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: remove_style - * Remove a style from this section. - * - * Parameters: - * $style - A <Style> object. - */ - public function remove_style($style) - { - qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `section` = ? AND `style` = ?", $this->id, $style->get_id()); - } - - /* - * Function: save - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public function save() - { - if(!self::test_name($this->name)) - throw new InvalidDataError("invalid_section_name"); - - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_sections` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] > 0) - throw new AlreadyExistsError(); - - $this->title->save(); - qdb("UPDATE `PREFIX_sections` SET `name` = ?, `title` = ?, `template` = ? WHERE `id` = ?", - $this->name, $this->title->get_id(), $this->template, $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - */ - public function delete() - { - $tx = new Transaction(); - try - { - $this->title->delete(); - qdb("DELETE FROM `PREFIX_sections` WHERE `id` = ?", $this->id); - qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `section` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: get_articles - * Get all articles in this section. - * - * Returns: - * Array of <Article> objects - */ - public function get_articles() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `section` = ?", $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = Article::by_sqlrow($sqlrow); - return $rv; - } + private $id; + + /* + * Variables: Public class variables + * + * $name - The name of the section. + * $title - The title of the section (a <Multilingual> object). + * $template - Name of the template. + */ + public $name; + public $title; + public $template; + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->title = Multilingual::by_id($sqlrow["title"]); + $this->template = $sqlrow["template"]; + } + + /* + * Function: test_name + * Tests, if a name is a valid section name. + * + * Parameters: + * $name - The name to test. + * + * Returns: + * True, if the name is a valid section name, False otherwise. + */ + public static function test_name($name) + { + return preg_match("/^[a-zA-Z0-9\\-_]+$/", $name) != 0; + } + + /* + * Function: get_id + */ + public function get_id() { return $this->id; } + + /* + * Constructor: create + * Creates a new section. + * + * Parameters: + * $name - The name of the new section. + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public static function create($name) + { + global $db_con; + + if(!self::test_name($name)) + throw new InvalidDataError("invalid_section_name"); + + try + { + $obj = self::by_name($name); + } + catch(DoesNotExistError $e) + { + $obj = new self(); + $obj->name = $name; + $obj->title = Multilingual::create(); + $obj->template = ""; + + qdb("INSERT INTO `PREFIX_sections` (`name`, `title`, `template`) VALUES (?, ?, '')", $name, $obj->title->get_id()); + + $obj->id = $db_con->lastInsertId(); + + return $obj; + } + + throw new AlreadyExistsError(); + } + + /* + * Constructor: by_id + * Gets section by ID. + * + * Parameters: + * $id - The ID. + * + * Returns: + * A <Section> object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_name + * Gets section by name. + * + * Parameters: + * $name - The name. + * + * Returns: + * A <Section> object. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_name($name) + { + $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE `name` = ?", $name); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Gets all sections. + * + * Returns: + * Array of Section objects. + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `title`, `template` FROM `PREFIX_sections` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: get_styles + * Get all styles associated with this section. + * + * Returns: + * List of <Style> objects. + */ + public function get_styles() + { + $rv = array(); + $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name`, `a`.`code` AS `code` FROM `PREFIX_styles` `a` INNER JOIN `PREFIX_section_style_relations` `b` ON `a`.`id` = `b`.`style` WHERE `b`.`section` = ?", $this->id); + while($sqlrow = $stmt->fetch()) + $rv[] = Style::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: add_style + * Add a style to this section. + * + * Parameters: + * $style - A <Style> object. + */ + public function add_style($style) + { + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_section_style_relations` WHERE `style` = ? AND `section` = ?", $style->get_id(), $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] == 0) + qdb("INSERT INTO `PREFIX_section_style_relations` (`section`, `style`) VALUES (?, ?)", $this->id, $style->get_id()); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: remove_style + * Remove a style from this section. + * + * Parameters: + * $style - A <Style> object. + */ + public function remove_style($style) + { + qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `section` = ? AND `style` = ?", $this->id, $style->get_id()); + } + + /* + * Function: save + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public function save() + { + if(!self::test_name($this->name)) + throw new InvalidDataError("invalid_section_name"); + + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_sections` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] > 0) + throw new AlreadyExistsError(); + + $this->title->save(); + qdb("UPDATE `PREFIX_sections` SET `name` = ?, `title` = ?, `template` = ? WHERE `id` = ?", + $this->name, $this->title->get_id(), $this->template, $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + */ + public function delete() + { + $tx = new Transaction(); + try + { + $this->title->delete(); + qdb("DELETE FROM `PREFIX_sections` WHERE `id` = ?", $this->id); + qdb("DELETE FROM `PREFIX_section_style_relations` WHERE `section` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: get_articles + * Get all articles in this section. + * + * Returns: + * Array of <Article> objects + */ + public function get_articles() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `section` = ?", $this->id); + while($sqlrow = $stmt->fetch()) + $rv[] = Article::by_sqlrow($sqlrow); + return $rv; + } } /* @@ -1856,219 +1856,219 @@ class Section extends BySQLRowEnabled */ class Tag extends BySQLRowEnabled { - private $id; - - /* - * Variables: Public class variables - * - * $name - The name of the tag - * $title - The title (an <Multilingual> object) - */ - public $name; - public $title; - - /* - * Function: test_name - * Test, if a name is a valid tag name. - * - * Parameters: - * $name - Name to test. - * - * Returns: - * True, if the name is valid, False otherwise. - */ - public static function test_name($name) - { - return (strpos($name, ",") === False) and (strpos($name, " ") === False); - } - - /* - * Function: get_id - */ - public function get_id() { return $this->id; } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->title = Multilingual::by_id($sqlrow["title"]); - } - - /* - * Constructor: create - * Create a new tag. - * - * Parameters: - * $name - The name - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public static function create($name) - { - global $db_con; - if(!self::test_name($name)) - throw new InvalidDataError("invalid_tag_name"); - - try - { - $obj = self::by_name($name); - } - catch(DoesNotExistError $e) - { - $obj = new self(); - - $obj->name = $name; - $obj->title = Multilingual::create(); - - qdb("INSERT INTO `PREFIX_tags` (`name`, `title`) VALUES (?, ?)", - $name, $obj->title->get_id()); - $obj->id = $db_con->lastInsertId(); - - return $obj; - } - throw new AlreadyExistsError(); - } - - /* - * Constructor: by_id - * Get tag by ID - * - * Parameters: - * $id - The ID - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_name - * Get tag by name - * - * Parameters: - * $name - The name - * - * Throws: - * <DoesNotExistError> - */ - public static function by_name($name) - { - $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE `name` = ?", $name); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Get all tags - * - * Returns: - * Array of Tag objects. - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: get_articles - * Get all articles that are tagged with this tag - * - * Returns: - * Array of <Article> objects - */ - public function get_articles() - { - $rv = array(); - $stmt = qdb( + private $id; + + /* + * Variables: Public class variables + * + * $name - The name of the tag + * $title - The title (an <Multilingual> object) + */ + public $name; + public $title; + + /* + * Function: test_name + * Test, if a name is a valid tag name. + * + * Parameters: + * $name - Name to test. + * + * Returns: + * True, if the name is valid, False otherwise. + */ + public static function test_name($name) + { + return (strpos($name, ",") === False) and (strpos($name, " ") === False); + } + + /* + * Function: get_id + */ + public function get_id() { return $this->id; } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->title = Multilingual::by_id($sqlrow["title"]); + } + + /* + * Constructor: create + * Create a new tag. + * + * Parameters: + * $name - The name + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public static function create($name) + { + global $db_con; + if(!self::test_name($name)) + throw new InvalidDataError("invalid_tag_name"); + + try + { + $obj = self::by_name($name); + } + catch(DoesNotExistError $e) + { + $obj = new self(); + + $obj->name = $name; + $obj->title = Multilingual::create(); + + qdb("INSERT INTO `PREFIX_tags` (`name`, `title`) VALUES (?, ?)", + $name, $obj->title->get_id()); + $obj->id = $db_con->lastInsertId(); + + return $obj; + } + throw new AlreadyExistsError(); + } + + /* + * Constructor: by_id + * Get tag by ID + * + * Parameters: + * $id - The ID + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_name + * Get tag by name + * + * Parameters: + * $name - The name + * + * Throws: + * <DoesNotExistError> + */ + public static function by_name($name) + { + $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE `name` = ?", $name); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Get all tags + * + * Returns: + * Array of Tag objects. + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `title` FROM `PREFIX_tags` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: get_articles + * Get all articles that are tagged with this tag + * + * Returns: + * Array of <Article> objects + */ + public function get_articles() + { + $rv = array(); + $stmt = qdb( "SELECT `a`.`id` AS `id`, `a`.`urlname` AS `urlname`, `a`.`title` AS `title`, `a`.`text` AS `text`, `a`.`excerpt` AS `excerpt`, `a`.`meta` AS `meta`, `a`.`custom` AS `custom`, `a`.`article_image` AS `article_image`, `a`.`status` AS `status`, `a`.`section` AS `section`, `a`.`timestamp` AS `timestamp`, `a`.`allow_comments` AS `allow_comments` FROM `PREFIX_articles` `a` INNER JOIN `PREFIX_article_tag_relations` `b` ON `a`.`id` = `b`.`article` WHERE `b`.`tag` = ?" , $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = Article::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: count_articles - * - * Returns: - * The number of articles that are tagged with this tag. - */ - public function count_articles() - { - $stmt = qdb("SELECT COUNT(*) AS `num` FROM `PREFIX_article_tag_relations` WHERE `tag` = ?", $this->id); - $sqlrow = $stmt->fetch(); - return $sqlrow["num"]; - } - - /* - * Function: save - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public function save() - { - if(!self::test_name($this->name)) - throw new InvalidDataError("invalid_tag_name"); - - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_tags` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] > 0) - throw new AlreadyExistsError(); - - $this->title->save(); - qdb("UPDATE `PREFIX_tags` SET `name` = ?, `title` = ? WHERE `id` = ?", - $this->name, $this->title->get_id(), $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - */ - public function delete() - { - $tx = new Transaction(); - try - { - $this->title->delete(); - qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `tag` = ?", $this->id); - qdb("DELETE FROM `PREFIX_tags` WHERE `id` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } + while($sqlrow = $stmt->fetch()) + $rv[] = Article::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: count_articles + * + * Returns: + * The number of articles that are tagged with this tag. + */ + public function count_articles() + { + $stmt = qdb("SELECT COUNT(*) AS `num` FROM `PREFIX_article_tag_relations` WHERE `tag` = ?", $this->id); + $sqlrow = $stmt->fetch(); + return $sqlrow["num"]; + } + + /* + * Function: save + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public function save() + { + if(!self::test_name($this->name)) + throw new InvalidDataError("invalid_tag_name"); + + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_tags` WHERE `name` = ? AND `id` != ?", $this->name, $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] > 0) + throw new AlreadyExistsError(); + + $this->title->save(); + qdb("UPDATE `PREFIX_tags` SET `name` = ?, `title` = ? WHERE `id` = ?", + $this->name, $this->title->get_id(), $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + */ + public function delete() + { + $tx = new Transaction(); + try + { + $this->title->delete(); + qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `tag` = ?", $this->id); + qdb("DELETE FROM `PREFIX_tags` WHERE `id` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } } /* @@ -2089,185 +2089,185 @@ class IOError extends Exception { } */ class Image extends BySQLRowEnabled { - private $id; - private $filename; - - private static $pre_maxw = 150; - private static $pre_maxh = 100; - - /* - * Variables: Public class variables - * - * $name - The image name - */ - public $name; - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->file = $sqlrow["file"]; - } - - /* - * Functions: Getters - * - * get_id - Get the ID - * get_filename - Get the filename - */ - public function get_id() { return $this->id; } - public function get_filename() { return $this->file; } - - /* - * Constructor: create - * Create a new image - * - * Parameters: - * $name - The name for the image - * $file - An uploaded image file (move_uploaded_file must be able to move the file!). - * - * Throws: - * <IOError>, <UnknownFileFormat> - */ - public static function create($name, $file) - { - $obj = new self(); - $obj->name = $name; - $obj->file = "0"; - - $tx = new Transaction(); - try - { - global $db_con; - - qdb("INSERT INTO `PREFIX_images` (`name`, `file`) VALUES (?, '0')", $name); - $obj->id = $db_con->lastInsertId(); - $obj->exchange_image($file); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - return $obj; - } - - /* - * Constructor: by_id - * Get image by ID. - * - * Parameters: - * $id - The ID - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `file` FROM `PREFIX_images` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Gets all images. - * - * Returns: - * Array of <Image> objects. - */ - public function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `file` FROM `PREFIX_images` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: exchange_image - * Exchanges image file. Also saves object to database. - * - * Parameters: - * $file - Location of new image.(move_uploaded_file must be able to move the file!) - * - * Throws: - * <IOError>, <UnknownFileFormat> - */ - public function exchange_image($file) - { - global $imagetype_file_extensions; - if(!is_file($file)) - throw new IOError("\"$file\" is not available"); - $imageinfo = getimagesize($file); - if($imageinfo === False) - throw new UnknownFileFormat(); - if(!isset($imagetype_file_extensions[$imageinfo[2]])) - throw new UnknownFileFormat(); - if(is_file(SITE_BASE_PATH . "/images/" . $this->file)) - unlink(SITE_BASE_PATH . "/images/" . $this->file); - $new_fn = $this->id . "." . $imagetype_file_extensions[$imageinfo[2]]; - if(!move_uploaded_file($file, SITE_BASE_PATH . "/images/" . $new_fn)) - throw new IOError("Can not move file."); - $this->file = $new_fn; - $this->save(); - - /* make preview image */ - switch($imageinfo[2]) - { - case IMAGETYPE_GIF: $img = imagecreatefromgif (SITE_BASE_PATH . "/images/" . $new_fn); break; - case IMAGETYPE_JPEG: $img = imagecreatefromjpeg(SITE_BASE_PATH . "/images/" . $new_fn); break; - case IMAGETYPE_PNG: $img = imagecreatefrompng (SITE_BASE_PATH . "/images/" . $new_fn); break; - default: $img = imagecreatetruecolor(40, 40); imagefill($img, 1, 1, imagecolorallocate($img, 127, 127, 127)); break; - } - $w_orig = imagesx($img); - $h_orig = imagesy($img); - if(($w_orig > self::$pre_maxw) or ($h_orig > self::$pre_maxh)) - { - $ratio = $w_orig / $h_orig; - if($ratio > 1) - { - $w_new = round(self::$pre_maxw); - $h_new = round(self::$pre_maxw / $ratio); - } - else - { - $h_new = round(self::$pre_maxh); - $w_new = round(self::$pre_maxh * $ratio); - } - $preview = imagecreatetruecolor($w_new, $h_new); - imagecopyresized($preview, $img, 0, 0, 0, 0, $w_new, $h_new, $w_orig, $h_orig); - imagepng($preview, SITE_BASE_PATH . "/images/previews/{$this->id}.png"); - } - else - imagepng($img, SITE_BASE_PATH . "/images/previews/{$this->id}.png"); - } - - /* - * Function: save - */ - public function save() - { - qdb("UPDATE `PREFIX_images` SET `name` = ?, `file` = ? WHERE `id` = ?", - $this->name, $this->file, $this->id); - } - - /* - * Function: delete - */ - public function delete() - { - qdb("DELETE FROM `PREFIX_images` WHERE `id` = ?", $this->id); - if(is_file(SITE_BASE_PATH . "/images/" . $this->file)) - unlink(SITE_BASE_PATH . "/images/" . $this->file); - if(is_file(SITE_BASE_PATH . "/images/previews/{$this->id}.png")) - unlink(SITE_BASE_PATH . "/images/previews/{$this->id}.png"); - } + private $id; + private $filename; + + private static $pre_maxw = 150; + private static $pre_maxh = 100; + + /* + * Variables: Public class variables + * + * $name - The image name + */ + public $name; + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->file = $sqlrow["file"]; + } + + /* + * Functions: Getters + * + * get_id - Get the ID + * get_filename - Get the filename + */ + public function get_id() { return $this->id; } + public function get_filename() { return $this->file; } + + /* + * Constructor: create + * Create a new image + * + * Parameters: + * $name - The name for the image + * $file - An uploaded image file (move_uploaded_file must be able to move the file!). + * + * Throws: + * <IOError>, <UnknownFileFormat> + */ + public static function create($name, $file) + { + $obj = new self(); + $obj->name = $name; + $obj->file = "0"; + + $tx = new Transaction(); + try + { + global $db_con; + + qdb("INSERT INTO `PREFIX_images` (`name`, `file`) VALUES (?, '0')", $name); + $obj->id = $db_con->lastInsertId(); + $obj->exchange_image($file); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + return $obj; + } + + /* + * Constructor: by_id + * Get image by ID. + * + * Parameters: + * $id - The ID + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `file` FROM `PREFIX_images` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Gets all images. + * + * Returns: + * Array of <Image> objects. + */ + public function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `file` FROM `PREFIX_images` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: exchange_image + * Exchanges image file. Also saves object to database. + * + * Parameters: + * $file - Location of new image.(move_uploaded_file must be able to move the file!) + * + * Throws: + * <IOError>, <UnknownFileFormat> + */ + public function exchange_image($file) + { + global $imagetype_file_extensions; + if(!is_file($file)) + throw new IOError("\"$file\" is not available"); + $imageinfo = getimagesize($file); + if($imageinfo === False) + throw new UnknownFileFormat(); + if(!isset($imagetype_file_extensions[$imageinfo[2]])) + throw new UnknownFileFormat(); + if(is_file(SITE_BASE_PATH . "/images/" . $this->file)) + unlink(SITE_BASE_PATH . "/images/" . $this->file); + $new_fn = $this->id . "." . $imagetype_file_extensions[$imageinfo[2]]; + if(!move_uploaded_file($file, SITE_BASE_PATH . "/images/" . $new_fn)) + throw new IOError("Can not move file."); + $this->file = $new_fn; + $this->save(); + + /* make preview image */ + switch($imageinfo[2]) + { + case IMAGETYPE_GIF: $img = imagecreatefromgif (SITE_BASE_PATH . "/images/" . $new_fn); break; + case IMAGETYPE_JPEG: $img = imagecreatefromjpeg(SITE_BASE_PATH . "/images/" . $new_fn); break; + case IMAGETYPE_PNG: $img = imagecreatefrompng (SITE_BASE_PATH . "/images/" . $new_fn); break; + default: $img = imagecreatetruecolor(40, 40); imagefill($img, 1, 1, imagecolorallocate($img, 127, 127, 127)); break; + } + $w_orig = imagesx($img); + $h_orig = imagesy($img); + if(($w_orig > self::$pre_maxw) or ($h_orig > self::$pre_maxh)) + { + $ratio = $w_orig / $h_orig; + if($ratio > 1) + { + $w_new = round(self::$pre_maxw); + $h_new = round(self::$pre_maxw / $ratio); + } + else + { + $h_new = round(self::$pre_maxh); + $w_new = round(self::$pre_maxh * $ratio); + } + $preview = imagecreatetruecolor($w_new, $h_new); + imagecopyresized($preview, $img, 0, 0, 0, 0, $w_new, $h_new, $w_orig, $h_orig); + imagepng($preview, SITE_BASE_PATH . "/images/previews/{$this->id}.png"); + } + else + imagepng($img, SITE_BASE_PATH . "/images/previews/{$this->id}.png"); + } + + /* + * Function: save + */ + public function save() + { + qdb("UPDATE `PREFIX_images` SET `name` = ?, `file` = ? WHERE `id` = ?", + $this->name, $this->file, $this->id); + } + + /* + * Function: delete + */ + public function delete() + { + qdb("DELETE FROM `PREFIX_images` WHERE `id` = ?", $this->id); + if(is_file(SITE_BASE_PATH . "/images/" . $this->file)) + unlink(SITE_BASE_PATH . "/images/" . $this->file); + if(is_file(SITE_BASE_PATH . "/images/previews/{$this->id}.png")) + unlink(SITE_BASE_PATH . "/images/previews/{$this->id}.png"); + } } /* @@ -2282,243 +2282,243 @@ class RepositoryUnreachableOrInvalid extends Exception { } */ class Repository extends BySQLRowEnabled { - private $id; - private $baseurl; - private $name; - private $description; - private $lastrefresh; - - private $stream_ctx; - - /* - * Variables: Public class variables - * $packages - Array with all packages from this repository. A entry itself is an array: array(name, versioncounter, description) - */ - public $packages; - - protected function __construct() - { - $this->stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); - } - - /* - * Functions: Getters - * get_id - Get internal ID. - * get_baseurl - Get the baseurl of the repository. - * get_name - Get repository name. - * get_description - Get repository description. - */ - public function get_id() { return $this->id; } - public function get_baseurl() { return $this->baseurl; } - public function get_name() { return $this->name; } - public function get_description() { return $this->description; } - - /* - * Constructor: create - * Create a new repository entry from a base url. - * - * Parameters: - * $baseurl - The baseurl of the repository. - * - * Throws: - * Could throw a <RepositoryUnreachableOrInvalid> exception. In this case, nothing will be written to the database. - */ - public static function create($baseurl) - { - $obj = new self(); - - if(preg_match('/^(http[s]?:\\/\\/.*?)[\\/]?$/', $baseurl, $matches) == 0) - throw new RepositoryUnreachableOrInvalid(); - - $obj->baseurl = $matches[1]; - $obj->refresh(True); - - $tx = new Transaction(); - try - { - global $db_con; - - qdb("INSERT INTO `ratatoeskr_repositories` () VALUES ()"); - $obj->id = $db_con->lastInsertId(); - $obj->save(); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - - return $obj; - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $this->name = $sqlrow["name"]; - $this->description = $sqlrow["description"]; - $this->baseurl = $sqlrow["baseurl"]; - $this->packages = unserialize(base64_decode($sqlrow["pkgcache"])); - $this->lastrefresh = $sqlrow["lastrefresh"]; - } - - /* - * Constructor: by_id - * Get a repository entry by ID. - * - * Parameters: - * $id - ID. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `name`, `description`, `baseurl`, `pkgcache`, `lastrefresh` FROM `PREFIX_repositories` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if(!$sqlrow) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: all - * Gets all available repositories. - * - * Returns: - * Array of <Repository> objects. - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `name`, `description`, `baseurl`, `pkgcache`, `lastrefresh` FROM `PREFIX_repositories` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - private function save() - { - qdb("UPDATE `PREFIX_repositories` SET `baseurl` = ?, `name` = ?, `description` = ?, `pkgcache` = ?, `lastrefresh` = ? WHERE `id` = ?", - $this->baseurl, - $this->name, - $this->description, - base64_encode(serialize($this->packages)), - $this->lastrefresh, - $this->id); - } - - /* - * Function: delete - * Delete the repository entry from the database. - */ - public function delete() - { - qdb("DELETE FROM `PREFIX_repositories` WHERE `id` = ?", $this->id); - } - - /* - * Function: refresh - * Refresh the package cache and the name and description. - * - * Parameters: - * $force - Force a refresh, even if the data was already fetched in the last 6 hours (default: False). - * - * Throws: - * <RepositoryUnreachableOrInvalid> - */ - public function refresh($force = False) - { - if(($this->lastrefresh > (time() - (60*60*4))) and (!$force)) - return; - - $repometa = @file_get_contents($this->baseurl . "/repometa", False, $this->stream_ctx); - if($repometa === FALSE) - throw new RepositoryUnreachableOrInvalid(); - $repometa = @unserialize($repometa); - if((!is_array($repometa)) or (!isset($repometa["name"])) or (!isset($repometa["description"]))) - throw new RepositoryUnreachableOrInvalid(); - - $this->name = $repometa["name"]; - $this->description = $repometa["description"]; - $this->packages = @unserialize(@file_get_contents($this->baseurl . "/packagelist", False, $ctx)); - - $this->lastrefresh = time(); - - $this->save(); - } - - /* - * Function: get_package_meta - * Get metadata of a plugin package from this repository. - * - * Parameters: - * $pkgname - The name of the package. - * - * Throws: - * A <DoesNotExistError> Exception, if the package was not found. - * - * Returns: - * A <PluginPackageMeta> object - */ - public function get_package_meta($pkgname) - { - $found = False; - foreach($this->packages as $p) - { - if($p[0] == $pkgname) - { - $found = True; - break; - } - } - if(!$found) - throw new DoesNotExistError("Package not in package cache."); - - $pkgmeta = @unserialize(@file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/meta", False, $this->stream_ctx)); - - if(!($pkgmeta instanceof PluginPackageMeta)) - throw new DoesNotExistError(); - - return $pkgmeta; - } - - /* - * Function: download_package - * Download a package from the repository - * - * Parameters: - * $pkgname - Name of the package. - * $version - The version to download (defaults to "current"). - * - * Throws: - * * A <DoesNotExistError> Exception, if the package was not found. - * * A <InvalidPackage> Exception, if the package was malformed. - * - * Returns: - * A <PluginPackage> object. - */ - public function download_package($pkgname, $version = "current") - { - $found = False; - foreach($this->packages as $p) - { - if($p[0] == $pkgname) - { - $found = True; - break; - } - } - if(!$found) - throw new DoesNotExistError("Package not in package cache."); - - $raw = @file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/versions/" . urlencode($version), False, $this->stream_ctx); - if($raw === False) - throw new DoesNotExistError(); - - return PluginPackage::load($raw); - } + private $id; + private $baseurl; + private $name; + private $description; + private $lastrefresh; + + private $stream_ctx; + + /* + * Variables: Public class variables + * $packages - Array with all packages from this repository. A entry itself is an array: array(name, versioncounter, description) + */ + public $packages; + + protected function __construct() + { + $this->stream_ctx = stream_context_create(array("http" => array("timeout" => 5))); + } + + /* + * Functions: Getters + * get_id - Get internal ID. + * get_baseurl - Get the baseurl of the repository. + * get_name - Get repository name. + * get_description - Get repository description. + */ + public function get_id() { return $this->id; } + public function get_baseurl() { return $this->baseurl; } + public function get_name() { return $this->name; } + public function get_description() { return $this->description; } + + /* + * Constructor: create + * Create a new repository entry from a base url. + * + * Parameters: + * $baseurl - The baseurl of the repository. + * + * Throws: + * Could throw a <RepositoryUnreachableOrInvalid> exception. In this case, nothing will be written to the database. + */ + public static function create($baseurl) + { + $obj = new self(); + + if(preg_match('/^(http[s]?:\\/\\/.*?)[\\/]?$/', $baseurl, $matches) == 0) + throw new RepositoryUnreachableOrInvalid(); + + $obj->baseurl = $matches[1]; + $obj->refresh(True); + + $tx = new Transaction(); + try + { + global $db_con; + + qdb("INSERT INTO `ratatoeskr_repositories` () VALUES ()"); + $obj->id = $db_con->lastInsertId(); + $obj->save(); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + + return $obj; + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $this->name = $sqlrow["name"]; + $this->description = $sqlrow["description"]; + $this->baseurl = $sqlrow["baseurl"]; + $this->packages = unserialize(base64_decode($sqlrow["pkgcache"])); + $this->lastrefresh = $sqlrow["lastrefresh"]; + } + + /* + * Constructor: by_id + * Get a repository entry by ID. + * + * Parameters: + * $id - ID. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `name`, `description`, `baseurl`, `pkgcache`, `lastrefresh` FROM `PREFIX_repositories` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if(!$sqlrow) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: all + * Gets all available repositories. + * + * Returns: + * Array of <Repository> objects. + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `name`, `description`, `baseurl`, `pkgcache`, `lastrefresh` FROM `PREFIX_repositories` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + private function save() + { + qdb("UPDATE `PREFIX_repositories` SET `baseurl` = ?, `name` = ?, `description` = ?, `pkgcache` = ?, `lastrefresh` = ? WHERE `id` = ?", + $this->baseurl, + $this->name, + $this->description, + base64_encode(serialize($this->packages)), + $this->lastrefresh, + $this->id); + } + + /* + * Function: delete + * Delete the repository entry from the database. + */ + public function delete() + { + qdb("DELETE FROM `PREFIX_repositories` WHERE `id` = ?", $this->id); + } + + /* + * Function: refresh + * Refresh the package cache and the name and description. + * + * Parameters: + * $force - Force a refresh, even if the data was already fetched in the last 6 hours (default: False). + * + * Throws: + * <RepositoryUnreachableOrInvalid> + */ + public function refresh($force = False) + { + if(($this->lastrefresh > (time() - (60*60*4))) and (!$force)) + return; + + $repometa = @file_get_contents($this->baseurl . "/repometa", False, $this->stream_ctx); + if($repometa === FALSE) + throw new RepositoryUnreachableOrInvalid(); + $repometa = @unserialize($repometa); + if((!is_array($repometa)) or (!isset($repometa["name"])) or (!isset($repometa["description"]))) + throw new RepositoryUnreachableOrInvalid(); + + $this->name = $repometa["name"]; + $this->description = $repometa["description"]; + $this->packages = @unserialize(@file_get_contents($this->baseurl . "/packagelist", False, $ctx)); + + $this->lastrefresh = time(); + + $this->save(); + } + + /* + * Function: get_package_meta + * Get metadata of a plugin package from this repository. + * + * Parameters: + * $pkgname - The name of the package. + * + * Throws: + * A <DoesNotExistError> Exception, if the package was not found. + * + * Returns: + * A <PluginPackageMeta> object + */ + public function get_package_meta($pkgname) + { + $found = False; + foreach($this->packages as $p) + { + if($p[0] == $pkgname) + { + $found = True; + break; + } + } + if(!$found) + throw new DoesNotExistError("Package not in package cache."); + + $pkgmeta = @unserialize(@file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/meta", False, $this->stream_ctx)); + + if(!($pkgmeta instanceof PluginPackageMeta)) + throw new DoesNotExistError(); + + return $pkgmeta; + } + + /* + * Function: download_package + * Download a package from the repository + * + * Parameters: + * $pkgname - Name of the package. + * $version - The version to download (defaults to "current"). + * + * Throws: + * * A <DoesNotExistError> Exception, if the package was not found. + * * A <InvalidPackage> Exception, if the package was malformed. + * + * Returns: + * A <PluginPackage> object. + */ + public function download_package($pkgname, $version = "current") + { + $found = False; + foreach($this->packages as $p) + { + if($p[0] == $pkgname) + { + $found = True; + break; + } + } + if(!$found) + throw new DoesNotExistError("Package not in package cache."); + + $raw = @file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/versions/" . urlencode($version), False, $this->stream_ctx); + if($raw === False) + throw new DoesNotExistError(); + + return PluginPackage::load($raw); + } } /* @@ -2527,508 +2527,508 @@ class Repository extends BySQLRowEnabled */ class Article extends BySQLRowEnabled { - private $id; - - private $section_id; - private $section_obj; - - /* - * Variables: Public class variables - * - * $urlname - URL name - * $title - Title (an <Multilingual> object) - * $text - The text (an <Multilingual> object) - * $excerpt - Excerpt (an <Multilingual> object) - * $meta - Keywords, comma seperated - * $custom - Custom fields, is an array - * $article_image - The article <Image>. If none: NULL - * $status - One of the ARTICLE_STATUS_* constants - * $timestamp - Timestamp - * $allow_comments - Are comments allowed? - */ - public $urlname; - public $title; - public $text; - public $excerpt; - public $meta; - public $custom; - public $article_image; - public $status; - public $timestamp; - public $allow_comments; - - protected function __construct() - { - $this->section_obj = NULL; - } - - protected function populate_by_sqlrow($sqlrow) - { - $this->id = $sqlrow["id"]; - $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"]); - $this->meta = $sqlrow["meta"]; - $this->custom = unserialize(base64_decode($sqlrow["custom"])); - $this->article_image = $sqlrow["article_image"] == 0 ? NULL : Image::by_id($sqlrow["article_image"]); - $this->status = $sqlrow["status"]; - $this->section_id = $sqlrow["section"]; - $this->timestamp = $sqlrow["timestamp"]; - $this->allow_comments = $sqlrow["allow_comments"] == 1; - } - - /* - * Function: get_id - */ - public function get_id() { return $this->id; } - - /* - * Function: test_urlname - * Test, if a urlname is a valid urlname. - * - * Parameters: - * $urlname - Urlname to test - * - * Returns: - * True, if the urlname is valid, False otherwise. - */ - public static function test_urlname($urlname) - { - return (bool) preg_match('/^[a-zA-Z0-9-_]+$/', $urlname); - } - - /* - * Function: test_status - * Test, if a status is valid. - * - * Parameters: - * $status - Status value to test. - * - * Returns: - * True, if the status is a valid status value, False otherwise. - */ - public static function test_status($status) - { - return is_numeric($status) and ($status >= 0) and ($status <= 3); - } - - /* - * Constructor: create - * Create a new Article object. - * - * Parameters: - * urlname - A unique URL name - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public static function create($urlname) - { - global $ratatoeskr_settings; - global $db_con; - - if(!self::test_urlname($urlname)) - throw new InvalidDataError("invalid_urlname"); - - 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_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 ('', ?, ?, ?, '', ?, 0, ?, ?, ?, ?)", - $obj->title->get_id(), - $obj->text->get_id(), - $obj->excerpt->get_id(), - base64_encode(serialize($obj->custom)), - $obj->status, - $obj->section_id, - $obj->timestamp, - $obj->allow_comments ? 1 : 0); - $obj->id = $db_con->lastInsertId(); - return $obj; - } - - throw new AlreadyExistsError(); - } - - /* - * Constructor: by_id - * Get by ID. - * - * Parameters: - * $id - The ID. - * - * Throws: - * <DoesNotExistError> - */ - public static function by_id($id) - { - $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `id` = ?", $id); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_urlname - * Get by urlname - * - * Parameters: - * $urlname - The urlname - * - * Throws: - * <DoesNotExistError> - */ - public static function by_urlname($urlname) - { - $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `urlname` = ?", $urlname); - $sqlrow = $stmt->fetch(); - if($sqlrow === False) - throw new DoesNotExistError(); - - return self::by_sqlrow($sqlrow); - } - - /* - * Constructor: by_multi - * Get Articles by multiple criterias - * - * Parameters: - * $criterias - Array that can have these keys: id (int) , urlname (string), section (<Section> object), status (int), onlyvisible, langavail(string), tag (<Tag> object) - * $sortby - Sort by this field (id, urlname, timestamp or title) - * $sortdir - Sorting directory (ASC or DESC) - * $count - How many entries (NULL for unlimited) - * $offset - How many entries should be skipped (NULL for none) - * $perpage - How many entries per page (NULL for no paging) - * $page - Page number (starting at 1, NULL for no paging) - * &$maxpage - Number of pages will be written here, if paging is activated. - * - * Returns: - * Array of Article objects - */ - public static function by_multi($criterias, $sortby, $sortdir, $count, $offset, $perpage, $page, &$maxpage) - { - $subqueries = array(); - $subparams = array(); - foreach($criterias as $k => $v) - { - switch($k) - { - case "id": - $subqueries[] = "`a`.`id` = ?"; - $subparams[] = $v; - break; - case "urlname": - $subqueries[] = "`a`.`urlname` = ?"; - $subparams[] = $v; - break; - case "section": - $subqueries[] = "`a`.`section` = ?"; - $subparams[] = $v->get_id(); - break; - case "status": - $subqueries[] = "`a`.`status` = ?"; - $subparams[] = $v; - break; - case "onlyvisible": - $subqueries[] = "`a`.`status` != 0"; - break; - case "langavail": - $subqueries[] = "`b`.`language` = ?"; - $subparams[] = $v; - break; - case "tag": - $subqueries[] = "`c`.`tag` = ?"; - $subparams[] = $v->get_id(); - break; - default: continue; - } - } - - if(($sortdir != "ASC") and ($sortdir != "DESC")) - $sortdir = "ASC"; - $sorting = ""; - switch($sortby) - { - case "id": $sorting = "ORDER BY `a`.`id` $sortdir"; break; - case "urlname": $sorting = "ORDER BY `a`.`urlname` $sortdir"; break; - case "timestamp": $sorting = "ORDER BY `a`.`timestamp` $sortdir"; break; - case "title": $sorting = "ORDER BY `b`.`text` $sortdir"; break; - } - - $stmt = prep_stmt("SELECT `a`.`id` AS `id`, `a`.`urlname` AS `urlname`, `a`.`title` AS `title`, `a`.`text` AS `text`, `a`.`excerpt` AS `excerpt`, `a`.`meta` AS `meta`, `a`.`custom` AS `custom`, `a`.`article_image` AS `article_image`, `a`.`status` AS `status`, `a`.`section` AS `section`, `a`.`timestamp` AS `timestamp`, `a`.`allow_comments` AS `allow_comments` FROM `PREFIX_articles` `a` + private $id; + + private $section_id; + private $section_obj; + + /* + * Variables: Public class variables + * + * $urlname - URL name + * $title - Title (an <Multilingual> object) + * $text - The text (an <Multilingual> object) + * $excerpt - Excerpt (an <Multilingual> object) + * $meta - Keywords, comma seperated + * $custom - Custom fields, is an array + * $article_image - The article <Image>. If none: NULL + * $status - One of the ARTICLE_STATUS_* constants + * $timestamp - Timestamp + * $allow_comments - Are comments allowed? + */ + public $urlname; + public $title; + public $text; + public $excerpt; + public $meta; + public $custom; + public $article_image; + public $status; + public $timestamp; + public $allow_comments; + + protected function __construct() + { + $this->section_obj = NULL; + } + + protected function populate_by_sqlrow($sqlrow) + { + $this->id = $sqlrow["id"]; + $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"]); + $this->meta = $sqlrow["meta"]; + $this->custom = unserialize(base64_decode($sqlrow["custom"])); + $this->article_image = $sqlrow["article_image"] == 0 ? NULL : Image::by_id($sqlrow["article_image"]); + $this->status = $sqlrow["status"]; + $this->section_id = $sqlrow["section"]; + $this->timestamp = $sqlrow["timestamp"]; + $this->allow_comments = $sqlrow["allow_comments"] == 1; + } + + /* + * Function: get_id + */ + public function get_id() { return $this->id; } + + /* + * Function: test_urlname + * Test, if a urlname is a valid urlname. + * + * Parameters: + * $urlname - Urlname to test + * + * Returns: + * True, if the urlname is valid, False otherwise. + */ + public static function test_urlname($urlname) + { + return (bool) preg_match('/^[a-zA-Z0-9-_]+$/', $urlname); + } + + /* + * Function: test_status + * Test, if a status is valid. + * + * Parameters: + * $status - Status value to test. + * + * Returns: + * True, if the status is a valid status value, False otherwise. + */ + public static function test_status($status) + { + return is_numeric($status) and ($status >= 0) and ($status <= 3); + } + + /* + * Constructor: create + * Create a new Article object. + * + * Parameters: + * urlname - A unique URL name + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public static function create($urlname) + { + global $ratatoeskr_settings; + global $db_con; + + if(!self::test_urlname($urlname)) + throw new InvalidDataError("invalid_urlname"); + + 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_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 ('', ?, ?, ?, '', ?, 0, ?, ?, ?, ?)", + $obj->title->get_id(), + $obj->text->get_id(), + $obj->excerpt->get_id(), + base64_encode(serialize($obj->custom)), + $obj->status, + $obj->section_id, + $obj->timestamp, + $obj->allow_comments ? 1 : 0); + $obj->id = $db_con->lastInsertId(); + return $obj; + } + + throw new AlreadyExistsError(); + } + + /* + * Constructor: by_id + * Get by ID. + * + * Parameters: + * $id - The ID. + * + * Throws: + * <DoesNotExistError> + */ + public static function by_id($id) + { + $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `id` = ?", $id); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_urlname + * Get by urlname + * + * Parameters: + * $urlname - The urlname + * + * Throws: + * <DoesNotExistError> + */ + public static function by_urlname($urlname) + { + $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE `urlname` = ?", $urlname); + $sqlrow = $stmt->fetch(); + if($sqlrow === False) + throw new DoesNotExistError(); + + return self::by_sqlrow($sqlrow); + } + + /* + * Constructor: by_multi + * Get Articles by multiple criterias + * + * Parameters: + * $criterias - Array that can have these keys: id (int) , urlname (string), section (<Section> object), status (int), onlyvisible, langavail(string), tag (<Tag> object) + * $sortby - Sort by this field (id, urlname, timestamp or title) + * $sortdir - Sorting directory (ASC or DESC) + * $count - How many entries (NULL for unlimited) + * $offset - How many entries should be skipped (NULL for none) + * $perpage - How many entries per page (NULL for no paging) + * $page - Page number (starting at 1, NULL for no paging) + * &$maxpage - Number of pages will be written here, if paging is activated. + * + * Returns: + * Array of Article objects + */ + public static function by_multi($criterias, $sortby, $sortdir, $count, $offset, $perpage, $page, &$maxpage) + { + $subqueries = array(); + $subparams = array(); + foreach($criterias as $k => $v) + { + switch($k) + { + case "id": + $subqueries[] = "`a`.`id` = ?"; + $subparams[] = $v; + break; + case "urlname": + $subqueries[] = "`a`.`urlname` = ?"; + $subparams[] = $v; + break; + case "section": + $subqueries[] = "`a`.`section` = ?"; + $subparams[] = $v->get_id(); + break; + case "status": + $subqueries[] = "`a`.`status` = ?"; + $subparams[] = $v; + break; + case "onlyvisible": + $subqueries[] = "`a`.`status` != 0"; + break; + case "langavail": + $subqueries[] = "`b`.`language` = ?"; + $subparams[] = $v; + break; + case "tag": + $subqueries[] = "`c`.`tag` = ?"; + $subparams[] = $v->get_id(); + break; + default: continue; + } + } + + if(($sortdir != "ASC") and ($sortdir != "DESC")) + $sortdir = "ASC"; + $sorting = ""; + switch($sortby) + { + case "id": $sorting = "ORDER BY `a`.`id` $sortdir"; break; + case "urlname": $sorting = "ORDER BY `a`.`urlname` $sortdir"; break; + case "timestamp": $sorting = "ORDER BY `a`.`timestamp` $sortdir"; break; + case "title": $sorting = "ORDER BY `b`.`text` $sortdir"; break; + } + + $stmt = prep_stmt("SELECT `a`.`id` AS `id`, `a`.`urlname` AS `urlname`, `a`.`title` AS `title`, `a`.`text` AS `text`, `a`.`excerpt` AS `excerpt`, `a`.`meta` AS `meta`, `a`.`custom` AS `custom`, `a`.`article_image` AS `article_image`, `a`.`status` AS `status`, `a`.`section` AS `section`, `a`.`timestamp` AS `timestamp`, `a`.`allow_comments` AS `allow_comments` FROM `PREFIX_articles` `a` INNER JOIN `PREFIX_translations` `b` ON `a`.`title` = `b`.`multilingual` LEFT OUTER JOIN `PREFIX_article_tag_relations` `c` ON `a`.`id` = `c`.`article` WHERE " . implode(" AND ", $subqueries) . " $sorting"); - - $stmt->execute($subparams); - - $rows = array(); - $fetched_ids = array(); - while($sqlrow = $stmt->fetch()) - { - if(!in_array($sqlrow["id"], $fetched_ids)) - { - $rows[] = $sqlrow; - $fetched_ids[] = $sqlrow["id"]; - } - } - - if($count !== NULL) - $rows = array_slice($rows, 0, $count); - if($offset !== NULL) - $rows = array_slice($rows, $offset); - if(($perpage !== NULL) and ($page !== NULL)) - { - $maxpage = ceil(count($rows) / $perpage); - $rows = array_slice($rows, $perpage * ($page - 1), $perpage); - } - - $rv = array(); - foreach($rows as $r) - $rv[] = self::by_sqlrow($r); - return $rv; - } - - /* - * Constructor: all - * Get all articles - * - * Returns: - * Array of Article objects - */ - public static function all() - { - $rv = array(); - $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE 1"); - while($sqlrow = $stmt->fetch()) - $rv[] = self::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: get_comments - * Getting comments for this article. - * - * Parameters: - * $limit_lang - Get only comments in a language (empty string for no limitation, this is the default). - * $only_visible - Do you only want the visible comments? (Default: False) - * - * Returns: - * Array of <Comment> objects. - */ - public function get_comments($limit_lang = "", $only_visible = False) - { - $rv = array(); - - $conditions = array("`article` = ?"); - $arguments = array($this->id); - if($limit_lang != "") - { - $conditions[] = "`language` = ?"; - $arguments[] = $limit_lang; - } - if($only_visible) - $conditions[] = "`visible` = 1"; - - $stmt = prep_stmt("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE " . implode(" AND ", $conditions)); - $stmt->execute($arguments); - while($sqlrow = $stmt->fetch()) - $rv[] = Comment::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: get_tags - * Get all Tags of this Article. - * - * Returns: - * Array of <Tag> objects. - */ - public function get_tags() - { - $rv = array(); - $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name`, `a`.`title` AS `title` FROM `PREFIX_tags` `a` INNER JOIN `PREFIX_article_tag_relations` `b` ON `a`.`id` = `b`.`tag` WHERE `b`.`article` = ?", $this->id); - while($sqlrow = $stmt->fetch()) - $rv[] = Tag::by_sqlrow($sqlrow); - return $rv; - } - - /* - * Function: set_tags - * Set the Tags that should be associated with this Article. - * - * Parameters: - * $tags - Array of <Tag> objects. - */ - public function set_tags($tags) - { - $tx = new Transaction(); - try - { - foreach($tags as $tag) - $tag->save(); - - qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `article`= ?", $this->id); - - $articleid = $this->id; - if(!empty($tags)) - { - $stmt = prep_stmt( - "INSERT INTO `PREFIX_article_tag_relations` (`article`, `tag`) VALUES " . - implode(",", array_fill(0, count($tags), "(?,?)")) - ); - $args = array(); - foreach($tags as $tag) - { - $args[] = $articleid; - $args[] = $tag->get_id(); - } - $stmt->execute($args); - } - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: get_section - * Get the section of this article. - * - * Returns: - * A <Section> object. - */ - public function get_section() - { - if($this->section_obj === NULL) - $this->section_obj = Section::by_id($this->section_id); - return $this->section_obj; - } - - /* - * Function: set_section - * Set the section of this article. - * - * Parameters: - * $section - A <Section> object. - */ - public function set_section($section) - { - $this->section_id = $section->get_id(); - $this->section_obj = $section; - } - - /* - * Function: get_extradata - * Get the extradata for this article and the given plugin. - * - * Parameters: - * $plugin_id - The ID of the plugin. - * - * Returns: - * An <ArticleExtradata> object. - */ - public function get_extradata($plugin_id) - { - return new ArticleExtradata($this->id, $plugin_id); - } - - /* - * Function: save - * - * Throws: - * <AlreadyExistsError>, <InvalidDataError> - */ - public function save() - { - if(!self::test_urlname($this->urlname)) - throw new InvalidDataError("invalid_urlname"); - - if(!self::test_status($this->status)) - throw new InvalidDataError("invalid_article_status"); - - $tx = new Transaction(); - try - { - $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_articles` WHERE `urlname` = ? AND `id` != ?", $this->urlname, $this->id); - $sqlrow = $stmt->fetch(); - if($sqlrow["n"] > 0) - throw new AlreadyExistsError(); - - $this->title->save(); - $this->text->save(); - $this->excerpt->save(); - - qdb("UPDATE `PREFIX_articles` SET `urlname` = ?, `title` = ?, `text` = ?, `excerpt` = ?, `meta` = ?, `custom` = ?, `article_image` = ?, `status` = ?, `section` = ?, `timestamp` = ?, `allow_comments` = ? WHERE `id` = ?", - $this->urlname, - $this->title->get_id(), - $this->text->get_id(), - $this->excerpt->get_id(), - $this->meta, - base64_encode(serialize($this->custom)), - $this->article_image === NULL ? 0 : $this->article_image->get_id(), - $this->status, - $this->section_id, - $this->timestamp, - $this->allow_comments ? 1 : 0, - $this->id - ); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } - - /* - * Function: delete - */ - public function delete() - { - $tx = new Transaction(); - try - { - $this->title->delete(); - $this->text->delete(); - $this->excerpt->delete(); - - foreach($this->get_comments() as $comment) - $comment->delete(); - - qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `article` = ?", $this->id); - qdb("DELETE FROM `PREFIX_article_extradata` WHERE `article` = ?", $this->id); - qdb("DELETE FROM `PREFIX_articles` WHERE `id` = ?", $this->id); - $tx->commit(); - } - catch(Exception $e) - { - $tx->rollback(); - throw $e; - } - } + + $stmt->execute($subparams); + + $rows = array(); + $fetched_ids = array(); + while($sqlrow = $stmt->fetch()) + { + if(!in_array($sqlrow["id"], $fetched_ids)) + { + $rows[] = $sqlrow; + $fetched_ids[] = $sqlrow["id"]; + } + } + + if($count !== NULL) + $rows = array_slice($rows, 0, $count); + if($offset !== NULL) + $rows = array_slice($rows, $offset); + if(($perpage !== NULL) and ($page !== NULL)) + { + $maxpage = ceil(count($rows) / $perpage); + $rows = array_slice($rows, $perpage * ($page - 1), $perpage); + } + + $rv = array(); + foreach($rows as $r) + $rv[] = self::by_sqlrow($r); + return $rv; + } + + /* + * Constructor: all + * Get all articles + * + * Returns: + * Array of Article objects + */ + public static function all() + { + $rv = array(); + $stmt = qdb("SELECT `id`, `urlname`, `title`, `text`, `excerpt`, `meta`, `custom`, `article_image`, `status`, `section`, `timestamp`, `allow_comments` FROM `PREFIX_articles` WHERE 1"); + while($sqlrow = $stmt->fetch()) + $rv[] = self::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: get_comments + * Getting comments for this article. + * + * Parameters: + * $limit_lang - Get only comments in a language (empty string for no limitation, this is the default). + * $only_visible - Do you only want the visible comments? (Default: False) + * + * Returns: + * Array of <Comment> objects. + */ + public function get_comments($limit_lang = "", $only_visible = False) + { + $rv = array(); + + $conditions = array("`article` = ?"); + $arguments = array($this->id); + if($limit_lang != "") + { + $conditions[] = "`language` = ?"; + $arguments[] = $limit_lang; + } + if($only_visible) + $conditions[] = "`visible` = 1"; + + $stmt = prep_stmt("SELECT `id`, `article`, `language`, `author_name`, `author_mail`, `text`, `timestamp`, `visible`, `read_by_admin` FROM `PREFIX_comments` WHERE " . implode(" AND ", $conditions)); + $stmt->execute($arguments); + while($sqlrow = $stmt->fetch()) + $rv[] = Comment::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: get_tags + * Get all Tags of this Article. + * + * Returns: + * Array of <Tag> objects. + */ + public function get_tags() + { + $rv = array(); + $stmt = qdb("SELECT `a`.`id` AS `id`, `a`.`name` AS `name`, `a`.`title` AS `title` FROM `PREFIX_tags` `a` INNER JOIN `PREFIX_article_tag_relations` `b` ON `a`.`id` = `b`.`tag` WHERE `b`.`article` = ?", $this->id); + while($sqlrow = $stmt->fetch()) + $rv[] = Tag::by_sqlrow($sqlrow); + return $rv; + } + + /* + * Function: set_tags + * Set the Tags that should be associated with this Article. + * + * Parameters: + * $tags - Array of <Tag> objects. + */ + public function set_tags($tags) + { + $tx = new Transaction(); + try + { + foreach($tags as $tag) + $tag->save(); + + qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `article`= ?", $this->id); + + $articleid = $this->id; + if(!empty($tags)) + { + $stmt = prep_stmt( + "INSERT INTO `PREFIX_article_tag_relations` (`article`, `tag`) VALUES " . + implode(",", array_fill(0, count($tags), "(?,?)")) + ); + $args = array(); + foreach($tags as $tag) + { + $args[] = $articleid; + $args[] = $tag->get_id(); + } + $stmt->execute($args); + } + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: get_section + * Get the section of this article. + * + * Returns: + * A <Section> object. + */ + public function get_section() + { + if($this->section_obj === NULL) + $this->section_obj = Section::by_id($this->section_id); + return $this->section_obj; + } + + /* + * Function: set_section + * Set the section of this article. + * + * Parameters: + * $section - A <Section> object. + */ + public function set_section($section) + { + $this->section_id = $section->get_id(); + $this->section_obj = $section; + } + + /* + * Function: get_extradata + * Get the extradata for this article and the given plugin. + * + * Parameters: + * $plugin_id - The ID of the plugin. + * + * Returns: + * An <ArticleExtradata> object. + */ + public function get_extradata($plugin_id) + { + return new ArticleExtradata($this->id, $plugin_id); + } + + /* + * Function: save + * + * Throws: + * <AlreadyExistsError>, <InvalidDataError> + */ + public function save() + { + if(!self::test_urlname($this->urlname)) + throw new InvalidDataError("invalid_urlname"); + + if(!self::test_status($this->status)) + throw new InvalidDataError("invalid_article_status"); + + $tx = new Transaction(); + try + { + $stmt = qdb("SELECT COUNT(*) AS `n` FROM `PREFIX_articles` WHERE `urlname` = ? AND `id` != ?", $this->urlname, $this->id); + $sqlrow = $stmt->fetch(); + if($sqlrow["n"] > 0) + throw new AlreadyExistsError(); + + $this->title->save(); + $this->text->save(); + $this->excerpt->save(); + + qdb("UPDATE `PREFIX_articles` SET `urlname` = ?, `title` = ?, `text` = ?, `excerpt` = ?, `meta` = ?, `custom` = ?, `article_image` = ?, `status` = ?, `section` = ?, `timestamp` = ?, `allow_comments` = ? WHERE `id` = ?", + $this->urlname, + $this->title->get_id(), + $this->text->get_id(), + $this->excerpt->get_id(), + $this->meta, + base64_encode(serialize($this->custom)), + $this->article_image === NULL ? 0 : $this->article_image->get_id(), + $this->status, + $this->section_id, + $this->timestamp, + $this->allow_comments ? 1 : 0, + $this->id + ); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } + + /* + * Function: delete + */ + public function delete() + { + $tx = new Transaction(); + try + { + $this->title->delete(); + $this->text->delete(); + $this->excerpt->delete(); + + foreach($this->get_comments() as $comment) + $comment->delete(); + + qdb("DELETE FROM `PREFIX_article_tag_relations` WHERE `article` = ?", $this->id); + qdb("DELETE FROM `PREFIX_article_extradata` WHERE `article` = ?", $this->id); + qdb("DELETE FROM `PREFIX_articles` WHERE `id` = ?", $this->id); + $tx->commit(); + } + catch(Exception $e) + { + $tx->rollback(); + throw $e; + } + } } /* @@ -3036,46 +3036,46 @@ WHERE " . implode(" AND ", $subqueries) . " $sorting"); * A Key-Value-Storage assigned to Articles for plugins to store additional data. * Can be accessed like an array. * Keys are strings and Values can be everything serialize() can process. - * + * * Extends the abstract <KVStorage> class. */ class ArticleExtradata extends KVStorage { - /* - * Constructor: __construct - * - * Parameters: - * $article_id - The ID of the Article. - * $plugin_id - The ID of the Plugin. - */ - public function __construct($article_id, $plugin_id) - { - $this->init("PREFIX_article_extradata", array( - "article" => $article_id, - "plugin" => $plugin_id, - )); - } + /* + * Constructor: __construct + * + * Parameters: + * $article_id - The ID of the Article. + * $plugin_id - The ID of the Plugin. + */ + public function __construct($article_id, $plugin_id) + { + $this->init("PREFIX_article_extradata", array( + "article" => $article_id, + "plugin" => $plugin_id, + )); + } } /* * Function: dbversion * Get the version of the database structure currently used. - * + * * Returns: - * The numerical version of the current database structure. + * The numerical version of the current database structure. */ function dbversion() { - /* Is the meta table present? If no, the version is 0. */ - $stmt = qdb("SELECT COUNT(*) FROM `information_schema`.`tables` WHERE `table_schema` = ? AND `table_name` = ?", - $config["mysql"]["db"], sub_prefix("PREFIX_meta")); - list($n) = $stmt->fetch(); - if($n == 0) - return 0; - - $stmt = qdb("SELECT `value` FROM `PREFIX_meta` WHERE `key` = 'dbversion'"); - $sqlrow = $stmt->fetch(); - return unserialize(base64_decode($sqlrow["value"])); + /* Is the meta table present? If no, the version is 0. */ + $stmt = qdb("SELECT COUNT(*) FROM `information_schema`.`tables` WHERE `table_schema` = ? AND `table_name` = ?", + $config["mysql"]["db"], sub_prefix("PREFIX_meta")); + list($n) = $stmt->fetch(); + if($n == 0) + return 0; + + $stmt = qdb("SELECT `value` FROM `PREFIX_meta` WHERE `key` = 'dbversion'"); + $sqlrow = $stmt->fetch(); + return unserialize(base64_decode($sqlrow["value"])); } /* @@ -3084,12 +3084,12 @@ function dbversion() */ function clean_database() { - global $ratatoeskr_settings; - if((!isset($ratatoeskr_settings["last_db_cleanup"])) or ($ratatoeskr_settings["last_db_cleanup"] < (time() - 86400))) - { - Plugin::clean_db(); - $ratatoeskr_settings["last_db_cleanup"] = time(); - } + global $ratatoeskr_settings; + if((!isset($ratatoeskr_settings["last_db_cleanup"])) or ($ratatoeskr_settings["last_db_cleanup"] < (time() - 86400))) + { + Plugin::clean_db(); + $ratatoeskr_settings["last_db_cleanup"] = time(); + } } ?> diff --git a/ratatoeskr/sys/plugin_api.php b/ratatoeskr/sys/plugin_api.php index cd3e42b..45ce957 100644 --- a/ratatoeskr/sys/plugin_api.php +++ b/ratatoeskr/sys/plugin_api.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/sys/plugin_api.php * Plugin API contains the plugin base class and other interfaces to Ratatöskr. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -30,15 +30,15 @@ $url_handlers = array(); /* master URL handler */ /* * Function: register_url_handler * Register an URL handler. See <ratatoeskr/sys/urlprocess.php> for more details. - * + * * Parameters: - * $name - The name of the new URL - * $callback - The Function to be called (see <url_process>). + * $name - The name of the new URL + * $callback - The Function to be called (see <url_process>). */ function register_url_handler($name, $callback) { - global $url_handlers; - $url_handlers[$name] = $callback; + global $url_handlers; + $url_handlers[$name] = $callback; } $pluginpages_handlers = array(); @@ -51,231 +51,231 @@ $articleeditor_plugins = array(); */ abstract class RatatoeskrPlugin { - private $id; - - /* - * Variables: Protected variables - * - * $kvstorage - The Key-Value-Storage for the Plugin. - * $ste - Access to the global STECore object. - * $rel_path_to_root - Relative URL to the root of the page. - */ - protected $kvstorage; - protected $ste; - protected $rel_path_to_root; - - /* - * Constructor: __construct - * Performing some neccessary initialisation stuff. - * If you are overwriting this function, you *really* should call parent::__construct! - * - * Parameters: - * $id - The ID of the plugin (not the name). - */ - public function __construct($id) - { - global $ste, $rel_path_to_root; - $this->id = $id; - - $this->kvstorage = new PluginKVStorage($id); - $this->ste = $ste; - $this->rel_path_to_root = $rel_path_to_root; - } - - /* - * Functions: Some getters - * - * get_id - get the Plugin-ID - * get_custompriv_dir - Get path to the custompriv directory of your plugin. - * get_custompub_dir - Get path to the custompub directory of your plugin. - * get_custompub_url - Get URL (can be accessed from the web) to the custompub directory of your plugin. - * get_template_dir - Get path to your template directory to be used with STE. - */ - final public function get_id() { return $this->id; } - final protected function get_custompriv_dir() { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id; } - final protected function get_custompub_dir() { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id; } - final protected function get_custompub_url() { return $GLOBALS["rel_path_to_root"] . "/ratatoeskr/plugin_extradata/public/" . $this->id; } - final protected function get_template_dir() { return "/plugintemplates/" . $this->id; } - - /* - * Function: register_url_handler - * Register a URL handler - * - * Parameters: - * $name - Name of URL - * $fx - The function. - */ - final protected function register_url_handler($name, $fx) - { - register_url_handler($name, $fx); - } - - /* - * Function: register_ste_tag - * Register a custom STE tag. - * - * Parameters: - * $name - Name of your new STE tag. - * $fx - Function to register with this tag. - */ - final protected function register_ste_tag($name, $fx) - { - $this->ste->register_tag($name, $fx); - } - - /* - * Function: register_textprocessor - * Register a textprocessor. - * - * Parameters: - * $name - The name of the textprocessor- - * $fx - Function to register (function($input), returns HTML). - * $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True. - */ - final protected function register_textprocessor($name, $fx, $visible_in_backend=True) - { - textprocessor_register($name, $fx, $visible_in_backend); - } - - /* - * Function: register_comment_validator - * Register a comment validator. - * - * A comment validator is a function, that checks the $_POST fields and decides whether a comment should be stored or not (throws an <CommentRejected> exception with the rejection reason as the message). - * - * Parameters: - * $fx - Validator function. - */ - final protected function register_comment_validator($fx) - { - global $comment_validators; - $comment_validators[] = $fx; - } - /* - * Function: register_on_comment_store - * Register a function that will be called, after a comment was saved. - * - * Parameters: - * $fx - Function, that accepts one parameter (a <Comment> object). - */ - final protected function register_on_comment_store($fx) - { - global $on_comment_store; - $on_comment_store[] = $fx; - } - - /* - * Function: register_backend_pluginpage - * Register a backend subpage for your plugin. - * - * Parameters: - * $label - The label for the page. - * $fx - A function for <url_process>. - * - * Your $fx should output output the result of a STE template, which should load "/systemtemplates/master.html" and overwrite the "content" section. - * - * If you need a URL to your pluginpage, you can use <get_backend_pluginpage_url> and the STE variable $rel_path_to_pluginpage. - * - * See also: - * <prepare_backend_pluginpage> - */ - final protected function register_backend_pluginpage($label, $fx) - { - global $pluginpages_handlers; - - $this->ste->vars["pluginpages"][$this->id] = $label; - asort($this->ste->vars["pluginpages"]); - $pluginid = $this->id; - $pluginpages_handlers["p{$this->id}"] = function(&$data, $url_now, &$url_next) use($pluginid, $fx) - { - global $ste, $rel_path_to_root; - $ste->vars["rel_path_to_pluginpage"] = "$rel_path_to_root/backend/pluginpages/p$pluginid"; - $rv = call_user_func_array($fx, array(&$data, $url_now, &$url_next)); - unset($ste->vars["rel_path_to_pluginpage"]); - return $rv; - }; - } - - /* - * Function: register_articleeditor_plugin - * Register a plugin for the article editor in the backend. - * - * Parameters: - * $label - The label for the plugin. - * $fx - A function that will be called during the articleeditor. - * This function must accept these parameters: - * * $article - An <Article> object or NULL, if no Article is edited right now. - * * $about_to_save - If True, the article is about to be saved. - * If you want to veto the saving, return the rejection reason as a string. - * If everything is okay and you need to save additional data, return a callback function that accepts the saved <Article> object (that callback should also write data back to the template, if necessary). - * If everything is okay and you do not need to save additional data, return NULL. - * $template - The name of the template to display in the editor, relative to your template directory. If you do not want to display anything, you can set ths to NULL. - */ - final protected function register_articleeditor_plugin($label, $fx, $template) - { - global $articleeditor_plugins; - - $articleeditor_plugins[] = array( - "label" => $label, - "fx" => $fx, - "template" => $this->get_template_dir() . "/" . $template, - "display" => $template != NULL - ); - } - - /* - * Function: get_backend_pluginpage_url - * Get the URL to your backend plugin page. - * - * Returns: - * The URL to your backend plugin page. - */ - final protected function get_backend_pluginpage_url() - { - global $rel_path_to_root; - return "$rel_path_to_root/backend/pluginpages/p{$this->id}"; - } - - /* - * Function: get_article_extradata - * Get the <ArticleExtradata> object for this plugin and the given article. - * - * Parameters: - * $article - An <Article> object. - * - * Returns: - * An <ArticleExtradata> object for this plugin and the given article. - */ - final protected function get_article_extradata($article) - { - return new ArticleExtradata($article->get_id(), $this->id); - } - - /* - * Function: prepare_backend_pluginpage - * Automatically sets the page title and highlights the menu-entry of your backend subpage. - */ - final protected function prepare_backend_pluginpage() - { - $this->ste->vars["section"] = "plugins"; - $this->ste->vars["submenu"] = "plugin" . $this->id; - $this->ste->vars["pagetitle"] = $this->ste->vars["pluginpages"][$this->id]; - } - - /* - * Functions: Functions that are called at special events - * - * init - Will be called after plugin is loaded. You should register your stuff here. - * atexit - Will be called, when Ratatöskr will exit. - * install - Will be called after installation. If your plugin needs to initialize some database stuff or generate files, this is the right function. - * uninstall - Will be called during uninstallation. If you used the install function you should undo your custom installation stuff. - * update - Will be called after your plugin was updated to a new version. - */ - public function init() {} - public function atexit() {} - public function install() {} - public function uninstall() {} - public function update() {} + private $id; + + /* + * Variables: Protected variables + * + * $kvstorage - The Key-Value-Storage for the Plugin. + * $ste - Access to the global STECore object. + * $rel_path_to_root - Relative URL to the root of the page. + */ + protected $kvstorage; + protected $ste; + protected $rel_path_to_root; + + /* + * Constructor: __construct + * Performing some neccessary initialisation stuff. + * If you are overwriting this function, you *really* should call parent::__construct! + * + * Parameters: + * $id - The ID of the plugin (not the name). + */ + public function __construct($id) + { + global $ste, $rel_path_to_root; + $this->id = $id; + + $this->kvstorage = new PluginKVStorage($id); + $this->ste = $ste; + $this->rel_path_to_root = $rel_path_to_root; + } + + /* + * Functions: Some getters + * + * get_id - get the Plugin-ID + * get_custompriv_dir - Get path to the custompriv directory of your plugin. + * get_custompub_dir - Get path to the custompub directory of your plugin. + * get_custompub_url - Get URL (can be accessed from the web) to the custompub directory of your plugin. + * get_template_dir - Get path to your template directory to be used with STE. + */ + final public function get_id() { return $this->id; } + final protected function get_custompriv_dir() { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id; } + final protected function get_custompub_dir() { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id; } + final protected function get_custompub_url() { return $GLOBALS["rel_path_to_root"] . "/ratatoeskr/plugin_extradata/public/" . $this->id; } + final protected function get_template_dir() { return "/plugintemplates/" . $this->id; } + + /* + * Function: register_url_handler + * Register a URL handler + * + * Parameters: + * $name - Name of URL + * $fx - The function. + */ + final protected function register_url_handler($name, $fx) + { + register_url_handler($name, $fx); + } + + /* + * Function: register_ste_tag + * Register a custom STE tag. + * + * Parameters: + * $name - Name of your new STE tag. + * $fx - Function to register with this tag. + */ + final protected function register_ste_tag($name, $fx) + { + $this->ste->register_tag($name, $fx); + } + + /* + * Function: register_textprocessor + * Register a textprocessor. + * + * Parameters: + * $name - The name of the textprocessor- + * $fx - Function to register (function($input), returns HTML). + * $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True. + */ + final protected function register_textprocessor($name, $fx, $visible_in_backend=True) + { + textprocessor_register($name, $fx, $visible_in_backend); + } + + /* + * Function: register_comment_validator + * Register a comment validator. + * + * A comment validator is a function, that checks the $_POST fields and decides whether a comment should be stored or not (throws an <CommentRejected> exception with the rejection reason as the message). + * + * Parameters: + * $fx - Validator function. + */ + final protected function register_comment_validator($fx) + { + global $comment_validators; + $comment_validators[] = $fx; + } + /* + * Function: register_on_comment_store + * Register a function that will be called, after a comment was saved. + * + * Parameters: + * $fx - Function, that accepts one parameter (a <Comment> object). + */ + final protected function register_on_comment_store($fx) + { + global $on_comment_store; + $on_comment_store[] = $fx; + } + + /* + * Function: register_backend_pluginpage + * Register a backend subpage for your plugin. + * + * Parameters: + * $label - The label for the page. + * $fx - A function for <url_process>. + * + * Your $fx should output output the result of a STE template, which should load "/systemtemplates/master.html" and overwrite the "content" section. + * + * If you need a URL to your pluginpage, you can use <get_backend_pluginpage_url> and the STE variable $rel_path_to_pluginpage. + * + * See also: + * <prepare_backend_pluginpage> + */ + final protected function register_backend_pluginpage($label, $fx) + { + global $pluginpages_handlers; + + $this->ste->vars["pluginpages"][$this->id] = $label; + asort($this->ste->vars["pluginpages"]); + $pluginid = $this->id; + $pluginpages_handlers["p{$this->id}"] = function(&$data, $url_now, &$url_next) use($pluginid, $fx) + { + global $ste, $rel_path_to_root; + $ste->vars["rel_path_to_pluginpage"] = "$rel_path_to_root/backend/pluginpages/p$pluginid"; + $rv = call_user_func_array($fx, array(&$data, $url_now, &$url_next)); + unset($ste->vars["rel_path_to_pluginpage"]); + return $rv; + }; + } + + /* + * Function: register_articleeditor_plugin + * Register a plugin for the article editor in the backend. + * + * Parameters: + * $label - The label for the plugin. + * $fx - A function that will be called during the articleeditor. + * This function must accept these parameters: + * * $article - An <Article> object or NULL, if no Article is edited right now. + * * $about_to_save - If True, the article is about to be saved. + * If you want to veto the saving, return the rejection reason as a string. + * If everything is okay and you need to save additional data, return a callback function that accepts the saved <Article> object (that callback should also write data back to the template, if necessary). + * If everything is okay and you do not need to save additional data, return NULL. + * $template - The name of the template to display in the editor, relative to your template directory. If you do not want to display anything, you can set ths to NULL. + */ + final protected function register_articleeditor_plugin($label, $fx, $template) + { + global $articleeditor_plugins; + + $articleeditor_plugins[] = array( + "label" => $label, + "fx" => $fx, + "template" => $this->get_template_dir() . "/" . $template, + "display" => $template != NULL + ); + } + + /* + * Function: get_backend_pluginpage_url + * Get the URL to your backend plugin page. + * + * Returns: + * The URL to your backend plugin page. + */ + final protected function get_backend_pluginpage_url() + { + global $rel_path_to_root; + return "$rel_path_to_root/backend/pluginpages/p{$this->id}"; + } + + /* + * Function: get_article_extradata + * Get the <ArticleExtradata> object for this plugin and the given article. + * + * Parameters: + * $article - An <Article> object. + * + * Returns: + * An <ArticleExtradata> object for this plugin and the given article. + */ + final protected function get_article_extradata($article) + { + return new ArticleExtradata($article->get_id(), $this->id); + } + + /* + * Function: prepare_backend_pluginpage + * Automatically sets the page title and highlights the menu-entry of your backend subpage. + */ + final protected function prepare_backend_pluginpage() + { + $this->ste->vars["section"] = "plugins"; + $this->ste->vars["submenu"] = "plugin" . $this->id; + $this->ste->vars["pagetitle"] = $this->ste->vars["pluginpages"][$this->id]; + } + + /* + * Functions: Functions that are called at special events + * + * init - Will be called after plugin is loaded. You should register your stuff here. + * atexit - Will be called, when Ratatöskr will exit. + * install - Will be called after installation. If your plugin needs to initialize some database stuff or generate files, this is the right function. + * uninstall - Will be called during uninstallation. If you used the install function you should undo your custom installation stuff. + * update - Will be called after your plugin was updated to a new version. + */ + public function init() {} + public function atexit() {} + public function install() {} + public function uninstall() {} + public function update() {} } ?> diff --git a/ratatoeskr/sys/pluginpackage.php b/ratatoeskr/sys/pluginpackage.php index 863df71..5365e48 100644 --- a/ratatoeskr/sys/pluginpackage.php +++ b/ratatoeskr/sys/pluginpackage.php @@ -3,7 +3,7 @@ /* * File: ratatoeskr/sys/pluginpackage.php * Handle plugin packages easily. - * + * * License: * This file is part of Ratatöskr. * Unlike the other parts of Ratatöskr, *this* file ist *not* licensed under the @@ -15,68 +15,68 @@ /* * Function: dir2array * Pack a directory into an array. - * + * * Parameters: - * $dir - The directory to pack. - * + * $dir - The directory to pack. + * * Returns: - * Associative array. Keys are filenames, values are either the file's content as a string or another array, if it's a directory. + * Associative array. Keys are filenames, values are either the file's content as a string or another array, if it's a directory. */ function dir2array($dir) { - $rv = array(); - foreach(scandir($dir) as $fn) - { - if(($fn == ".") or ($fn == "..")) - continue; - $fn_new = $dir . "/" . $fn; - if(is_dir($fn_new)) - $rv[$fn] = dir2array($fn_new); - elseif(is_file($fn_new)) - $rv[$fn] = file_get_contents($fn_new); - } - return $rv; + $rv = array(); + foreach(scandir($dir) as $fn) + { + if(($fn == ".") or ($fn == "..")) + continue; + $fn_new = $dir . "/" . $fn; + if(is_dir($fn_new)) + $rv[$fn] = dir2array($fn_new); + elseif(is_file($fn_new)) + $rv[$fn] = file_get_contents($fn_new); + } + return $rv; } /* * Function: array2dir * Unpack an array into a directory. - * + * * Parameters: - * $a - Array to unpack. - * $dir - Directory to unpack to. + * $a - Array to unpack. + * $dir - Directory to unpack to. */ function array2dir($a, $dir) { - if(!is_dir($dir)) - mkdir($dir); - - foreach($a as $k => $v) - { - $k = "$dir/$k"; - if(is_array($v)) - array2dir($v, $k); - else - file_put_contents($k, $v); - } + if(!is_dir($dir)) + mkdir($dir); + + foreach($a as $k => $v) + { + $k = "$dir/$k"; + if(is_array($v)) + array2dir($v, $k); + else + file_put_contents($k, $v); + } } function validate_url ($u) { return preg_match("/^http[s]{0,1}:\\/\\/.*$/", $u) != 0; } function validate_arraydir($a) { - if(!is_array($a)) - return False; - foreach($a as $k=>$v) - { - if(!is_string($k)) - return False; - if(is_array($v) and (!validate_arraydir($v))) - return False; - elseif(!is_string($v)) - return False; - } - return True; -} + if(!is_array($a)) + return False; + foreach($a as $k=>$v) + { + if(!is_string($k)) + return False; + if(is_array($v) and (!validate_arraydir($v))) + return False; + elseif(!is_string($v)) + return False; + } + return True; +} /* * Class: InvalidPackage @@ -90,164 +90,164 @@ class InvalidPackage extends Exception {} */ class PluginPackage { - public static $magic = "R7RPLGPACKV001"; - - /* - * Variables: Mandatory values - * - * $code - The plugin code - * $classname - The name of the plugins main class - * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _) - * $author - The author of the plugin (preferably in the format: Name<mail@address>) - * $versiontext - A text to describe the current version, something like "1.1 Beta" - * $versioncount - A number for this version, should be increased with every release - * $api - The used API version - * $short_description - A short description. - */ - public $code = NULL; - public $classname = NULL; - public $name = NULL; - public $author = NULL; - public $versiontext = NULL; - public $versioncount = NULL; - public $api = NULL; - public $short_description = NULL; - - /* - * Variables: Optional values - * - * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software. - * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin. - * $license - The license text of your plugin. - * $help - A help / manual (formatted in HTML) for your plugin. - * $custompub - <dir2array> 'd directory that contains custom public(i.e. can later be accessed from the web) data. - * $custompriv - <dir2array> 'd directory that contains custom private data. - * $tpls - <dir2array> 'd directory containing custom STE templates. - */ - public $updatepath = NULL; - public $web = NULL; - public $license = NULL; - public $help = NULL; - public $custompub = NULL; - public $custompriv = NULL; - public $tpls = NULL; - - /* - * Function: validate - * Validate, if the variables are set correctly. - * Will throw an <InvalidPackage> exception if invalid. - */ - public function validate() - { - if(!is_string($this->code)) - throw new InvalidPackage("Invalid code value."); - if(!is_string($this->classname)) - throw new InvalidPackage("Invalid classname value."); - if(preg_match("/^[a-zA-Z0-9_\\-]+$/", $this->name) == 0) - throw new InvalidPackage("Invalid name value (must be at least 1 character, accepted chars: a-z A-Z 0-9 - _)."); - if(!is_string($this->author)) - throw new InvalidPackage("Invalid author value."); - if(!is_string($this->versiontext)) - throw new InvalidPackage("Invalid versiontext value."); - if(!is_numeric($this->versioncount)) - throw new InvalidPackage("Invalid versioncount value. Must be a number."); - if(!is_numeric($this->api)) - throw new InvalidPackage("Invalid api value. Must be a number."); - if(!is_string($this->short_description)) - throw new InvalidPackage("Invalid short_description value."); - - if((!empty($this->updatepath)) and (!validate_url($this->updatepath))) - throw new InvalidPackage("Invalid updatepath value. Must be an URL. " .$this->updatepath); - if((!empty($this->web)) and (!validate_url($this->web))) - throw new InvalidPackage("Invalid web value. Must be an URL."); - if(($this->license !== NULL) and (!is_string($this->license))) - throw new InvalidPackage("Invalid license value."); - if(($this->help !== NULL) and (!is_string($this->help))) - throw new InvalidPackage("Invalid help value."); - if(($this->custompub !== NULL) and (!validate_arraydir($this->custompub))) - throw new InvalidPackage("Invalid custompub value."); - if(($this->custompriv !== NULL) and (!validate_arraydir($this->custompriv))) - throw new InvalidPackage("Invalid custompriv value."); - if(($this->tpls !== NULL) and (!validate_arraydir($this->tpls))) - throw new InvalidPackage("Invalid tpls value."); - return True; - } - - /* - * Function: load - * Load a plugin package from binary data. - * - * Parameters: - * $plugin_raw - The raw package to load. - * - * Returns: - * The <PluginPackage> object. - * - * Throws: - * <InvalidPackage> if package is invalid. - */ - public static function load($plugin_raw) - { - /* Read and compare magic number */ - $magic = substr($plugin_raw, 0, strlen(self::$magic)); - if($magic != self::$magic) - throw new InvalidPackage("Wrong magic number"); - - /* Read sha1sum and uncompress serialized plugin, then compare the hash */ - $sha1sum = substr($plugin_raw, strlen(self::$magic), 20); - $pluginser = gzuncompress(substr($plugin_raw, strlen(self::$magic) + 20)); - if(sha1($pluginser, True) != $sha1sum) - throw new InvalidPackage("Wrong SHA1 hash"); - - $plugin = @unserialize($pluginser); - if(!($plugin instanceof self)) - throw new InvalidPackage("Not the correct class or not unserializeable."); - - $plugin->validate(); - - return $plugin; - } - - /* - * Function: save - * Save the plugin. - * - * Returns: - * A binary plugin package. - * - * Throws: - * <InvalidPackage> if package is invalid. - */ - public function save() - { - $this->validate(); - $ser = serialize($this); - return self::$magic . sha1($ser, True) . gzcompress($ser, 9); - } - - /* - * Function: extract_meta - * Get just the metadata of this package. - * - * Returns: - * A <PluginPackageMeta> object. - */ - public function extract_meta() - { - $meta = new PluginPackageMeta(); - - $meta->name = $this->name; - $meta->author = $this->author; - $meta->versiontext = $this->versiontext; - $meta->versioncount = $this->versioncount; - $meta->api = $this->api; - $meta->short_description = $this->short_description; - $meta->updatepath = $this->updatepath; - $meta->web = $this->web; - $meta->license = $this->license; - - return $meta; - } + public static $magic = "R7RPLGPACKV001"; + + /* + * Variables: Mandatory values + * + * $code - The plugin code + * $classname - The name of the plugins main class + * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _) + * $author - The author of the plugin (preferably in the format: Name<mail@address>) + * $versiontext - A text to describe the current version, something like "1.1 Beta" + * $versioncount - A number for this version, should be increased with every release + * $api - The used API version + * $short_description - A short description. + */ + public $code = NULL; + public $classname = NULL; + public $name = NULL; + public $author = NULL; + public $versiontext = NULL; + public $versioncount = NULL; + public $api = NULL; + public $short_description = NULL; + + /* + * Variables: Optional values + * + * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software. + * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin. + * $license - The license text of your plugin. + * $help - A help / manual (formatted in HTML) for your plugin. + * $custompub - <dir2array> 'd directory that contains custom public(i.e. can later be accessed from the web) data. + * $custompriv - <dir2array> 'd directory that contains custom private data. + * $tpls - <dir2array> 'd directory containing custom STE templates. + */ + public $updatepath = NULL; + public $web = NULL; + public $license = NULL; + public $help = NULL; + public $custompub = NULL; + public $custompriv = NULL; + public $tpls = NULL; + + /* + * Function: validate + * Validate, if the variables are set correctly. + * Will throw an <InvalidPackage> exception if invalid. + */ + public function validate() + { + if(!is_string($this->code)) + throw new InvalidPackage("Invalid code value."); + if(!is_string($this->classname)) + throw new InvalidPackage("Invalid classname value."); + if(preg_match("/^[a-zA-Z0-9_\\-]+$/", $this->name) == 0) + throw new InvalidPackage("Invalid name value (must be at least 1 character, accepted chars: a-z A-Z 0-9 - _)."); + if(!is_string($this->author)) + throw new InvalidPackage("Invalid author value."); + if(!is_string($this->versiontext)) + throw new InvalidPackage("Invalid versiontext value."); + if(!is_numeric($this->versioncount)) + throw new InvalidPackage("Invalid versioncount value. Must be a number."); + if(!is_numeric($this->api)) + throw new InvalidPackage("Invalid api value. Must be a number."); + if(!is_string($this->short_description)) + throw new InvalidPackage("Invalid short_description value."); + + if((!empty($this->updatepath)) and (!validate_url($this->updatepath))) + throw new InvalidPackage("Invalid updatepath value. Must be an URL. " .$this->updatepath); + if((!empty($this->web)) and (!validate_url($this->web))) + throw new InvalidPackage("Invalid web value. Must be an URL."); + if(($this->license !== NULL) and (!is_string($this->license))) + throw new InvalidPackage("Invalid license value."); + if(($this->help !== NULL) and (!is_string($this->help))) + throw new InvalidPackage("Invalid help value."); + if(($this->custompub !== NULL) and (!validate_arraydir($this->custompub))) + throw new InvalidPackage("Invalid custompub value."); + if(($this->custompriv !== NULL) and (!validate_arraydir($this->custompriv))) + throw new InvalidPackage("Invalid custompriv value."); + if(($this->tpls !== NULL) and (!validate_arraydir($this->tpls))) + throw new InvalidPackage("Invalid tpls value."); + return True; + } + + /* + * Function: load + * Load a plugin package from binary data. + * + * Parameters: + * $plugin_raw - The raw package to load. + * + * Returns: + * The <PluginPackage> object. + * + * Throws: + * <InvalidPackage> if package is invalid. + */ + public static function load($plugin_raw) + { + /* Read and compare magic number */ + $magic = substr($plugin_raw, 0, strlen(self::$magic)); + if($magic != self::$magic) + throw new InvalidPackage("Wrong magic number"); + + /* Read sha1sum and uncompress serialized plugin, then compare the hash */ + $sha1sum = substr($plugin_raw, strlen(self::$magic), 20); + $pluginser = gzuncompress(substr($plugin_raw, strlen(self::$magic) + 20)); + if(sha1($pluginser, True) != $sha1sum) + throw new InvalidPackage("Wrong SHA1 hash"); + + $plugin = @unserialize($pluginser); + if(!($plugin instanceof self)) + throw new InvalidPackage("Not the correct class or not unserializeable."); + + $plugin->validate(); + + return $plugin; + } + + /* + * Function: save + * Save the plugin. + * + * Returns: + * A binary plugin package. + * + * Throws: + * <InvalidPackage> if package is invalid. + */ + public function save() + { + $this->validate(); + $ser = serialize($this); + return self::$magic . sha1($ser, True) . gzcompress($ser, 9); + } + + /* + * Function: extract_meta + * Get just the metadata of this package. + * + * Returns: + * A <PluginPackageMeta> object. + */ + public function extract_meta() + { + $meta = new PluginPackageMeta(); + + $meta->name = $this->name; + $meta->author = $this->author; + $meta->versiontext = $this->versiontext; + $meta->versioncount = $this->versioncount; + $meta->api = $this->api; + $meta->short_description = $this->short_description; + $meta->updatepath = $this->updatepath; + $meta->web = $this->web; + $meta->license = $this->license; + + return $meta; + } } /* @@ -256,33 +256,33 @@ class PluginPackage */ class PluginPackageMeta { - /* - * Variables: Mandatory values - * - * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _) - * $author - The author of the plugin (preferably in the format: Name<mail@address>) - * $versiontext - A text to describe the current version, something like "1.1 Beta" - * $versioncount - A number for this version, should be increased with every release - * $api - The used API version - * $short_description - A short description. - */ - public $name = NULL; - public $author = NULL; - public $versiontext = NULL; - public $versioncount = NULL; - public $api = NULL; - public $short_description = NULL; - - /* - * Variables: Optional values - * - * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software. - * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin. - * $license - The license text of your plugin. - */ - public $updatepath = NULL; - public $web = NULL; - public $license = NULL; + /* + * Variables: Mandatory values + * + * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _) + * $author - The author of the plugin (preferably in the format: Name<mail@address>) + * $versiontext - A text to describe the current version, something like "1.1 Beta" + * $versioncount - A number for this version, should be increased with every release + * $api - The used API version + * $short_description - A short description. + */ + public $name = NULL; + public $author = NULL; + public $versiontext = NULL; + public $versioncount = NULL; + public $api = NULL; + public $short_description = NULL; + + /* + * Variables: Optional values + * + * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software. + * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin. + * $license - The license text of your plugin. + */ + public $updatepath = NULL; + public $web = NULL; + public $license = NULL; } ?> diff --git a/ratatoeskr/sys/pwhash.php b/ratatoeskr/sys/pwhash.php index 8ec4762..5f31dbb 100644 --- a/ratatoeskr/sys/pwhash.php +++ b/ratatoeskr/sys/pwhash.php @@ -1,9 +1,9 @@ <?php /* * File: ratatoeskr/sys/pwhash.php - * + * * Hashing passwords - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -14,61 +14,61 @@ * Class: PasswordHash * Contains static functions for password hashes. * Is just used as a namespace, can not be created. - * + * * It should be fairly difficult to break these salted hashes via bruteforce attacks. */ class PasswordHash { - private function __construct() {} /* Prevent construction */ - - private static $saltlen_min = 20; - private static $saltlen_max = 30; - private static $iterations_min = 200; - private static $iterations_max = 1000; - - private static function hash($data, $salt, $iterations) - { - $hash = $data . $salt; - for($i = $iterations ;$i--;) - $hash = sha1($data . $hash . $salt, (bool) $i); - return $iterations . '$' . bin2hex($salt) . '$' . $hash; - } - - /* - * Function: create - * Create a password hash string. - * - * Parameters: - * $password - The password (or other data) to hash. - * - * Returns: - * The salted hash as a string. - */ - public static function create($password) - { - $salt = ""; - $saltlen = mt_rand(self::$saltlen_min, self::$saltlen_max); - for($i = 0; $i < $saltlen; $i++) - $salt .= chr(mt_rand(0,255)); - return self::hash($password, $salt, mt_rand(self::$iterations_min, self::$iterations_max)); - } - - /* - * Function: validate - * Validate a salted hash. - * - * Parameters: - * $password - The password to test. - * $pwhash - The hash to test against. - * - * Returns: - * True, if $password was correct, False otherwise. - */ - public static function validate($password, $pwhash) - { - list($iterations, $hexsalt, $hash) = explode('$', $pwhash); - return self::hash($password, pack("H*", $hexsalt), $iterations) == $pwhash; - } + private function __construct() {} /* Prevent construction */ + + private static $saltlen_min = 20; + private static $saltlen_max = 30; + private static $iterations_min = 200; + private static $iterations_max = 1000; + + private static function hash($data, $salt, $iterations) + { + $hash = $data . $salt; + for($i = $iterations ;$i--;) + $hash = sha1($data . $hash . $salt, (bool) $i); + return $iterations . '$' . bin2hex($salt) . '$' . $hash; + } + + /* + * Function: create + * Create a password hash string. + * + * Parameters: + * $password - The password (or other data) to hash. + * + * Returns: + * The salted hash as a string. + */ + public static function create($password) + { + $salt = ""; + $saltlen = mt_rand(self::$saltlen_min, self::$saltlen_max); + for($i = 0; $i < $saltlen; $i++) + $salt .= chr(mt_rand(0,255)); + return self::hash($password, $salt, mt_rand(self::$iterations_min, self::$iterations_max)); + } + + /* + * Function: validate + * Validate a salted hash. + * + * Parameters: + * $password - The password to test. + * $pwhash - The hash to test against. + * + * Returns: + * True, if $password was correct, False otherwise. + */ + public static function validate($password, $pwhash) + { + list($iterations, $hexsalt, $hash) = explode('$', $pwhash); + return self::hash($password, pack("H*", $hexsalt), $iterations) == $pwhash; + } } ?> diff --git a/ratatoeskr/sys/textprocessors.php b/ratatoeskr/sys/textprocessors.php index ea6fb82..f5281bf 100644 --- a/ratatoeskr/sys/textprocessors.php +++ b/ratatoeskr/sys/textprocessors.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/sys/textprocessors.php * Manage text processors (functions that transform text to HTML) and implement some default ones. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -15,64 +15,64 @@ require_once(dirname(__FILE__) . "/utils.php"); /* * Function: textprocessor_register * Register a textprocessor. - * + * * Parameters: - * $name - The name of the textprocessor - * $fx - The textprocessor function (function($input), returns HTML) - * $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True. + * $name - The name of the textprocessor + * $fx - The textprocessor function (function($input), returns HTML) + * $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True. */ function textprocessor_register($name, $fx, $visible_in_backend=True) { - global $textprocessors; - $textprocessors[$name] = array($fx, $visible_in_backend); + global $textprocessors; + $textprocessors[$name] = array($fx, $visible_in_backend); } /* * Function: textprocessor_apply * Apply a textprocessor on a text. - * + * * Parameters: - * $text - The input text. - * $textprocessor - The name of the textprocessor. - * + * $text - The input text. + * $textprocessor - The name of the textprocessor. + * * Returns: - * HTML + * HTML */ function textprocessor_apply($text, $textprocessor) { - global $textprocessors; - if(!isset($textprocessors[$textprocessor])) - throw new Exception("Unknown Textprocessor: $textprocessor"); - - $fx = @$textprocessors[$textprocessor][0]; - if(!is_callable($fx)) - throw new Exception("Invalid Textprocessor: $textprocessor"); - - return call_user_func($fx, $text); + global $textprocessors; + if(!isset($textprocessors[$textprocessor])) + throw new Exception("Unknown Textprocessor: $textprocessor"); + + $fx = @$textprocessors[$textprocessor][0]; + if(!is_callable($fx)) + throw new Exception("Invalid Textprocessor: $textprocessor"); + + return call_user_func($fx, $text); } /* * Function: textprocessor_apply_translation * Applys a textprocessor automatically on a <Translation> object. The used textprocessor is determined by the $texttype property. - * + * * Parameters: - * $translationobj - The <Translation> object. - * + * $translationobj - The <Translation> object. + * * Returns: - * HTML + * HTML */ function textprocessor_apply_translation($translationobj) { - return textprocessor_apply($translationobj->text, $translationobj->texttype); + return textprocessor_apply($translationobj->text, $translationobj->texttype); } if(!isset($textprocessors)) { - $textprocessors = array( - "Markdown" => array("Markdown", True), - "Plain Text" => array(function($text) { return str_replace(array("\r\n", "\n"), array("<br />", "<br />"), htmlesc($text)); }, True), - "HTML" => array(function($text) { return $text; }, True) - ); + $textprocessors = array( + "Markdown" => array("Markdown", True), + "Plain Text" => array(function($text) { return str_replace(array("\r\n", "\n"), array("<br />", "<br />"), htmlesc($text)); }, True), + "HTML" => array(function($text) { return $text; }, True) + ); } ?> diff --git a/ratatoeskr/sys/translation.php b/ratatoeskr/sys/translation.php index 1104bdb..4ca6ec8 100644 --- a/ratatoeskr/sys/translation.php +++ b/ratatoeskr/sys/translation.php @@ -2,7 +2,7 @@ /* * File: ratatoeskr/sys/translation.php * Load translation. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -13,55 +13,55 @@ require_once(dirname(__FILE__) . "/utils.php"); require_once(dirname(__FILE__) . "/init_ste.php"); if(!defined("SETUP")) - require_once(dirname(__FILE__) . "/models.php"); + require_once(dirname(__FILE__) . "/models.php"); if(!defined("TRANSLATION_PLUGIN_LOADED")) { - $ste->register_tag( - "get_translation", - function($ste, $params, $sub) - { - global $translation; - if((!isset($translation)) or empty($params["for"]) or (!isset($translation[$params["for"]]))) - return ""; - $rv = $translation[$params["for"]]; - return (!empty($params["raw"])) ? $rv : htmlesc($rv); - } - ); - define("TRANSLATION_PLUGIN_LOADED", True); + $ste->register_tag( + "get_translation", + function($ste, $params, $sub) + { + global $translation; + if((!isset($translation)) or empty($params["for"]) or (!isset($translation[$params["for"]]))) + return ""; + $rv = $translation[$params["for"]]; + return (!empty($params["raw"])) ? $rv : htmlesc($rv); + } + ); + define("TRANSLATION_PLUGIN_LOADED", True); } /* * Function: load_language * Load a language (i.e. set the global $translation variable). - * + * * Parameters: - * $lang - The language (2-Letter code, e.g. "en", "de", "it" ...) to load. NULL for default (from database). + * $lang - The language (2-Letter code, e.g. "en", "de", "it" ...) to load. NULL for default (from database). */ function load_language($lang=NULL) { - if(!defined("SETUP")) - { - global $ratatoeskr_settings; - if($lang === NULL) - $lang = $ratatoeskr_settings["default_language"]; - } - else - { - if($lang === NULL) - $lang = "en"; - } - - /* - * Because we will include an file defined by the $lang param, we will - * only allow alphabetic characters, so this function should not be - * vulnerable to LFI-Exploits... - */ - $lang = implode("", array_filter(str_split($lang, 1), "ctype_alpha")); - - require(dirname(__FILE__) . "/../translations/$lang.php"); - - $GLOBALS["translation"] = $translation; + if(!defined("SETUP")) + { + global $ratatoeskr_settings; + if($lang === NULL) + $lang = $ratatoeskr_settings["default_language"]; + } + else + { + if($lang === NULL) + $lang = "en"; + } + + /* + * Because we will include an file defined by the $lang param, we will + * only allow alphabetic characters, so this function should not be + * vulnerable to LFI-Exploits... + */ + $lang = implode("", array_filter(str_split($lang, 1), "ctype_alpha")); + + require(dirname(__FILE__) . "/../translations/$lang.php"); + + $GLOBALS["translation"] = $translation; } ?> diff --git a/ratatoeskr/sys/urlprocess.php b/ratatoeskr/sys/urlprocess.php index d3c5edb..841ac67 100644 --- a/ratatoeskr/sys/urlprocess.php +++ b/ratatoeskr/sys/urlprocess.php @@ -1,9 +1,9 @@ <?php /* * File: ratatoeskr/sys/urlprocess.php - * + * * Providing functions / classes to handle URLs - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -13,147 +13,147 @@ /* * Function: url_action_simple * Generate an action in a more simple way. - * + * * Parameters: - * $function - A callback that gets the $data var as an input and returns the new $data var. Can throw an <Redirect> Exception. - * + * $function - A callback that gets the $data var as an input and returns the new $data var. Can throw an <Redirect> Exception. + * * Returns: - * A callback that can be used as an url action. + * A callback that can be used as an url action. */ function url_action_simple($function) { - return function(&$data, $url_now, &$url_next) use ($function) - { - try - { - $data = call_user_func($function, $data); - $url_next = array(); - } - catch(Redirect $e) - { - $url_next = $e->nextpath; - } - }; + return function(&$data, $url_now, &$url_next) use ($function) + { + try + { + $data = call_user_func($function, $data); + $url_next = array(); + } + catch(Redirect $e) + { + $url_next = $e->nextpath; + } + }; } /* * Function: url_action_subactions * Generate an action that contains subactions. Subactions can redirect to ".." to go to the level above. - * + * * Parameters: - * $actions - Associative array of actions. - * + * $actions - Associative array of actions. + * * Returns: - * A callback that can be used as an url action. + * A callback that can be used as an url action. */ function url_action_subactions($actions) { - return function(&$data, $url_now, &$url_next) use ($actions) - { - $result = url_process($url_next, $actions, $data); - if($result !== NULL) - $url_next = $result; - else - $url_next = array(); - }; + return function(&$data, $url_now, &$url_next) use ($actions) + { + $result = url_process($url_next, $actions, $data); + if($result !== NULL) + $url_next = $result; + else + $url_next = array(); + }; } /* * Function: url_action_alias * Generate an action that is an alias for another one (i.e. redirects). - * + * * Parameters: - * $for - Path (array) of the action this one should be an alias of. + * $for - Path (array) of the action this one should be an alias of. * * Returns: - * A callback that can be used as an url action. + * A callback that can be used as an url action. */ function url_action_alias($for) { - return function(&$data, $url_now, &$url_next) use($for) - { - $url_next = array_merge($for, $url_next); - }; + return function(&$data, $url_now, &$url_next) use($for) + { + $url_next = array_merge($for, $url_next); + }; } /* * Function: url_process * Choose an appropiate action for the given URL. - * + * * Parameters: - * $url - Either an array containing the URL components or the URL (both relative). - * $actions - Associative array of actions. - * Key is the name (anything alphanumeric, should usually not start with '_', reserved for special URL names, see beneath). - * Value is a callback of the form: function(&$data, $url_now, &$url_next). $data can be used for shared data between subactions. $url_next can be modified in order to redirect to another action / stop the routing. - * + * $url - Either an array containing the URL components or the URL (both relative). + * $actions - Associative array of actions. + * Key is the name (anything alphanumeric, should usually not start with '_', reserved for special URL names, see beneath). + * Value is a callback of the form: function(&$data, $url_now, &$url_next). $data can be used for shared data between subactions. $url_next can be modified in order to redirect to another action / stop the routing. + * * Special actions: - * _index - If name is empty, the index will be called. - * _default - If nothing was found, this is the default. - * _notfound - If not even _default exists or NotFoundError was thrown. - * _prelude - If existant, will be executed before everything else. - * _epilog - If existant, will be executed after evrything else. + * _index - If name is empty, the index will be called. + * _default - If nothing was found, this is the default. + * _notfound - If not even _default exists or NotFoundError was thrown. + * _prelude - If existant, will be executed before everything else. + * _epilog - If existant, will be executed after evrything else. */ function url_process($url, $actions, &$data) { - $epilog_running = 0; - if(is_string($url)) - $url = explode("/", $url); - $url = array_filter($url, function($x) { return !empty($x); }); - if(count($url) == 0) - $url = array("_index"); - - if(isset($actions["_prelude"])) - $url = array_merge(array("_prelude"), $url); - - $url_now = $url[0]; - $url_next = array_slice($url, 1); - - while(is_string($url_now) and ($url_now != "") and ($url_now != "..")) - { - $cb = NULL; - if(empty($url_now)) - $url_now = "_index"; - if(isset($actions[$url_now])) - $cb = $actions[$url_now]; - else if(isset($actions["_default"])) - $cb = $actions["_default"]; - else if(isset($actions["_notfound"])) - $cb = $actions["_notfound"]; - else - throw new NotFoundError(); - - try - { - call_user_func_array($cb, array(&$data, $url_now, &$url_next)); - } - catch(NotFoundError $e) - { - if(isset($actions["_notfound"])) - $url_next = array("_notfound"); - else - throw $e; - } - - if(count($url_next) > 0) - { - $url_now = $url_next[0]; - $url_next = array_slice($url_next, 1); - } - else if(isset($actions["_epilog"]) and ($epilog_running <= 0)) - { - $epilog_running = 2; - $url_now = "_epilog"; - } - else - $url_now = ""; - - --$epilog_running; - } - - if($url_now == "..") - return $url_next; - else - return NULL; + $epilog_running = 0; + if(is_string($url)) + $url = explode("/", $url); + $url = array_filter($url, function($x) { return !empty($x); }); + if(count($url) == 0) + $url = array("_index"); + + if(isset($actions["_prelude"])) + $url = array_merge(array("_prelude"), $url); + + $url_now = $url[0]; + $url_next = array_slice($url, 1); + + while(is_string($url_now) and ($url_now != "") and ($url_now != "..")) + { + $cb = NULL; + if(empty($url_now)) + $url_now = "_index"; + if(isset($actions[$url_now])) + $cb = $actions[$url_now]; + else if(isset($actions["_default"])) + $cb = $actions["_default"]; + else if(isset($actions["_notfound"])) + $cb = $actions["_notfound"]; + else + throw new NotFoundError(); + + try + { + call_user_func_array($cb, array(&$data, $url_now, &$url_next)); + } + catch(NotFoundError $e) + { + if(isset($actions["_notfound"])) + $url_next = array("_notfound"); + else + throw $e; + } + + if(count($url_next) > 0) + { + $url_now = $url_next[0]; + $url_next = array_slice($url_next, 1); + } + else if(isset($actions["_epilog"]) and ($epilog_running <= 0)) + { + $epilog_running = 2; + $url_now = "_epilog"; + } + else + $url_now = ""; + + --$epilog_running; + } + + if($url_now == "..") + return $url_next; + else + return NULL; } /* @@ -163,12 +163,12 @@ function url_process($url, $actions, &$data) */ class Redirect extends Exception { - public $nextpath; - public function __construct($nextpath) - { - $this->nextpath = $nextpath; - parent::__construct(); - } + public $nextpath; + public function __construct($nextpath) + { + $this->nextpath = $nextpath; + parent::__construct(); + } } /* * Class: NotFoundError diff --git a/ratatoeskr/sys/utils.php b/ratatoeskr/sys/utils.php index c2f8e66..4b4298f 100644 --- a/ratatoeskr/sys/utils.php +++ b/ratatoeskr/sys/utils.php @@ -1,9 +1,9 @@ <?php /* * File: ratatoeskr/sys/utils.php - * + * * Various useful helper functions. - * + * * License: * This file is part of Ratatöskr. * Ratatöskr is licensed unter the MIT / X11 License. @@ -12,110 +12,110 @@ /* * Function: array_repeat - * + * * Parameters: - * - * $val - - * $n - - * + * + * $val - + * $n - + * * Returns: - * - * An array with $val $n-times repeated. + * + * An array with $val $n-times repeated. */ function array_repeat($val, $n) { - $rv = array(); - for($i = 0; $i < $n; ++$i) - array_push($rv, $val); - return $rv; + $rv = array(); + for($i = 0; $i < $n; ++$i) + array_push($rv, $val); + return $rv; } /* * Function: array_blend - * + * * Blend multiple arrays together. - * + * * Example: - * - * array_blend(array(1,2,3), array(4,5,6), array(7,8,9)); - * will return array(1,4,7,2,5,8,3,6,9) + * + * array_blend(array(1,2,3), array(4,5,6), array(7,8,9)); + * will return array(1,4,7,2,5,8,3,6,9) */ function array_blend() { - $arrays = array_filter(func_get_args(), "is_array"); - - switch(count($arrays)) - { - case 0: return array(); break; - case 1: return $arrays[0]; break; - default: - $rv = array(); - while(array_sum(array_map("count", $arrays)) > 0) - { - for($i = 0; $i < count($arrays); ++$i) - { - $val = array_shift($arrays[$i]); - if($val === NULL) - continue; - array_push($rv, $val); - } - } - return $rv; - break; - } + $arrays = array_filter(func_get_args(), "is_array"); + + switch(count($arrays)) + { + case 0: return array(); break; + case 1: return $arrays[0]; break; + default: + $rv = array(); + while(array_sum(array_map("count", $arrays)) > 0) + { + for($i = 0; $i < count($arrays); ++$i) + { + $val = array_shift($arrays[$i]); + if($val === NULL) + continue; + array_push($rv, $val); + } + } + return $rv; + break; + } } /* * Function: array_filter_empty - * + * * Filters all empty elements out of an array. * * Parameters: - * - * $input - The input array + * + * $input - The input array * * Returns: - * - * The $input without its empty elements. + * + * The $input without its empty elements. */ function array_filter_empty($input) { - return array_filter($input, function($x){return !empty($x);}); + return array_filter($input, function($x){return !empty($x);}); } /* * Function: array_filter_keys - * + * * Like PHPs `array_filter`, but callback will get the key, not the value of the array element. */ function array_filter_keys($input, $callback) { - if(!is_array($input)) - throw new InvalidArgumentException("Argument 1 must be an array"); - if(empty($input)) - return array(); - $delete_keys = array_filter(array_keys($input), function ($x) use ($callback) { return !$callback($x);}); - foreach($delete_keys as $key) - unset($input[$key]); - return $input; + if(!is_array($input)) + throw new InvalidArgumentException("Argument 1 must be an array"); + if(empty($input)) + return array(); + $delete_keys = array_filter(array_keys($input), function ($x) use ($callback) { return !$callback($x);}); + foreach($delete_keys as $key) + unset($input[$key]); + return $input; } /* * Function: array_kvpairs_to_assoc * Convert array of key-value pairs to an associative array. - * + * * Parameters: - * $input - Array of key-value pairs - * + * $input - Array of key-value pairs + * * Returns: - * An associative array. + * An associative array. */ function array_kvpairs_to_assoc($input) { - $rv = array(); - foreach($input as $kvpair) - $rv[$kvpair[0]] = $kvpair[1]; - return $rv; + $rv = array(); + foreach($input as $kvpair) + $rv[$kvpair[0]] = $kvpair[1]; + return $rv; } /* @@ -124,79 +124,79 @@ function array_kvpairs_to_assoc($input) */ function intcmp($a, $b) { - return ($a == $b) ? 0 : (($a < $b) ? -1 : 1); + return ($a == $b) ? 0 : (($a < $b) ? -1 : 1); } /* * Function: ucount - * + * * Count elements of an array matching unser-defined rules. - * + * * Parameters: - * $array - The input array. - * $callback - A callback function. It will be called with the current value as the only parameter. The value is counted, if callback returns TRUE. + * $array - The input array. + * $callback - A callback function. It will be called with the current value as the only parameter. The value is counted, if callback returns TRUE. * * Returns: - * - * Number of elements where $callback returned TRUE. + * + * Number of elements where $callback returned TRUE. */ function ucount($array, $callback) { - return count(array_filter($array, $callback)); + return count(array_filter($array, $callback)); } /* * Function: vcount - * + * * Counts how often $value appears in $array. - * + * * Parameters: - * - * $array - - * $value - - * + * + * $array - + * $value - + * * Returns: - * - * How often $value appears in $array. + * + * How often $value appears in $array. */ function vcount($array, $value) { - return ucount($array, function($x){return $x===$value;}); + return ucount($array, function($x){return $x===$value;}); } /* * Function: self_url - * + * * Gets current URL. - * + * * From: http://dev.kanngard.net/Permalinks/ID_20050507183447.html */ function self_url() { - $s = empty($_SERVER["HTTPS"]) ? '' - : ($_SERVER["HTTPS"] == "on") ? "s" - : ""; - $protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s; - $port = ($_SERVER["SERVER_PORT"] == "80") ? "" - : (":".$_SERVER["SERVER_PORT"]); - return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI']; + $s = empty($_SERVER["HTTPS"]) ? '' + : ($_SERVER["HTTPS"] == "on") ? "s" + : ""; + $protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s; + $port = ($_SERVER["SERVER_PORT"] == "80") ? "" + : (":".$_SERVER["SERVER_PORT"]); + return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI']; } function strleft($s1, $s2) { - return substr($s1, 0, strpos($s1, $s2)); + return substr($s1, 0, strpos($s1, $s2)); } /* * Function: htmlesc * Escape HTML (shorter than htmlspecialchars) - * + * * Parameters: - * $text - Input text. - * + * $text - Input text. + * * Returns: - * HTML + * HTML */ function htmlesc($text) { - return htmlspecialchars($text, ENT_QUOTES, "UTF-8"); + return htmlspecialchars($text, ENT_QUOTES, "UTF-8"); } /* @@ -205,20 +205,20 @@ function htmlesc($text) */ function delete_directory($dir) { - $dir_content = scandir($dir); - foreach($dir_content as $f) - { - if(($f == "..") or ($f == ".")) - continue; - - $f = "$dir/$f"; - - if(is_dir($f)) - delete_directory($f); - else - unlink($f); - } - rmdir($dir); + $dir_content = scandir($dir); + foreach($dir_content as $f) + { + if(($f == "..") or ($f == ".")) + continue; + + $f = "$dir/$f"; + + if(is_dir($f)) + delete_directory($f); + else + unlink($f); + } + rmdir($dir); } /* diff --git a/ratatoeskr/translations/de.php b/ratatoeskr/translations/de.php index 657c3ed..50844e3 100644 --- a/ratatoeskr/translations/de.php +++ b/ratatoeskr/translations/de.php @@ -1,287 +1,287 @@ <?php $translation = array( - "username" => "Benutzername", - "password" => "Passwort", - "login_form_header" => "Login", - "login_form_button" => "Login", - "login_background_image" => "Hintergrundbild: <a href=\"[[URL]]\">[[FILENAME]]</a> von [[AUTHOR]]. Lizenz: [[LICENSE]]", - "login_failed" => "Login fehlgeschlagen: (Benutzername/Passwort falsch oder du bist kein Admin).", - "logout" => "Logout", - "section_admin" => "Administration", - "section_content" => "Inhalt", - "section_design" => "Design", - "section_plugins" => "Plugins", - "menu_articles" => "Artikel", - "menu_comments" => "Kommentare", - "menu_images" => "Bilder", - "menu_languages" => "Sprachen", - "menu_newarticles" => "Neuer Artikel", - "menu_pagesections" => "Seitensektionen", - "menu_plugin_repos" => "Pluginsammlungen", - "menu_plugininstall" => "Plugin installieren", - "menu_pluginlist" => "Pluginliste", - "menu_settings" => "Einstellungen", - "menu_styles" => "Stile", - "menu_tags" => "Tags", - "menu_templates" => "Templates", - "menu_users_groups" => "Benutzer / Gruppen", - "new_article" => "Neuer Artikel", - "articleedit_title" => "Titel des Artikels", - "articleedit_content" => "Inhalt", - "articleedit_excerpt" => "Exzerpt", - "comment_form_name" => "Dein Name", - "comment_form_mail" => "Deine E-Mailadresse", - "comment_form_text" => "Dein Kommentar (Markdown Format)", - "comment_form_submit" => "Kommentar senden", - "comment_form_preview" => "Vorschau", - "page_prev" => "<-- vorherige Seite", - "page_next" => "nächste Seite -->", - "e404_details" => "Die Seite [[URL]] konte nicht gefunden werden. Das tut uns leid.", - "author_name_missing" => "Kein Autorenname angegeben.", - "author_email_missing" => "Keine Autoren E-Mailadresse angegeben.", - "comment_text_missing" => "Ein leerer Kommentar kann nicht veröffentlicht werden.", - "comment_form_invalid" => "Das Komentarformular ist ungültig.", - "comment_too_fast" => "DieserKommentar wurde zu schnell geschrieben. Bist du etwa ein Spambot?", - "article_other_languages" => "Dieser Artikel in anderen Sprachen: ", - "save_texts_as_lang" => "Texte in dieser Sprache speichern:", - "settings_meta" => "Einstellungen / Metadaten", - "urlname" => "Eindeutiger URL-Name", - "tags_cs" => "Tags (kommagetrennt)", - "date_time" => "Datum / Zeit", - "article_status" => "Artikelstatus", - "article_status_hidden" => "Versteckt", - "article_status_live" => "Sichtbar", - "article_status_sticky" => "Klebrig", - "article_section" => "Sektion", - "invalid_urlname" => "Ungültiger URL-Name (Kann a-z A-Z 0-9 - und _ beinhalten)", - "invalid_article_status" => "Ungültiger Artikelstatus", - "unknown_txtproc" => "Unbekannter Textprozessor", - "invalid_date" => "Ungültiges Datum", - "article_edit_error" => "Konnte Artikel nicht bearbeiten.", - "unknown_section" => "Unbekannte Sektion", - "allow_comments" => "Kommentare erlauben?", - "article_name_already_in_use" => "Artikelname bereits vergeben.", - "article_save_success" => "Artikel erfolgreich abgespeichert.", - "tags_successfully_deleted" => "Tags erfolgreich gelöscht.", - "new_tag_name" => "Name", - "tags_successfully_edited" => "Tags erfolgreich bearbeitet.", - "tags_overview" => "Tag Übersicht", - "tag_name" => "Tag Name", - "yes" => "Ja", - "no" => "Nein", - "tag_add_lang" => "Übersetzung hinzufügen", - "save_changes" => "Änderungen speichern", - "language_unknown" => "Unbekannte Sprache", - "translation_added_successfully" => "Übersetzung erfolgreich hinzufügefügt.", - "invalid_tag_name" => "Ungülter Tagname. Ein Tagname darf keine Kommas (,) oder Leerzeichen ( ) enthalten und darf nicht leer sein.", - "available_languages" => "Verfügbare Sprachen", - "tags" => "Tags", - "section" => "Sektion", - "no_articles" => "Kein Artikel gespeichert.", - "delete" => "Löschen", - "articles_deleted" => "Artikel gelöscht.", - "sort_asc" => "aufsteigend", - "sort_desc" => "absteigend", - "filter" => "Filter", - "filter_urlname" => "nach URL-Name", - "filter_tag" => "nach Tag", - "filter_section" => "nach Sektion", - "image_upload" => "Neues Bild hochladen", - "img_upload_name" => "Name", - "img_upload_name_leave_empty" => "(Leerlassen für Standarddateinamen)", - "image_preview" => "Vorschau", - "image_name" => "Name", - "image_getmarkup" => "Einbettungscode", - "no_images" => "Keine Bilder gespeichert.", - "upload_failed" => "Hochladen fehlgeschlagen.", - "unknown_file_format" => "Unbekanntes Dateiformat.", - "upload_success" => "Hochladen erfolgreich", - "images_deleted" => "Bilder gelöscht.", - "generate_embed_code" => "Erstelle Einbettungscode.", - "image_alt" => "Alternativtitel", - "embed_code" => "Einbettungscode", - "was_read" => "Gelesen?", - "article" => "Artikel", - "visible" => "Sichtbar", - "comment_excerpt" => "Kommentar (Exzerpt)", - "no_comments" => "Keine Kommentare verfügbar.", - "read_more" => "Lies mehr.", - "language" => "Sprache", - "author" => "Autor", - "filter_article" => "nach Artikel", - "commentaction_make_invisible" => "Sichtbar machen", - "commentaction_make_visible" => "Unsichtbar machen", - "commentaction_mark_read" => "Als gelesen markieren", - "commentaction_mark_unread" => "Als ungelesen markieren", - "comments_successfully_deleted" => "Kommentare erfolgreich gelöscht.", - "comments_successfully_marked_read" => "Kommentare erfolgreich als gelesen markiert.", - "comments_successfully_marked_unread" => "Kommentare erfolgreich als ungelesen markiert.", - "comments_successfully_made_visible" => "Kommentare erfolgreich sichtbar gemacht.", - "comments_successfully_made_invisible" => "Kommentare erfolgreich unsichtbar gemacht.", - "unknown_action" => "Unbekannte Aktion.", - "comment_successfully_deleted" => "Kommentar erfolgreich gelöscht.", - "comment_successfully_made_visible" => "Kommentar erfolgreich sichtbar gemacht.", - "comment_successfully_made_invisible" => "Kommentar erfolgreich unsichtbar gemacht.", - "comment_perform_action" => "Aktion auf diesen Kommentar anwenden", - "comment_text" => "Kommentartext", - "comment_text_raw" => "Kommentartext (roh)", - "new_template" => "Neues Template", - "template" => "Template", - "template_name" => "Template Name", - "template_code" => "Template Code", - "templates_successfully_deleted" => "Templates erfolgreich gelöscht", - "invalid_template_name" => "Ungltiger Templatename. Gültige Templatenamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_), Bindestrichen (-) und Punkten (.)", - "could_not_compile_template" => "Konnte Template nicht Kompilieren. Grund: ", - "template_successfully_saved" => "Template erfolgreich abgespeichert.", - "style" => "Stil", - "new_style" => "Neuer Stil", - "style_name" => "Stilname", - "style_code" => "Stilcode", - "styles_successfully_deleted" => "Stile erfolgreich gelöscht.", - "invalid_style_name" => "Ungültiger Stilname. Gültige stilnamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_), Bindestrichen (-) und Punkten (.)", - "style_successfully_saved" => "Stil erfolgreich gespeichert.", - "new_section" => "Neue Sektion", - "section_name" => "Sektionsname", - "section_is_default" => "Ist Standard", - "styles" => "Stile", - "make_default" => "Als Standard setzen", - "set_template" => "Setze Template", - "add_style" => "Stil hinzufügen", - "section_already_exists" => "Sektion existiert bereits", - "unknown_template" => "Unbekanntes Template", - "invalid_section_name" => "Ungültiger Sektionsname. Gültige Sektionsnamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_) und Bindestrichen (-)", - "section_title" => "Titel", - "set_title" => "Setze Titel", - "section_created_successfully" => "Sektion erfolgreich erstellt", - "style_removed" => "Stil entfernt", - "remove" => "Entfernen", - "cannot_delete_default_section" => "Kann Standardsekton nicht löschen.", - "section_successfully_deleted" => "Sektion erfolgreich gelöscht,", - "default_section_changed_successfully" => "Standardsekton erfolgreich geändert.", - "successfully_added_style" => "Stil wurde erfolgreich hinzugefügt.", - "successfully_set_section_title" => "Titel erfolgreich gesetzt.", - "successfully_set_template" => "Template erfolgreich gesetzt.", - "comment_textprocessor" => "Textprozessor für Kommentare", - "language_settings" => "Spracheinstellungen", - "language_code" => "Sprachcode", - "default_language" => "Standardsprache", - "add_language" => "Sprache hinzufügen", - "comment_auto_visible" => "Kommentare standardmäßig sichtbar machen.", - "comment_settings" => "Kommentarenstellungen", - "comment_settings_successfully_saved" => "Kommentarenstellungen erfolgreich gespeichert", - "cannot_delete_default_language" => "Kann Standardsprache nicht löschen.", - "language_successfully_deleted" => "Sprache erfolgreich gelöscht.", - "successfully_set_default_language" => "Standardsprache erfolgreich gesetzt.", - "language_successfully_added" => "Sprache erfolgreich hinzugefügt.", - "new_user" => "Neuer Benutzer", - "initial_password" => "Initiales Passwort", - "new_group" => "Neue Gruppe", - "groupname" => "Gruppenname", - "users" => "Benutzer", - "groups" => "Gruppen", - "group" => "Gruppe", - "member_of_groups" => "Mitglied dieser Gruppen", - "cannot_delete_admin_group" => "Kann admin-Gruppe nicht löschen.", - "successfully_deleted_groups" => "Gruppen erfolgreich gelöscht.", - "empty_group_name" => "Kann Gruppe nicht erstellen: Gruppenname darf nicht leer sein.", - "group_already_exists" => "Gruppe existiert bereits.", - "successfully_created_group" => "Gruppe erfolgreich erstellt.", - "empty_username" => "Kann Benutzer nicht erstellen: Name darf nicht leer sein.", - "user_already_exists" => "Benutzer existiert bereits.", - "successfully_created_user" => "Benutzer erfolgreich erstellt.", - "cannot_delete_yourself" => "Du kannst dich nicht selbst löschen.", - "successfully_deleted_users" => "Benutzer erfolgreich gelöscht.", - "fullname" => "Vollständiger Name", - "mail_address" => "Mailadresse", - "new_password" => "Neues Passwort", - "successfully_modified_user" => "Benutzer erfolgreich verändert.", - "successfully_set_new_password" => "Neues Passwort erfolgreich gesetzt.", - "plugin_name" => "Name", - "plugin_version" => "Version", - "plugin_isactive" => "Aktiv", - "plugin_description" => "Beschreibung", - "plugin_author" => "Autor", - "plugin_web" => "Web", - "plugin_help" => "Hilfe", - "plugin_update" => "Update", - "plugin_activate" => "Aktivieren", - "plugin_deactivate" => "Deaktivieren", - "no_plugins" => "Keine Plugins installiert.", - "install_from_package" => "Aus Paket installieren", - "invalid_package" => "Ungültiges Paket", - "incompatible_plugin" => "Dieses Plugin ist nicht mit dieser Version von Ratatöskr kompatibel. Es benötigt die API Version [[API]] oder eine kompatible.", - "plugin_safety_warning" => "Installiere <strong>niemals</strong> ein Plugin, dem du nicht vertraust! Plugins sind sehr mächtig und könnten potentiell deine Ratatöskr Installation zerstören!", - "plugin_src" => "Sourcecode", - "license" => "Lizenz", - "plugin_installed_successfully" => "Plugin erfolgreich installiert.", - "successfully_deleted_plugins" => "Plugins erfolgreich gelöscht.", - "plugins_activated" => "Plugins aktiviert.", - "plugins_deactivated" => "Plugins deaktiviert.", - "successfully_updated_plugins" => "Diese Plugins wurden aktualisiert: [[PLUGINS]]", - "nothing_to_update" => "Keine Update verfügbar.", - "add_repo" => "Füge einen Sammlung hinzu", - "repo_baseurl" => "Repository base URL", - "repo_list" => "Liste von Sammlungen", - "repo_name" => "Name", - "repo_description" => "Beschreibung", - "no_repos" => "Keine Sammlungen gefunden.", - "force_repo_refresh" => "Auffrischen erzwingen", - "successfully_added_repo" => "Sammlung erfolgreich hinzugefügt.", - "repository_unreachable_or_invalid" => "Sammlung nicht verfügbar oder ungültig.", - "repos_deleted" => "Sammlungen gelöscht.", - "successfully_refreshed_repos" => "Erfolgreich aufgefrischt.", - "repo_refresh_failed_on" => "Auffrischen ist bei diesen Sammlungen gescheitert: [[REPOS]]", - "no_repos_add_some" => "Keine Sammlungen gefunden. Du solltest <a href=\"[[URL]]\">ein paar Sammlungen hinzufügen</a>.", - "install_from_repo" => "Aus Sammlung installieren", - "search" => "Suche", - "repo_plugin_search_in" => "Suche in", - "search_in_all_repos" => "allen Sammlungen", - "repo" => "Sammlung", - "install" => "Installieren", - "package_or_repo_not_found" => "Paket oder Sammlung nicht gefunden.", - "dbsetup_mysql_host" => "MySQL Host (normalerweise 'localhost')", - "dbsetup_mysql_user" => "MySQL Benutzername", - "dbsetup_mysql_passwd" => "MySQL Passwort", - "dbsetup_mysql_database" => "MySQL Datenbank-Name", - "dbsetup_table_prefix" => "Tabellenpräfix", - "dbsetup" => "Datenbank Setup", - "admin_setup" => "Administrator Daten", - "setup_almost_done" => "Fast geschafft", - "setup_configfile_instructions" => "Du musst noch den Inhalt der Datei '/ratatoeskr/config.php' in deiner Ratatöskr Installation mit diesem Text ersetzen:", - "setup_delete_setup_instructions_and_pointers" => "Außerdem solltest du wirklich die Datei '/setup.php' in deiner Ratatöskr Installation löschen. Wenn du das gemacht hast, kannst du zu deiner neuen Ratatöskr Installation gehen:", - "setup_link_yourpage" => "Deine neuen Webpage", - "setup_link_backend" => "Das Backend deiner Webpage", - "admin_data_must_be_filled_out" => "Administrator Daten müssen ausgefüllt sein", - "enforce" => "Erzwingen", - "could_not_activate_plugin_api_incompat" => "Konnte diese Plugins nicht aktivieren, da sie nicht (mehr) mit deiner Ratatöskr-Installation kompatibel sind: [[PLUGINS]]", - "plugins_incompat" => "Diese Plugins sind nicht (mehr) mit deiner Ratatöskr-Installation kompatibel: [[PLUGINS]]", - "could_not_initialize_repos" => "Setup ist abgeschlossen, allerdings konnten die Standard-Repositories nicht initalisiert werden.", - "debugmode" => "Debug-Modus", - "enabled" => "Aktiviert", - "disabled" => "Deaktiviert", - "debugmode_might_get_overwritten_by_config_file" => "(dies kann durch config.php überschrieben werden)", - "debugmode_now_enabled" => "Debug-Modus ist nun aktiviert", - "debugmode_now_disabled" => "Debug-Modus ist nun deaktiviert", - /* Very long texts here */ - "linking_back_hint" => <<<LINKINGBACK + "username" => "Benutzername", + "password" => "Passwort", + "login_form_header" => "Login", + "login_form_button" => "Login", + "login_background_image" => "Hintergrundbild: <a href=\"[[URL]]\">[[FILENAME]]</a> von [[AUTHOR]]. Lizenz: [[LICENSE]]", + "login_failed" => "Login fehlgeschlagen: (Benutzername/Passwort falsch oder du bist kein Admin).", + "logout" => "Logout", + "section_admin" => "Administration", + "section_content" => "Inhalt", + "section_design" => "Design", + "section_plugins" => "Plugins", + "menu_articles" => "Artikel", + "menu_comments" => "Kommentare", + "menu_images" => "Bilder", + "menu_languages" => "Sprachen", + "menu_newarticles" => "Neuer Artikel", + "menu_pagesections" => "Seitensektionen", + "menu_plugin_repos" => "Pluginsammlungen", + "menu_plugininstall" => "Plugin installieren", + "menu_pluginlist" => "Pluginliste", + "menu_settings" => "Einstellungen", + "menu_styles" => "Stile", + "menu_tags" => "Tags", + "menu_templates" => "Templates", + "menu_users_groups" => "Benutzer / Gruppen", + "new_article" => "Neuer Artikel", + "articleedit_title" => "Titel des Artikels", + "articleedit_content" => "Inhalt", + "articleedit_excerpt" => "Exzerpt", + "comment_form_name" => "Dein Name", + "comment_form_mail" => "Deine E-Mailadresse", + "comment_form_text" => "Dein Kommentar (Markdown Format)", + "comment_form_submit" => "Kommentar senden", + "comment_form_preview" => "Vorschau", + "page_prev" => "<-- vorherige Seite", + "page_next" => "nächste Seite -->", + "e404_details" => "Die Seite [[URL]] konte nicht gefunden werden. Das tut uns leid.", + "author_name_missing" => "Kein Autorenname angegeben.", + "author_email_missing" => "Keine Autoren E-Mailadresse angegeben.", + "comment_text_missing" => "Ein leerer Kommentar kann nicht veröffentlicht werden.", + "comment_form_invalid" => "Das Komentarformular ist ungültig.", + "comment_too_fast" => "DieserKommentar wurde zu schnell geschrieben. Bist du etwa ein Spambot?", + "article_other_languages" => "Dieser Artikel in anderen Sprachen: ", + "save_texts_as_lang" => "Texte in dieser Sprache speichern:", + "settings_meta" => "Einstellungen / Metadaten", + "urlname" => "Eindeutiger URL-Name", + "tags_cs" => "Tags (kommagetrennt)", + "date_time" => "Datum / Zeit", + "article_status" => "Artikelstatus", + "article_status_hidden" => "Versteckt", + "article_status_live" => "Sichtbar", + "article_status_sticky" => "Klebrig", + "article_section" => "Sektion", + "invalid_urlname" => "Ungültiger URL-Name (Kann a-z A-Z 0-9 - und _ beinhalten)", + "invalid_article_status" => "Ungültiger Artikelstatus", + "unknown_txtproc" => "Unbekannter Textprozessor", + "invalid_date" => "Ungültiges Datum", + "article_edit_error" => "Konnte Artikel nicht bearbeiten.", + "unknown_section" => "Unbekannte Sektion", + "allow_comments" => "Kommentare erlauben?", + "article_name_already_in_use" => "Artikelname bereits vergeben.", + "article_save_success" => "Artikel erfolgreich abgespeichert.", + "tags_successfully_deleted" => "Tags erfolgreich gelöscht.", + "new_tag_name" => "Name", + "tags_successfully_edited" => "Tags erfolgreich bearbeitet.", + "tags_overview" => "Tag Übersicht", + "tag_name" => "Tag Name", + "yes" => "Ja", + "no" => "Nein", + "tag_add_lang" => "Übersetzung hinzufügen", + "save_changes" => "Änderungen speichern", + "language_unknown" => "Unbekannte Sprache", + "translation_added_successfully" => "Übersetzung erfolgreich hinzufügefügt.", + "invalid_tag_name" => "Ungülter Tagname. Ein Tagname darf keine Kommas (,) oder Leerzeichen ( ) enthalten und darf nicht leer sein.", + "available_languages" => "Verfügbare Sprachen", + "tags" => "Tags", + "section" => "Sektion", + "no_articles" => "Kein Artikel gespeichert.", + "delete" => "Löschen", + "articles_deleted" => "Artikel gelöscht.", + "sort_asc" => "aufsteigend", + "sort_desc" => "absteigend", + "filter" => "Filter", + "filter_urlname" => "nach URL-Name", + "filter_tag" => "nach Tag", + "filter_section" => "nach Sektion", + "image_upload" => "Neues Bild hochladen", + "img_upload_name" => "Name", + "img_upload_name_leave_empty" => "(Leerlassen für Standarddateinamen)", + "image_preview" => "Vorschau", + "image_name" => "Name", + "image_getmarkup" => "Einbettungscode", + "no_images" => "Keine Bilder gespeichert.", + "upload_failed" => "Hochladen fehlgeschlagen.", + "unknown_file_format" => "Unbekanntes Dateiformat.", + "upload_success" => "Hochladen erfolgreich", + "images_deleted" => "Bilder gelöscht.", + "generate_embed_code" => "Erstelle Einbettungscode.", + "image_alt" => "Alternativtitel", + "embed_code" => "Einbettungscode", + "was_read" => "Gelesen?", + "article" => "Artikel", + "visible" => "Sichtbar", + "comment_excerpt" => "Kommentar (Exzerpt)", + "no_comments" => "Keine Kommentare verfügbar.", + "read_more" => "Lies mehr.", + "language" => "Sprache", + "author" => "Autor", + "filter_article" => "nach Artikel", + "commentaction_make_invisible" => "Sichtbar machen", + "commentaction_make_visible" => "Unsichtbar machen", + "commentaction_mark_read" => "Als gelesen markieren", + "commentaction_mark_unread" => "Als ungelesen markieren", + "comments_successfully_deleted" => "Kommentare erfolgreich gelöscht.", + "comments_successfully_marked_read" => "Kommentare erfolgreich als gelesen markiert.", + "comments_successfully_marked_unread" => "Kommentare erfolgreich als ungelesen markiert.", + "comments_successfully_made_visible" => "Kommentare erfolgreich sichtbar gemacht.", + "comments_successfully_made_invisible" => "Kommentare erfolgreich unsichtbar gemacht.", + "unknown_action" => "Unbekannte Aktion.", + "comment_successfully_deleted" => "Kommentar erfolgreich gelöscht.", + "comment_successfully_made_visible" => "Kommentar erfolgreich sichtbar gemacht.", + "comment_successfully_made_invisible" => "Kommentar erfolgreich unsichtbar gemacht.", + "comment_perform_action" => "Aktion auf diesen Kommentar anwenden", + "comment_text" => "Kommentartext", + "comment_text_raw" => "Kommentartext (roh)", + "new_template" => "Neues Template", + "template" => "Template", + "template_name" => "Template Name", + "template_code" => "Template Code", + "templates_successfully_deleted" => "Templates erfolgreich gelöscht", + "invalid_template_name" => "Ungltiger Templatename. Gültige Templatenamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_), Bindestrichen (-) und Punkten (.)", + "could_not_compile_template" => "Konnte Template nicht Kompilieren. Grund: ", + "template_successfully_saved" => "Template erfolgreich abgespeichert.", + "style" => "Stil", + "new_style" => "Neuer Stil", + "style_name" => "Stilname", + "style_code" => "Stilcode", + "styles_successfully_deleted" => "Stile erfolgreich gelöscht.", + "invalid_style_name" => "Ungültiger Stilname. Gültige stilnamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_), Bindestrichen (-) und Punkten (.)", + "style_successfully_saved" => "Stil erfolgreich gespeichert.", + "new_section" => "Neue Sektion", + "section_name" => "Sektionsname", + "section_is_default" => "Ist Standard", + "styles" => "Stile", + "make_default" => "Als Standard setzen", + "set_template" => "Setze Template", + "add_style" => "Stil hinzufügen", + "section_already_exists" => "Sektion existiert bereits", + "unknown_template" => "Unbekanntes Template", + "invalid_section_name" => "Ungültiger Sektionsname. Gültige Sektionsnamen sind mindestens ein Zeichen lang und bestehen nur aus Buchstaben (a-z), Ziffern (0-9), Unterstrichen (_) und Bindestrichen (-)", + "section_title" => "Titel", + "set_title" => "Setze Titel", + "section_created_successfully" => "Sektion erfolgreich erstellt", + "style_removed" => "Stil entfernt", + "remove" => "Entfernen", + "cannot_delete_default_section" => "Kann Standardsekton nicht löschen.", + "section_successfully_deleted" => "Sektion erfolgreich gelöscht,", + "default_section_changed_successfully" => "Standardsekton erfolgreich geändert.", + "successfully_added_style" => "Stil wurde erfolgreich hinzugefügt.", + "successfully_set_section_title" => "Titel erfolgreich gesetzt.", + "successfully_set_template" => "Template erfolgreich gesetzt.", + "comment_textprocessor" => "Textprozessor für Kommentare", + "language_settings" => "Spracheinstellungen", + "language_code" => "Sprachcode", + "default_language" => "Standardsprache", + "add_language" => "Sprache hinzufügen", + "comment_auto_visible" => "Kommentare standardmäßig sichtbar machen.", + "comment_settings" => "Kommentarenstellungen", + "comment_settings_successfully_saved" => "Kommentarenstellungen erfolgreich gespeichert", + "cannot_delete_default_language" => "Kann Standardsprache nicht löschen.", + "language_successfully_deleted" => "Sprache erfolgreich gelöscht.", + "successfully_set_default_language" => "Standardsprache erfolgreich gesetzt.", + "language_successfully_added" => "Sprache erfolgreich hinzugefügt.", + "new_user" => "Neuer Benutzer", + "initial_password" => "Initiales Passwort", + "new_group" => "Neue Gruppe", + "groupname" => "Gruppenname", + "users" => "Benutzer", + "groups" => "Gruppen", + "group" => "Gruppe", + "member_of_groups" => "Mitglied dieser Gruppen", + "cannot_delete_admin_group" => "Kann admin-Gruppe nicht löschen.", + "successfully_deleted_groups" => "Gruppen erfolgreich gelöscht.", + "empty_group_name" => "Kann Gruppe nicht erstellen: Gruppenname darf nicht leer sein.", + "group_already_exists" => "Gruppe existiert bereits.", + "successfully_created_group" => "Gruppe erfolgreich erstellt.", + "empty_username" => "Kann Benutzer nicht erstellen: Name darf nicht leer sein.", + "user_already_exists" => "Benutzer existiert bereits.", + "successfully_created_user" => "Benutzer erfolgreich erstellt.", + "cannot_delete_yourself" => "Du kannst dich nicht selbst löschen.", + "successfully_deleted_users" => "Benutzer erfolgreich gelöscht.", + "fullname" => "Vollständiger Name", + "mail_address" => "Mailadresse", + "new_password" => "Neues Passwort", + "successfully_modified_user" => "Benutzer erfolgreich verändert.", + "successfully_set_new_password" => "Neues Passwort erfolgreich gesetzt.", + "plugin_name" => "Name", + "plugin_version" => "Version", + "plugin_isactive" => "Aktiv", + "plugin_description" => "Beschreibung", + "plugin_author" => "Autor", + "plugin_web" => "Web", + "plugin_help" => "Hilfe", + "plugin_update" => "Update", + "plugin_activate" => "Aktivieren", + "plugin_deactivate" => "Deaktivieren", + "no_plugins" => "Keine Plugins installiert.", + "install_from_package" => "Aus Paket installieren", + "invalid_package" => "Ungültiges Paket", + "incompatible_plugin" => "Dieses Plugin ist nicht mit dieser Version von Ratatöskr kompatibel. Es benötigt die API Version [[API]] oder eine kompatible.", + "plugin_safety_warning" => "Installiere <strong>niemals</strong> ein Plugin, dem du nicht vertraust! Plugins sind sehr mächtig und könnten potentiell deine Ratatöskr Installation zerstören!", + "plugin_src" => "Sourcecode", + "license" => "Lizenz", + "plugin_installed_successfully" => "Plugin erfolgreich installiert.", + "successfully_deleted_plugins" => "Plugins erfolgreich gelöscht.", + "plugins_activated" => "Plugins aktiviert.", + "plugins_deactivated" => "Plugins deaktiviert.", + "successfully_updated_plugins" => "Diese Plugins wurden aktualisiert: [[PLUGINS]]", + "nothing_to_update" => "Keine Update verfügbar.", + "add_repo" => "Füge einen Sammlung hinzu", + "repo_baseurl" => "Repository base URL", + "repo_list" => "Liste von Sammlungen", + "repo_name" => "Name", + "repo_description" => "Beschreibung", + "no_repos" => "Keine Sammlungen gefunden.", + "force_repo_refresh" => "Auffrischen erzwingen", + "successfully_added_repo" => "Sammlung erfolgreich hinzugefügt.", + "repository_unreachable_or_invalid" => "Sammlung nicht verfügbar oder ungültig.", + "repos_deleted" => "Sammlungen gelöscht.", + "successfully_refreshed_repos" => "Erfolgreich aufgefrischt.", + "repo_refresh_failed_on" => "Auffrischen ist bei diesen Sammlungen gescheitert: [[REPOS]]", + "no_repos_add_some" => "Keine Sammlungen gefunden. Du solltest <a href=\"[[URL]]\">ein paar Sammlungen hinzufügen</a>.", + "install_from_repo" => "Aus Sammlung installieren", + "search" => "Suche", + "repo_plugin_search_in" => "Suche in", + "search_in_all_repos" => "allen Sammlungen", + "repo" => "Sammlung", + "install" => "Installieren", + "package_or_repo_not_found" => "Paket oder Sammlung nicht gefunden.", + "dbsetup_mysql_host" => "MySQL Host (normalerweise 'localhost')", + "dbsetup_mysql_user" => "MySQL Benutzername", + "dbsetup_mysql_passwd" => "MySQL Passwort", + "dbsetup_mysql_database" => "MySQL Datenbank-Name", + "dbsetup_table_prefix" => "Tabellenpräfix", + "dbsetup" => "Datenbank Setup", + "admin_setup" => "Administrator Daten", + "setup_almost_done" => "Fast geschafft", + "setup_configfile_instructions" => "Du musst noch den Inhalt der Datei '/ratatoeskr/config.php' in deiner Ratatöskr Installation mit diesem Text ersetzen:", + "setup_delete_setup_instructions_and_pointers" => "Außerdem solltest du wirklich die Datei '/setup.php' in deiner Ratatöskr Installation löschen. Wenn du das gemacht hast, kannst du zu deiner neuen Ratatöskr Installation gehen:", + "setup_link_yourpage" => "Deine neuen Webpage", + "setup_link_backend" => "Das Backend deiner Webpage", + "admin_data_must_be_filled_out" => "Administrator Daten müssen ausgefüllt sein", + "enforce" => "Erzwingen", + "could_not_activate_plugin_api_incompat" => "Konnte diese Plugins nicht aktivieren, da sie nicht (mehr) mit deiner Ratatöskr-Installation kompatibel sind: [[PLUGINS]]", + "plugins_incompat" => "Diese Plugins sind nicht (mehr) mit deiner Ratatöskr-Installation kompatibel: [[PLUGINS]]", + "could_not_initialize_repos" => "Setup ist abgeschlossen, allerdings konnten die Standard-Repositories nicht initalisiert werden.", + "debugmode" => "Debug-Modus", + "enabled" => "Aktiviert", + "disabled" => "Deaktiviert", + "debugmode_might_get_overwritten_by_config_file" => "(dies kann durch config.php überschrieben werden)", + "debugmode_now_enabled" => "Debug-Modus ist nun aktiviert", + "debugmode_now_disabled" => "Debug-Modus ist nun deaktiviert", + /* Very long texts here */ + "linking_back_hint" => <<<LINKINGBACK <h2>Verlinken auf die Seitenwurzel</h2> <p>Der Text <code>%root%</code> wird mit einem Pfad ersetzt, der auf die Wurzel deiner Ratatöskr Seite verweist.</p> LINKINGBACK - ,"content_write_cheatsheet" => <<<CHEATSHEET + ,"content_write_cheatsheet" => <<<CHEATSHEET <h2>Markdown Spickzettel</h2> <h3>Betonung / Kräftig</h3> <p> - <code>*<em>Betonung</em>*</code><br /> - <code>_<em>Betonung</em>_</code><br /> - <code>**<strong>Kräftig</strong>**</code><br /> - <code>__<strong>Kräftig</strong>__</code> + <code>*<em>Betonung</em>*</code><br /> + <code>_<em>Betonung</em>_</code><br /> + <code>**<strong>Kräftig</strong>**</code><br /> + <code>__<strong>Kräftig</strong>__</code> </p> <h3>Absätze und manuelle Zeilenumbrüche.</h3> <p> - <code>Erster Absatz<br /> + <code>Erster Absatz<br /> <br /> Zweiter Absatz mit<br /> langem<br /> @@ -294,7 +294,7 @@ mit zweil Leerzeichen ab.</code> <h3>Überschriften</h3> <p> - <code>Überschrift 1<br /> + <code>Überschrift 1<br /> =============<br /> <br /> Überschrift 2<br /> @@ -311,22 +311,22 @@ mit zweil Leerzeichen ab.</code> <h3>Verlinken</h3> <p> - <code>[Linktext](http://url/zur/resource "Optionaler Titel")</code> + <code>[Linktext](http://url/zur/resource "Optionaler Titel")</code> </p> <p> - <code>[Linktext][id]. Irgendwo anders:<br /> + <code>[Linktext][id]. Irgendwo anders:<br /> <br /> [id]: http://url/zur/resource "Optionaler Titel"</code> </p> <h3>Bilder</h3> <p> - <code>![alt text](/pfad/zum/bild "Optionaler Titel")</code> + <code>![alt text](/pfad/zum/bild "Optionaler Titel")</code> </p> <h3>Sortierte / Unsortierte Liste</h3> <p> - <code>* Element A<br /> + <code>* Element A<br /> * Element B<br /> <br /> Mit zweitem Absatz.<br /> @@ -336,15 +336,15 @@ mit zweil Leerzeichen ab.</code> * Element C2<br /></code> </p> <p> - <code>1. Erstes Element<br /> + <code>1. Erstes Element<br /> 2. Zweites Element </code> </p> <h3>Erfahre mehr</h3> <p> - <a href="http://daringfireball.net/projects/markdown/syntax">Komplette Syntax</a><br /> - <a href="http://daringfireball.net/projects/markdown/dingus">Markdown testen</a> + <a href="http://daringfireball.net/projects/markdown/syntax">Komplette Syntax</a><br /> + <a href="http://daringfireball.net/projects/markdown/dingus">Markdown testen</a> </p> CHEATSHEET ); diff --git a/ratatoeskr/translations/en.php b/ratatoeskr/translations/en.php index a53617c..9770696 100644 --- a/ratatoeskr/translations/en.php +++ b/ratatoeskr/translations/en.php @@ -1,287 +1,287 @@ <?php $translation = array( - "username" => "Username", - "password" => "Password", - "login_form_header" => "Login", - "login_form_button" => "Login", - "login_background_image" => "Background image: <a href=\"[[URL]]\">[[FILENAME]]</a> by [[AUTHOR]]. License: [[LICENSE]]", - "login_failed" => "Login failed (Username/Password is wrong or you are not an admin).", - "logout" => "Logout", - "section_admin" => "Administration", - "section_content" => "Content", - "section_design" => "Design", - "section_plugins" => "Plugins", - "menu_articles" => "Articles", - "menu_comments" => "Comments", - "menu_images" => "Images", - "menu_languages" => "Languages", - "menu_newarticles" => "New Article", - "menu_pagesections" => "Page Sections", - "menu_plugin_repos" => "Plugin Repositories", - "menu_plugininstall" => "Install Plugin", - "menu_pluginlist" => "Plugin List", - "menu_settings" => "Settings", - "menu_styles" => "Styles", - "menu_tags" => "Tags", - "menu_templates" => "Templates", - "menu_users_groups" => "Users / Groups", - "new_article" => "New Article", - "articleedit_title" => "Article Title", - "articleedit_content" => "Content", - "articleedit_excerpt" => "Excerpt", - "comment_form_name" => "Your name", - "comment_form_mail" => "Your E-Mailaddress", - "comment_form_text" => "Your comment (Markdown format)", - "comment_form_submit" => "Submit comment", - "comment_form_preview" => "Preview", - "page_prev" => "<-- previous page", - "page_next" => "next page -->", - "e404_details" => "The page [[URL]] could not be found. Sorry.", - "author_name_missing" => "No author name given.", - "author_email_missing" => "No author E-Mailaddress given.", - "comment_text_missing" => "An empty comment can not be posted.", - "comment_form_invalid" => "The comment form is invalid.", - "comment_too_fast" => "This comment was written too fast. Are you a spambot?", - "article_other_languages" => "This article in other languages: ", - "save_texts_as_lang" => "Save texts as language", - "settings_meta" => "Settings / Metadata", - "urlname" => "Unique URL name", - "tags_cs" => "Tags (comma seperated)", - "date_time" => "Date / Time", - "article_status" => "Article Status", - "article_status_hidden" => "Hidden", - "article_status_live" => "Live", - "article_status_sticky" => "Sticky", - "article_section" => "Section", - "invalid_urlname" => "Invalid URL name (Can contain a-z A-Z 0-9 - and _)", - "invalid_article_status" => "Invalid article status", - "unknown_txtproc" => "Unknown Textprocessor", - "invalid_date" => "Invalid date", - "article_edit_error" => "Could not edit article.", - "unknown_section" => "Unknown section", - "allow_comments" => "Allow comments?", - "article_name_already_in_use" => "Article name is already in use.", - "article_save_success" => "Article successfully saved.", - "tags_successfully_deleted" => "Tags successfully deleted.", - "new_tag_name" => "Name", - "tags_successfully_edited" => "Successfully edited tags.", - "tags_overview" => "Tag Overview", - "tag_name" => "Tag name", - "yes" => "Yes", - "no" => "No", - "tag_add_lang" => "Add translation", - "save_changes" => "Save changes", - "language_unknown" => "Unknown language", - "translation_added_successfully" => "Translation added successfully.", - "invalid_tag_name" => "Invalid tag name. A tag name can not contain commas (,) or spaces ( ) and must not be empty.", - "available_languages" => "Available languages", - "tags" => "Tags", - "section" => "Section", - "no_articles" => "No articles stored.", - "delete" => "Delete", - "articles_deleted" => "Articles deleted.", - "sort_asc" => "ascending", - "sort_desc" => "descending", - "filter" => "Filter", - "filter_urlname" => "by URL name", - "filter_tag" => "by tag", - "filter_section" => "by section", - "image_upload" => "Upload a new image", - "img_upload_name" => "Name", - "img_upload_name_leave_empty" => "(Leave empty for default filename)", - "image_preview" => "Preview", - "image_name" => "Name", - "image_getmarkup" => "Embed code", - "no_images" => "No images stored.", - "upload_failed" => "Upload failed.", - "unknown_file_format" => "Unknown file format.", - "upload_success" => "Upload successful", - "images_deleted" => "Images deleted.", - "generate_embed_code" => "Generate embed code.", - "image_alt" => "Alternative Title", - "embed_code" => "Embed code", - "was_read" => "Read?", - "article" => "Article", - "visible" => "Visible", - "comment_excerpt" => "Comment (excerpt)", - "no_comments" => "No comments available.", - "read_more" => "Read more", - "language" => "Language", - "author" => "Author", - "filter_article" => "by Article", - "commentaction_make_invisible" => "Make invisible", - "commentaction_make_visible" => "Make visible", - "commentaction_mark_read" => "Mark as read", - "commentaction_mark_unread" => "Mark as unread", - "comments_successfully_deleted" => "Comments sucessfully deleted.", - "comments_successfully_marked_read" => "Comments successfully marked as read.", - "comments_successfully_marked_unread" => "Comments successfully marked as unread.", - "comments_successfully_made_visible" => "Comments successfully made visible.", - "comments_successfully_made_invisible" => "Comments successfully made invisible.", - "unknown_action" => "Unknown action.", - "comment_successfully_deleted" => "Comment sucessfully deleted.", - "comment_successfully_made_visible" => "Comment successfully made visible.", - "comment_successfully_made_invisible" => "Comment successfully made invisible.", - "comment_perform_action" => "Perform an action on this comment", - "comment_text" => "Comment Text", - "comment_text_raw" => "Comment Text (raw)", - "new_template" => "New Template", - "template" => "Template", - "template_name" => "Template name", - "template_code" => "Template code", - "templates_successfully_deleted" => "Templates successfully deleted", - "invalid_template_name" => "Invalid template name. Valid template names are at least 1 character long and only contains letters, numbers, underscores(_), hyphens(-) and dots(.)", - "could_not_compile_template" => "Could not compile template. Reason: ", - "template_successfully_saved" => "Template successfully saved.", - "style" => "Style", - "new_style" => "New style", - "style_name" => "Style name", - "style_code" => "Style code", - "styles_successfully_deleted" => "Styles successfully deleted", - "invalid_style_name" => "Invalid style name. Valid style names are at least 1 character long and only contains letters, numbers, underscores(_), hyphens(-) and dots(.)", - "style_successfully_saved" => "Style successfully saved.", - "new_section" => "New Section", - "section_name" => "Section name", - "section_is_default" => "Is default", - "styles" => "Styles", - "make_default" => "Make default", - "set_template" => "Set template", - "add_style" => "Add style", - "section_already_exists" => "Section already exists.", - "unknown_template" => "Unknown template", - "invalid_section_name" => "Invalid section name. Valid section names are at least 1 character long and only contains letters, numbers, underscores(_) and hyphens(-)", - "section_title" => "Title", - "set_title" => "Set Title", - "section_created_successfully" => "Section created", - "style_removed" => "Style removed", - "remove" => "Remove", - "cannot_delete_default_section" => "Can not delete default section.", - "section_successfully_deleted" => "Section successfully deleted.", - "default_section_changed_successfully" => "Default section changed successfully.", - "successfully_added_style" => "Successfully added style.", - "successfully_set_section_title" => "Successfully set title.", - "successfully_set_template" => "Successfully set template.", - "comment_textprocessor" => "Textprocessor for comments", - "language_settings" => "Language settings", - "language_code" => "Language code", - "default_language" => "Default language", - "add_language" => "Add language", - "comment_auto_visible" => "Make comments visible automatically", - "comment_settings" => "Comment settings", - "comment_settings_successfully_saved" => "Comment settings successfully saved", - "cannot_delete_default_language" => "Can not delete default language.", - "language_successfully_deleted" => "Language successfully deleted.", - "successfully_set_default_language" => "Successfully set default language.", - "language_successfully_added" => "Language successfully added.", - "new_user" => "New user", - "initial_password" => "Initial password", - "new_group" => "New Group", - "groupname" => "Group name", - "users" => "Users", - "groups" => "Groups", - "group" => "Group", - "member_of_groups" => "Member of these groups", - "cannot_delete_admin_group" => "Can not delete admin group.", - "successfully_deleted_groups" => "Successfully deleted groups.", - "empty_group_name" => "Can not create group: Empty group name.", - "group_already_exists" => "Group already exists.", - "successfully_created_group" => "Successfully created group.", - "empty_username" => "Can not create user: Empty username.", - "user_already_exists" => "User already exists.", - "successfully_created_user" => "Successfully created user.", - "cannot_delete_yourself" => "You can not delete yourself.", - "successfully_deleted_users" => "Successfully deleted users.", - "fullname" => "Full name", - "mail_address" => "Mail Address", - "new_password" => "New password", - "successfully_modified_user" => "Successfully modified user.", - "successfully_set_new_password" => "Successfully set new password.", - "plugin_name" => "Name", - "plugin_version" => "Version", - "plugin_isactive" => "Active", - "plugin_description" => "Description", - "plugin_author" => "Author", - "plugin_web" => "Web", - "plugin_help" => "Help", - "plugin_update" => "Update", - "plugin_activate" => "Activate", - "plugin_deactivate" => "Deactivate", - "no_plugins" => "No plugins installed", - "install_from_package" => "Install from package", - "invalid_package" => "Invalid package", - "incompatible_plugin" => "This plugin is not comatible wit this version of Ratatöskr. It requires the API version [[API]] or a compatible one.", - "plugin_safety_warning" => "<strong>Never</strong> install plugins you do not trust! Plugins have a lot of power and could potentially destroy your Ratatöskr installation!", - "plugin_src" => "Source code", - "license" => "License", - "plugin_installed_successfully" => "Plugin successfully installed.", - "successfully_deleted_plugins" => "Successfully deleted plugins.", - "plugins_activated" => "Plugins activated.", - "plugins_deactivated" => "Plugins deactivated.", - "successfully_updated_plugins" => "These plugins were updated: [[PLUGINS]]", - "nothing_to_update" => "Nothing to update.", - "add_repo" => "Add a repository", - "repo_baseurl" => "Repository base URL", - "repo_list" => "Repository List", - "repo_name" => "Name", - "repo_description" => "Description", - "no_repos" => "No repositories found.", - "force_repo_refresh" => "Force refresh", - "successfully_added_repo" => "Successfully added repository.", - "repository_unreachable_or_invalid" => "Repository is unreachable or is invalid.", - "repos_deleted" => "Repositories deleted.", - "successfully_refreshed_repos" => "Successfully refreshed.", - "repo_refresh_failed_on" => "Repository refresh failed on these repositories: [[REPOS]]", - "no_repos_add_some" => "No repositories found. You should <a href=\"[[URL]]\">add some repositories</a>.", - "install_from_repo" => "Install from repository", - "search" => "Search", - "repo_plugin_search_in" => "Search in", - "search_in_all_repos" => "all repositories", - "repo" => "Repository", - "install" => "Install", - "package_or_repo_not_found" => "Package or repository not found.", - "dbsetup_mysql_host" => "MySQL host (usually 'localhost')", - "dbsetup_mysql_user" => "MySQL Username", - "dbsetup_mysql_passwd" => "MySQL Password", - "dbsetup_mysql_database" => "MySQL Database name", - "dbsetup_table_prefix" => "Table prefix", - "dbsetup" => "Database setup", - "admin_setup" => "Administrator data", - "setup_almost_done" => "Almost done", - "setup_configfile_instructions" => "You need to change the contents of the file '/ratatoeskr/config.php' in your Ratatöskr installation to this:", - "setup_delete_setup_instructions_and_pointers" => "Also you really should delete the '/setup.php' in your Ratatöskr installation. If you have done that, you can go to your new Ratatöskr installation:", - "setup_link_yourpage" => "Your new Webpage", - "setup_link_backend" => "The backend of your Webpage", - "admin_data_must_be_filled_out" => "Administrator data must be filled out", - "enforce" => "Enforce", - "could_not_activate_plugin_api_incompat" => "Could not activate these plugins, because they are not / no longer compatible with your Ratatöskr-installation: [[PLUGINS]]", - "plugins_incompat" => "These plugins are not / no longer compatible with your Ratatöskr -installation: [[PLUGINS]]", - "could_not_initialize_repos" => "Setup is completed, but the default repositories could not be initalized.", - "debugmode" => "Debugmode", - "enabled" => "Enabled", - "disabled" => "Disabled", - "debugmode_might_get_overwritten_by_config_file" => "(this can be overwritten by config.php)", - "debugmode_now_enabled" => "Debugmode now enabled", - "debugmode_now_disabled" => "Debugmode now disabled", - /* Very long texts here */ - "linking_back_hint" => <<<LINKINGBACK + "username" => "Username", + "password" => "Password", + "login_form_header" => "Login", + "login_form_button" => "Login", + "login_background_image" => "Background image: <a href=\"[[URL]]\">[[FILENAME]]</a> by [[AUTHOR]]. License: [[LICENSE]]", + "login_failed" => "Login failed (Username/Password is wrong or you are not an admin).", + "logout" => "Logout", + "section_admin" => "Administration", + "section_content" => "Content", + "section_design" => "Design", + "section_plugins" => "Plugins", + "menu_articles" => "Articles", + "menu_comments" => "Comments", + "menu_images" => "Images", + "menu_languages" => "Languages", + "menu_newarticles" => "New Article", + "menu_pagesections" => "Page Sections", + "menu_plugin_repos" => "Plugin Repositories", + "menu_plugininstall" => "Install Plugin", + "menu_pluginlist" => "Plugin List", + "menu_settings" => "Settings", + "menu_styles" => "Styles", + "menu_tags" => "Tags", + "menu_templates" => "Templates", + "menu_users_groups" => "Users / Groups", + "new_article" => "New Article", + "articleedit_title" => "Article Title", + "articleedit_content" => "Content", + "articleedit_excerpt" => "Excerpt", + "comment_form_name" => "Your name", + "comment_form_mail" => "Your E-Mailaddress", + "comment_form_text" => "Your comment (Markdown format)", + "comment_form_submit" => "Submit comment", + "comment_form_preview" => "Preview", + "page_prev" => "<-- previous page", + "page_next" => "next page -->", + "e404_details" => "The page [[URL]] could not be found. Sorry.", + "author_name_missing" => "No author name given.", + "author_email_missing" => "No author E-Mailaddress given.", + "comment_text_missing" => "An empty comment can not be posted.", + "comment_form_invalid" => "The comment form is invalid.", + "comment_too_fast" => "This comment was written too fast. Are you a spambot?", + "article_other_languages" => "This article in other languages: ", + "save_texts_as_lang" => "Save texts as language", + "settings_meta" => "Settings / Metadata", + "urlname" => "Unique URL name", + "tags_cs" => "Tags (comma seperated)", + "date_time" => "Date / Time", + "article_status" => "Article Status", + "article_status_hidden" => "Hidden", + "article_status_live" => "Live", + "article_status_sticky" => "Sticky", + "article_section" => "Section", + "invalid_urlname" => "Invalid URL name (Can contain a-z A-Z 0-9 - and _)", + "invalid_article_status" => "Invalid article status", + "unknown_txtproc" => "Unknown Textprocessor", + "invalid_date" => "Invalid date", + "article_edit_error" => "Could not edit article.", + "unknown_section" => "Unknown section", + "allow_comments" => "Allow comments?", + "article_name_already_in_use" => "Article name is already in use.", + "article_save_success" => "Article successfully saved.", + "tags_successfully_deleted" => "Tags successfully deleted.", + "new_tag_name" => "Name", + "tags_successfully_edited" => "Successfully edited tags.", + "tags_overview" => "Tag Overview", + "tag_name" => "Tag name", + "yes" => "Yes", + "no" => "No", + "tag_add_lang" => "Add translation", + "save_changes" => "Save changes", + "language_unknown" => "Unknown language", + "translation_added_successfully" => "Translation added successfully.", + "invalid_tag_name" => "Invalid tag name. A tag name can not contain commas (,) or spaces ( ) and must not be empty.", + "available_languages" => "Available languages", + "tags" => "Tags", + "section" => "Section", + "no_articles" => "No articles stored.", + "delete" => "Delete", + "articles_deleted" => "Articles deleted.", + "sort_asc" => "ascending", + "sort_desc" => "descending", + "filter" => "Filter", + "filter_urlname" => "by URL name", + "filter_tag" => "by tag", + "filter_section" => "by section", + "image_upload" => "Upload a new image", + "img_upload_name" => "Name", + "img_upload_name_leave_empty" => "(Leave empty for default filename)", + "image_preview" => "Preview", + "image_name" => "Name", + "image_getmarkup" => "Embed code", + "no_images" => "No images stored.", + "upload_failed" => "Upload failed.", + "unknown_file_format" => "Unknown file format.", + "upload_success" => "Upload successful", + "images_deleted" => "Images deleted.", + "generate_embed_code" => "Generate embed code.", + "image_alt" => "Alternative Title", + "embed_code" => "Embed code", + "was_read" => "Read?", + "article" => "Article", + "visible" => "Visible", + "comment_excerpt" => "Comment (excerpt)", + "no_comments" => "No comments available.", + "read_more" => "Read more", + "language" => "Language", + "author" => "Author", + "filter_article" => "by Article", + "commentaction_make_invisible" => "Make invisible", + "commentaction_make_visible" => "Make visible", + "commentaction_mark_read" => "Mark as read", + "commentaction_mark_unread" => "Mark as unread", + "comments_successfully_deleted" => "Comments sucessfully deleted.", + "comments_successfully_marked_read" => "Comments successfully marked as read.", + "comments_successfully_marked_unread" => "Comments successfully marked as unread.", + "comments_successfully_made_visible" => "Comments successfully made visible.", + "comments_successfully_made_invisible" => "Comments successfully made invisible.", + "unknown_action" => "Unknown action.", + "comment_successfully_deleted" => "Comment sucessfully deleted.", + "comment_successfully_made_visible" => "Comment successfully made visible.", + "comment_successfully_made_invisible" => "Comment successfully made invisible.", + "comment_perform_action" => "Perform an action on this comment", + "comment_text" => "Comment Text", + "comment_text_raw" => "Comment Text (raw)", + "new_template" => "New Template", + "template" => "Template", + "template_name" => "Template name", + "template_code" => "Template code", + "templates_successfully_deleted" => "Templates successfully deleted", + "invalid_template_name" => "Invalid template name. Valid template names are at least 1 character long and only contains letters, numbers, underscores(_), hyphens(-) and dots(.)", + "could_not_compile_template" => "Could not compile template. Reason: ", + "template_successfully_saved" => "Template successfully saved.", + "style" => "Style", + "new_style" => "New style", + "style_name" => "Style name", + "style_code" => "Style code", + "styles_successfully_deleted" => "Styles successfully deleted", + "invalid_style_name" => "Invalid style name. Valid style names are at least 1 character long and only contains letters, numbers, underscores(_), hyphens(-) and dots(.)", + "style_successfully_saved" => "Style successfully saved.", + "new_section" => "New Section", + "section_name" => "Section name", + "section_is_default" => "Is default", + "styles" => "Styles", + "make_default" => "Make default", + "set_template" => "Set template", + "add_style" => "Add style", + "section_already_exists" => "Section already exists.", + "unknown_template" => "Unknown template", + "invalid_section_name" => "Invalid section name. Valid section names are at least 1 character long and only contains letters, numbers, underscores(_) and hyphens(-)", + "section_title" => "Title", + "set_title" => "Set Title", + "section_created_successfully" => "Section created", + "style_removed" => "Style removed", + "remove" => "Remove", + "cannot_delete_default_section" => "Can not delete default section.", + "section_successfully_deleted" => "Section successfully deleted.", + "default_section_changed_successfully" => "Default section changed successfully.", + "successfully_added_style" => "Successfully added style.", + "successfully_set_section_title" => "Successfully set title.", + "successfully_set_template" => "Successfully set template.", + "comment_textprocessor" => "Textprocessor for comments", + "language_settings" => "Language settings", + "language_code" => "Language code", + "default_language" => "Default language", + "add_language" => "Add language", + "comment_auto_visible" => "Make comments visible automatically", + "comment_settings" => "Comment settings", + "comment_settings_successfully_saved" => "Comment settings successfully saved", + "cannot_delete_default_language" => "Can not delete default language.", + "language_successfully_deleted" => "Language successfully deleted.", + "successfully_set_default_language" => "Successfully set default language.", + "language_successfully_added" => "Language successfully added.", + "new_user" => "New user", + "initial_password" => "Initial password", + "new_group" => "New Group", + "groupname" => "Group name", + "users" => "Users", + "groups" => "Groups", + "group" => "Group", + "member_of_groups" => "Member of these groups", + "cannot_delete_admin_group" => "Can not delete admin group.", + "successfully_deleted_groups" => "Successfully deleted groups.", + "empty_group_name" => "Can not create group: Empty group name.", + "group_already_exists" => "Group already exists.", + "successfully_created_group" => "Successfully created group.", + "empty_username" => "Can not create user: Empty username.", + "user_already_exists" => "User already exists.", + "successfully_created_user" => "Successfully created user.", + "cannot_delete_yourself" => "You can not delete yourself.", + "successfully_deleted_users" => "Successfully deleted users.", + "fullname" => "Full name", + "mail_address" => "Mail Address", + "new_password" => "New password", + "successfully_modified_user" => "Successfully modified user.", + "successfully_set_new_password" => "Successfully set new password.", + "plugin_name" => "Name", + "plugin_version" => "Version", + "plugin_isactive" => "Active", + "plugin_description" => "Description", + "plugin_author" => "Author", + "plugin_web" => "Web", + "plugin_help" => "Help", + "plugin_update" => "Update", + "plugin_activate" => "Activate", + "plugin_deactivate" => "Deactivate", + "no_plugins" => "No plugins installed", + "install_from_package" => "Install from package", + "invalid_package" => "Invalid package", + "incompatible_plugin" => "This plugin is not comatible wit this version of Ratatöskr. It requires the API version [[API]] or a compatible one.", + "plugin_safety_warning" => "<strong>Never</strong> install plugins you do not trust! Plugins have a lot of power and could potentially destroy your Ratatöskr installation!", + "plugin_src" => "Source code", + "license" => "License", + "plugin_installed_successfully" => "Plugin successfully installed.", + "successfully_deleted_plugins" => "Successfully deleted plugins.", + "plugins_activated" => "Plugins activated.", + "plugins_deactivated" => "Plugins deactivated.", + "successfully_updated_plugins" => "These plugins were updated: [[PLUGINS]]", + "nothing_to_update" => "Nothing to update.", + "add_repo" => "Add a repository", + "repo_baseurl" => "Repository base URL", + "repo_list" => "Repository List", + "repo_name" => "Name", + "repo_description" => "Description", + "no_repos" => "No repositories found.", + "force_repo_refresh" => "Force refresh", + "successfully_added_repo" => "Successfully added repository.", + "repository_unreachable_or_invalid" => "Repository is unreachable or is invalid.", + "repos_deleted" => "Repositories deleted.", + "successfully_refreshed_repos" => "Successfully refreshed.", + "repo_refresh_failed_on" => "Repository refresh failed on these repositories: [[REPOS]]", + "no_repos_add_some" => "No repositories found. You should <a href=\"[[URL]]\">add some repositories</a>.", + "install_from_repo" => "Install from repository", + "search" => "Search", + "repo_plugin_search_in" => "Search in", + "search_in_all_repos" => "all repositories", + "repo" => "Repository", + "install" => "Install", + "package_or_repo_not_found" => "Package or repository not found.", + "dbsetup_mysql_host" => "MySQL host (usually 'localhost')", + "dbsetup_mysql_user" => "MySQL Username", + "dbsetup_mysql_passwd" => "MySQL Password", + "dbsetup_mysql_database" => "MySQL Database name", + "dbsetup_table_prefix" => "Table prefix", + "dbsetup" => "Database setup", + "admin_setup" => "Administrator data", + "setup_almost_done" => "Almost done", + "setup_configfile_instructions" => "You need to change the contents of the file '/ratatoeskr/config.php' in your Ratatöskr installation to this:", + "setup_delete_setup_instructions_and_pointers" => "Also you really should delete the '/setup.php' in your Ratatöskr installation. If you have done that, you can go to your new Ratatöskr installation:", + "setup_link_yourpage" => "Your new Webpage", + "setup_link_backend" => "The backend of your Webpage", + "admin_data_must_be_filled_out" => "Administrator data must be filled out", + "enforce" => "Enforce", + "could_not_activate_plugin_api_incompat" => "Could not activate these plugins, because they are not / no longer compatible with your Ratatöskr-installation: [[PLUGINS]]", + "plugins_incompat" => "These plugins are not / no longer compatible with your Ratatöskr -installation: [[PLUGINS]]", + "could_not_initialize_repos" => "Setup is completed, but the default repositories could not be initalized.", + "debugmode" => "Debugmode", + "enabled" => "Enabled", + "disabled" => "Disabled", + "debugmode_might_get_overwritten_by_config_file" => "(this can be overwritten by config.php)", + "debugmode_now_enabled" => "Debugmode now enabled", + "debugmode_now_disabled" => "Debugmode now disabled", + /* Very long texts here */ + "linking_back_hint" => <<<LINKINGBACK <h2>Linking back</h2> <p>The text <code>%root%</code> will be replaced with a path, that points to the root of your Ratatöskr page.</p> LINKINGBACK - ,"content_write_cheatsheet" => <<<CHEATSHEET + ,"content_write_cheatsheet" => <<<CHEATSHEET <h2>Markdown Cheat Sheet</h2> <h3>Emphasis / Strong</h3> <p> - <code>*<em>emphasis</em>*</code><br /> - <code>_<em>emphasis</em>_</code><br /> - <code>**<strong>strong</strong>**</code><br /> - <code>__<strong>strong</strong>__</code> + <code>*<em>emphasis</em>*</code><br /> + <code>_<em>emphasis</em>_</code><br /> + <code>**<strong>strong</strong>**</code><br /> + <code>__<strong>strong</strong>__</code> </p> <h3>Paragraphs and manual line breaks.</h3> <p> - <code>First Paragraph<br /> + <code>First Paragraph<br /> <br /> Second Paragraph with<br /> long<br /> @@ -293,7 +293,7 @@ end a line with two whitespaces.</code> <h3>Headers</h3> <p> - <code>Header 1<br /> + <code>Header 1<br /> ========<br /> <br /> Header 2<br /> @@ -310,22 +310,22 @@ Header 2<br /> <h3>Linking</h3> <p> - <code>[Linktext](http://url/to/resource "Optional title")</code> + <code>[Linktext](http://url/to/resource "Optional title")</code> </p> <p> - <code>[Linktext][id]. Somewhere else:<br /> + <code>[Linktext][id]. Somewhere else:<br /> <br /> [id]: http://url/to/resource "Optional title"</code> </p> <h3>Images</h3> <p> - <code>![alt text](/path/to/image "Optional title")</code> + <code>![alt text](/path/to/image "Optional title")</code> </p> <h3>Ordered / Unordered Lists</h3> <p> - <code>* Item A<br /> + <code>* Item A<br /> * Item B<br /> <br /> With a second paragraph.<br /> @@ -335,15 +335,15 @@ Header 2<br /> * Item C2<br /></code> </p> <p> - <code>1. First element<br /> + <code>1. First element<br /> 2. Second Element </code> </p> <h3>Learn More</h3> <p> - <a href="http://daringfireball.net/projects/markdown/syntax">Complete Syntax</a><br /> - <a href="http://daringfireball.net/projects/markdown/dingus">Test Markdown</a> + <a href="http://daringfireball.net/projects/markdown/syntax">Complete Syntax</a><br /> + <a href="http://daringfireball.net/projects/markdown/dingus">Test Markdown</a> </p> CHEATSHEET ); |