forked from Cavemanon/cavepaintings
lots of minor doc tweaks, type hints, etc
This commit is contained in:
parent
edd3e49a2f
commit
dc10a18086
@ -11,8 +11,14 @@
|
||||
# Shimmie
|
||||
|
||||
[![Build Status](https://travis-ci.org/shish/shimmie2.svg?branch=master)](https://travis-ci.org/shish/shimmie2)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/shish/shimmie2/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master)
|
||||
[![Code Coverage](https://scrutinizer-ci.com/g/shish/shimmie2/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/shish/shimmie2/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master)
|
||||
[![Code Coverage](https://scrutinizer-ci.com/g/shish/shimmie2/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master)
|
||||
(master)
|
||||
|
||||
[![Build Status](https://travis-ci.org/shish/shimmie2.svg?branch=develop)](https://travis-ci.org/shish/shimmie2)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/shish/shimmie2/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=develop)
|
||||
[![Code Coverage](https://scrutinizer-ci.com/g/shish/shimmie2/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=develop)
|
||||
(develop)
|
||||
|
||||
This is the main branch of Shimmie, if you know anything at all about running
|
||||
websites, this is the version to use.
|
||||
@ -23,14 +29,14 @@ check out one of the versioned branches.
|
||||
# Requirements
|
||||
|
||||
- MySQL/MariaDB 5.1+ (with experimental support for PostgreSQL 9+ and SQLite 3)
|
||||
- PHP 5.4.8+
|
||||
- Stable PHP ([5.5 as of writing](https://en.wikipedia.org/wiki/PHP#Release_history))
|
||||
- GD or ImageMagick
|
||||
|
||||
# Installation
|
||||
|
||||
1. Download the latest release under [Releases](https://github.com/shish/shimmie2/releases).
|
||||
2. Create a blank database
|
||||
3. Unzip shimmie into a folder on the web host
|
||||
2. Unzip shimmie into a folder on the web host
|
||||
3. Create a blank database
|
||||
4. Visit the folder with a web browser
|
||||
5. Enter the location of the database
|
||||
6. Click "install". Hopefully you'll end up at the welcome screen; if
|
||||
@ -43,7 +49,7 @@ check out one of the versioned branches.
|
||||
3. Install [Composer](https://getcomposer.org/). (If you don't already have it)
|
||||
4. Run `composer global require "fxp/composer-asset-plugin:~1.1" --no-plugins`. (This is installed globally due to a known composer bug)
|
||||
5. Run `composer install` in the shimmie folder.
|
||||
6. Follow instructions noted in "Installation" (Excluding 1 & 3).
|
||||
6. Follow instructions noted in "Installation" starting from step 3.
|
||||
|
||||
## Upgrade from 2.3.X
|
||||
|
||||
@ -155,7 +161,7 @@ Issue/Bug tracker: http://github.com/shish/shimmie2/issues
|
||||
|
||||
All code is released under the [GNU GPL Version 2](http://www.gnu.org/licenses/gpl-2.0.html) unless mentioned otherwise.
|
||||
|
||||
If you give shimmie to someone else, you have to give them the source (which should be easy, as PHP
|
||||
is an interpreted language...). If you want to add customisations to your own
|
||||
site, then those customisations belong to you, and you can do what you want
|
||||
with them.
|
||||
If you give shimmie to someone else, you have to give them the source (which
|
||||
should be easy, as PHP is an interpreted language...). If you want to add
|
||||
customisations to your own site, then those customisations belong to you,
|
||||
and you can do what you want with them.
|
||||
|
@ -166,8 +166,15 @@ function xml_tag($name, $attrs=array(), $children=array()) {
|
||||
return $xml;
|
||||
}
|
||||
|
||||
// Original PHP code by Chirp Internet: www.chirp.com.au
|
||||
// Please acknowledge use of this code by including this header.
|
||||
/**
|
||||
* Original PHP code by Chirp Internet: www.chirp.com.au
|
||||
* Please acknowledge use of this code by including this header.
|
||||
*
|
||||
* @param string $string input data
|
||||
* @param int $limit how long the string should be
|
||||
* @param string $break where to break the string
|
||||
* @param string $pad what to add to the end of the string after truncating
|
||||
*/
|
||||
function truncate($string, $limit, $break=" ", $pad="...") {
|
||||
// return with no change if string is shorter than $limit
|
||||
if(strlen($string) <= $limit) return $string;
|
||||
@ -1031,8 +1038,8 @@ if (!function_exists('http_parse_headers')) { #http://www.php.net/manual/en/func
|
||||
* In cases like these, we need to make sure to check for them if the camelcase version does not exist.
|
||||
*
|
||||
* @param array $headers
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
* @param string $name
|
||||
* @return string|bool
|
||||
*/
|
||||
function findHeader ($headers, $name) {
|
||||
if (!is_array($headers)) {
|
||||
@ -1441,6 +1448,10 @@ function _set_event_listeners() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $event_listeners
|
||||
* @param string $path
|
||||
*/
|
||||
function _dump_event_listeners($event_listeners, $path) {
|
||||
$p = "<"."?php\n";
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
<?php
|
||||
|
||||
class ExtManagerTheme extends Themelet {
|
||||
/**
|
||||
* @param Page $page
|
||||
* @param Extension[] $extensions
|
||||
* @param bool $editable
|
||||
*/
|
||||
public function display_table(Page $page, /*array*/ $extensions, /*bool*/ $editable) {
|
||||
$h_en = $editable ? "<th>Enabled</th>" : "";
|
||||
$html = "
|
||||
|
@ -87,328 +87,347 @@ class Forum extends Extension {
|
||||
|
||||
|
||||
public function onPageRequest(PageRequestEvent $event) {
|
||||
global $page, $user;
|
||||
|
||||
if($event->page_matches("forum")) {
|
||||
switch($event->get_arg(0)) {
|
||||
case "index":
|
||||
{
|
||||
$this->show_last_threads($page, $event, $user->is_admin());
|
||||
if(!$user->is_anonymous()) $this->theme->display_new_thread_composer($page);
|
||||
break;
|
||||
}
|
||||
case "view":
|
||||
{
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
$pageNumber = int_escape($event->get_arg(2));
|
||||
list($errors) = $this->sanity_check_viewed_thread($threadID);
|
||||
|
||||
global $page, $user;
|
||||
|
||||
if($event->page_matches("forum")) {
|
||||
switch($event->get_arg(0)) {
|
||||
case "index":
|
||||
$this->show_last_threads($page, $event, $user->is_admin());
|
||||
if(!$user->is_anonymous()) $this->theme->display_new_thread_composer($page);
|
||||
break;
|
||||
case "view":
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
$pageNumber = int_escape($event->get_arg(2));
|
||||
list($errors) = $this->sanity_check_viewed_thread($threadID);
|
||||
|
||||
if($errors!=null)
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->show_posts($event, $user->is_admin());
|
||||
if($user->is_admin()) $this->theme->add_actions_block($page, $threadID);
|
||||
if(!$user->is_anonymous()) $this->theme->display_new_post_composer($page, $threadID);
|
||||
break;
|
||||
case "new":
|
||||
global $page;
|
||||
$this->theme->display_new_thread_composer($page);
|
||||
break;
|
||||
case "create":
|
||||
$redirectTo = "forum/index";
|
||||
if (!$user->is_anonymous())
|
||||
{
|
||||
list($errors) = $this->sanity_check_new_thread();
|
||||
|
||||
if($errors!=null)
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->show_posts($event, $user->is_admin());
|
||||
if($user->is_admin()) $this->theme->add_actions_block($page, $threadID);
|
||||
if(!$user->is_anonymous()) $this->theme->display_new_post_composer($page, $threadID);
|
||||
break;
|
||||
}
|
||||
case "new":
|
||||
{
|
||||
global $page;
|
||||
$this->theme->display_new_thread_composer($page);
|
||||
break;
|
||||
}
|
||||
case "create":
|
||||
{
|
||||
$redirectTo = "forum/index";
|
||||
if (!$user->is_anonymous())
|
||||
{
|
||||
list($errors) = $this->sanity_check_new_thread();
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
|
||||
if($errors!=null)
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
$newThreadID = $this->save_new_thread($user);
|
||||
$this->save_new_post($newThreadID, $user);
|
||||
$redirectTo = "forum/view/".$newThreadID."/1";
|
||||
}
|
||||
|
||||
$newThreadID = $this->save_new_thread($user);
|
||||
$this->save_new_post($newThreadID, $user);
|
||||
$redirectTo = "forum/view/".$newThreadID."/1";
|
||||
}
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link($redirectTo));
|
||||
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link($redirectTo));
|
||||
break;
|
||||
case "delete":
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
$postID = int_escape($event->get_arg(2));
|
||||
|
||||
break;
|
||||
}
|
||||
case "delete":
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
$postID = int_escape($event->get_arg(2));
|
||||
if ($user->is_admin()) {$this->delete_post($postID);}
|
||||
|
||||
if ($user->is_admin()) {$this->delete_post($postID);}
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/view/".$threadID));
|
||||
break;
|
||||
case "nuke":
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/view/".$threadID));
|
||||
break;
|
||||
case "nuke":
|
||||
$threadID = int_escape($event->get_arg(1));
|
||||
if ($user->is_admin())
|
||||
$this->delete_thread($threadID);
|
||||
|
||||
if ($user->is_admin())
|
||||
$this->delete_thread($threadID);
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/index"));
|
||||
break;
|
||||
case "answer":
|
||||
$threadID = int_escape($_POST["threadID"]);
|
||||
$total_pages = $this->get_total_pages_for_thread($threadID);
|
||||
if (!$user->is_anonymous())
|
||||
{
|
||||
list($errors) = $this->sanity_check_new_post();
|
||||
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/index"));
|
||||
break;
|
||||
case "answer":
|
||||
$threadID = int_escape($_POST["threadID"]);
|
||||
$total_pages = $this->get_total_pages_for_thread($threadID);
|
||||
if (!$user->is_anonymous())
|
||||
{
|
||||
list($errors) = $this->sanity_check_new_post();
|
||||
|
||||
if ($errors!=null)
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
$this->save_new_post($threadID, $user);
|
||||
}
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/view/".$threadID."/".$total_pages));
|
||||
break;
|
||||
default:
|
||||
{
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/index"));
|
||||
//$this->theme->display_error(400, "Invalid action", "You should check forum/index.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function get_total_pages_for_thread(/*int*/ $threadID)
|
||||
{
|
||||
global $database, $config;
|
||||
$result = $database->get_row("SELECT COUNT(1) AS count FROM forum_posts WHERE thread_id = ?", array($threadID));
|
||||
|
||||
return ceil($result["count"] / $config->get_int("forumPostsPerPage"));
|
||||
}
|
||||
|
||||
private function sanity_check_new_thread()
|
||||
{
|
||||
$errors = null;
|
||||
if (!array_key_exists("title", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No title supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["title"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty title.</div>";
|
||||
}
|
||||
else if (strlen(html_escape($_POST["title"])) > 255)
|
||||
{
|
||||
$errors .= "<div id='error'>Your title is too long.</div>";
|
||||
}
|
||||
|
||||
if (!array_key_exists("message", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No message supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["message"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty message.</div>";
|
||||
}
|
||||
|
||||
return array($errors);
|
||||
}
|
||||
private function sanity_check_new_post()
|
||||
{
|
||||
$errors = null;
|
||||
if (!array_key_exists("threadID", $_POST))
|
||||
{
|
||||
$errors = "<div id='error'>No thread ID supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["threadID"]) == 0)
|
||||
{
|
||||
$errors = "<div id='error'>No thread ID supplied.</div>";
|
||||
}
|
||||
else if (is_numeric($_POST["threadID"]))
|
||||
|
||||
if (!array_key_exists("message", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No message supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["message"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty message.</div>";
|
||||
}
|
||||
|
||||
return array($errors);
|
||||
}
|
||||
private function sanity_check_viewed_thread($threadID)
|
||||
{
|
||||
$errors = null;
|
||||
if (!$this->threadExists($threadID))
|
||||
{
|
||||
$errors = "<div id='error'>Inexistent thread.</div>";
|
||||
}
|
||||
return array($errors);
|
||||
}
|
||||
private function get_thread_title($threadID)
|
||||
{
|
||||
global $database;
|
||||
$result = $database->get_row("SELECT t.title FROM forum_threads AS t WHERE t.id = ? ", array($threadID));
|
||||
return $result["title"];
|
||||
}
|
||||
|
||||
private function show_last_threads(Page $page, $event, $showAdminOptions = false)
|
||||
{
|
||||
global $config, $database;
|
||||
$pageNumber = $event->get_arg(1);
|
||||
$threadsPerPage = $config->get_int('forumThreadsPerPage', 15);
|
||||
$totalPages = ceil($database->get_one("SELECT COUNT(*) FROM forum_threads") / $threadsPerPage);
|
||||
|
||||
if(is_null($pageNumber) || !is_numeric($pageNumber))
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber <= 0)
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber >= $totalPages)
|
||||
$pageNumber = $totalPages - 1;
|
||||
else
|
||||
$pageNumber--;
|
||||
|
||||
$threads = $database->get_all(
|
||||
"SELECT f.id, f.sticky, f.title, f.date, f.uptodate, u.name AS user_name, u.email AS user_email, u.class AS user_class, sum(1) - 1 AS response_count ".
|
||||
"FROM forum_threads AS f ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON f.user_id = u.id ".
|
||||
"INNER JOIN forum_posts AS p ".
|
||||
"ON p.thread_id = f.id ".
|
||||
"GROUP BY f.id, f.sticky, f.title, f.date, u.name, u.email, u.class ".
|
||||
"ORDER BY f.sticky ASC, f.uptodate DESC LIMIT :limit OFFSET :offset"
|
||||
, array("limit"=>$threadsPerPage, "offset"=>$pageNumber * $threadsPerPage)
|
||||
);
|
||||
|
||||
$this->theme->display_thread_list($page, $threads, $showAdminOptions, $pageNumber + 1, $totalPages);
|
||||
}
|
||||
|
||||
private function show_posts($event, $showAdminOptions = false)
|
||||
{
|
||||
global $config, $database;
|
||||
$threadID = $event->get_arg(1);
|
||||
$pageNumber = $event->get_arg(2);
|
||||
$postsPerPage = $config->get_int('forumPostsPerPage', 15);
|
||||
$totalPages = ceil($database->get_one("SELECT COUNT(*) FROM forum_posts WHERE thread_id = ?", array($threadID)) / $postsPerPage);
|
||||
$threadTitle = $this->get_thread_title($threadID);
|
||||
|
||||
if(is_null($pageNumber) || !is_numeric($pageNumber))
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber <= 0)
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber >= $totalPages)
|
||||
$pageNumber = $totalPages - 1;
|
||||
else
|
||||
$pageNumber--;
|
||||
|
||||
$posts = $database->get_all(
|
||||
"SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class ".
|
||||
"FROM forum_posts AS p ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON p.user_id = u.id ".
|
||||
"WHERE thread_id = :thread_id ".
|
||||
"ORDER BY p.date ASC ".
|
||||
"LIMIT :limit OFFSET :offset"
|
||||
, array("thread_id"=>$threadID, "offset"=>$pageNumber * $postsPerPage, "limit"=>$postsPerPage)
|
||||
);
|
||||
$this->theme->display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber + 1, $totalPages);
|
||||
}
|
||||
|
||||
private function save_new_thread($user)
|
||||
{
|
||||
$title = html_escape($_POST["title"]);
|
||||
$sticky = !empty($_POST["sticky"]) ? html_escape($_POST["sticky"]) : "N";
|
||||
|
||||
if($sticky == ""){
|
||||
$sticky = "N";
|
||||
}
|
||||
|
||||
global $database;
|
||||
$database->execute("
|
||||
INSERT INTO forum_threads
|
||||
(title, sticky, user_id, date, uptodate)
|
||||
VALUES
|
||||
(?, ?, ?, now(), now())",
|
||||
array($title, $sticky, $user->id));
|
||||
|
||||
$threadID = $database->get_last_insert_id("forum_threads_id_seq");
|
||||
|
||||
log_info("forum", "Thread {$threadID} created by {$user->name}");
|
||||
|
||||
return $threadID;
|
||||
}
|
||||
|
||||
private function save_new_post($threadID, $user)
|
||||
{
|
||||
global $config;
|
||||
$userID = $user->id;
|
||||
$message = html_escape($_POST["message"]);
|
||||
|
||||
$max_characters = $config->get_int('forumMaxCharsPerPost');
|
||||
$message = substr($message, 0, $max_characters);
|
||||
|
||||
global $database;
|
||||
$database->execute("INSERT INTO forum_posts
|
||||
(thread_id, user_id, date, message)
|
||||
VALUES
|
||||
(?, ?, now(), ?)"
|
||||
, array($threadID, $userID, $message));
|
||||
|
||||
$postID = $database->get_last_insert_id("forum_posts_id_seq");
|
||||
|
||||
log_info("forum", "Post {$postID} created by {$user->name}");
|
||||
|
||||
$database->execute("UPDATE forum_threads SET uptodate=now() WHERE id=?", array ($threadID));
|
||||
}
|
||||
|
||||
private function retrieve_posts($threadID, $pageNumber)
|
||||
{
|
||||
global $database, $config;
|
||||
$postsPerPage = $config->get_int('forumPostsPerPage', 15);
|
||||
|
||||
return $database->get_all(
|
||||
"SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class ".
|
||||
"FROM forum_posts AS p ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON p.user_id = u.id ".
|
||||
"WHERE thread_id = :thread_id ".
|
||||
"ORDER BY p.date ASC ".
|
||||
"LIMIT :limit OFFSET :offset "
|
||||
, array("thread_id"=>$threadID, "offset"=>($pageNumber - 1) * $postsPerPage, "limit"=>$postsPerPage));
|
||||
}
|
||||
|
||||
private function delete_thread($threadID)
|
||||
{
|
||||
global $database;
|
||||
$database->execute("DELETE FROM forum_threads WHERE id = ?", array($threadID));
|
||||
$database->execute("DELETE FROM forum_posts WHERE thread_id = ?", array($threadID));
|
||||
}
|
||||
|
||||
private function delete_post($postID)
|
||||
{
|
||||
global $database;
|
||||
$database->execute("DELETE FROM forum_posts WHERE id = ?", array($postID));
|
||||
}
|
||||
private function threadExists($threadID){
|
||||
global $database;
|
||||
$result=$database->get_one("SELECT EXISTS (SELECT * FROM forum_threads WHERE id= ?)", array($threadID));
|
||||
if ($result==1){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
if ($errors!=null)
|
||||
{
|
||||
$this->theme->display_error(500, "Error", $errors);
|
||||
break;
|
||||
}
|
||||
$this->save_new_post($threadID, $user);
|
||||
}
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/view/".$threadID."/".$total_pages));
|
||||
break;
|
||||
default:
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("forum/index"));
|
||||
//$this->theme->display_error(400, "Invalid action", "You should check forum/index.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function get_total_pages_for_thread($threadID)
|
||||
{
|
||||
global $database, $config;
|
||||
$result = $database->get_row("SELECT COUNT(1) AS count FROM forum_posts WHERE thread_id = ?", array($threadID));
|
||||
|
||||
return ceil($result["count"] / $config->get_int("forumPostsPerPage"));
|
||||
}
|
||||
|
||||
private function sanity_check_new_thread()
|
||||
{
|
||||
$errors = null;
|
||||
if (!array_key_exists("title", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No title supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["title"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty title.</div>";
|
||||
}
|
||||
else if (strlen(html_escape($_POST["title"])) > 255)
|
||||
{
|
||||
$errors .= "<div id='error'>Your title is too long.</div>";
|
||||
}
|
||||
|
||||
if (!array_key_exists("message", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No message supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["message"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty message.</div>";
|
||||
}
|
||||
|
||||
return array($errors);
|
||||
}
|
||||
|
||||
private function sanity_check_new_post()
|
||||
{
|
||||
$errors = null;
|
||||
if (!array_key_exists("threadID", $_POST))
|
||||
{
|
||||
$errors = "<div id='error'>No thread ID supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["threadID"]) == 0)
|
||||
{
|
||||
$errors = "<div id='error'>No thread ID supplied.</div>";
|
||||
}
|
||||
else if (is_numeric($_POST["threadID"]))
|
||||
|
||||
if (!array_key_exists("message", $_POST))
|
||||
{
|
||||
$errors .= "<div id='error'>No message supplied.</div>";
|
||||
}
|
||||
else if (strlen($_POST["message"]) == 0)
|
||||
{
|
||||
$errors .= "<div id='error'>You cannot have an empty message.</div>";
|
||||
}
|
||||
|
||||
return array($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function sanity_check_viewed_thread($threadID)
|
||||
{
|
||||
$errors = null;
|
||||
if (!$this->threadExists($threadID))
|
||||
{
|
||||
$errors = "<div id='error'>Inexistent thread.</div>";
|
||||
}
|
||||
return array($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function get_thread_title($threadID)
|
||||
{
|
||||
global $database;
|
||||
$result = $database->get_row("SELECT t.title FROM forum_threads AS t WHERE t.id = ? ", array($threadID));
|
||||
return $result["title"];
|
||||
}
|
||||
|
||||
private function show_last_threads(Page $page, PageRequestEvent $event, $showAdminOptions = false)
|
||||
{
|
||||
global $config, $database;
|
||||
$pageNumber = $event->get_arg(1);
|
||||
$threadsPerPage = $config->get_int('forumThreadsPerPage', 15);
|
||||
$totalPages = ceil($database->get_one("SELECT COUNT(*) FROM forum_threads") / $threadsPerPage);
|
||||
|
||||
if(is_null($pageNumber) || !is_numeric($pageNumber))
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber <= 0)
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber >= $totalPages)
|
||||
$pageNumber = $totalPages - 1;
|
||||
else
|
||||
$pageNumber--;
|
||||
|
||||
$threads = $database->get_all(
|
||||
"SELECT f.id, f.sticky, f.title, f.date, f.uptodate, u.name AS user_name, u.email AS user_email, u.class AS user_class, sum(1) - 1 AS response_count ".
|
||||
"FROM forum_threads AS f ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON f.user_id = u.id ".
|
||||
"INNER JOIN forum_posts AS p ".
|
||||
"ON p.thread_id = f.id ".
|
||||
"GROUP BY f.id, f.sticky, f.title, f.date, u.name, u.email, u.class ".
|
||||
"ORDER BY f.sticky ASC, f.uptodate DESC LIMIT :limit OFFSET :offset"
|
||||
, array("limit"=>$threadsPerPage, "offset"=>$pageNumber * $threadsPerPage)
|
||||
);
|
||||
|
||||
$this->theme->display_thread_list($page, $threads, $showAdminOptions, $pageNumber + 1, $totalPages);
|
||||
}
|
||||
|
||||
private function show_posts(PageRequestEvent $event, $showAdminOptions = false)
|
||||
{
|
||||
global $config, $database;
|
||||
$threadID = $event->get_arg(1);
|
||||
$pageNumber = $event->get_arg(2);
|
||||
$postsPerPage = $config->get_int('forumPostsPerPage', 15);
|
||||
$totalPages = ceil($database->get_one("SELECT COUNT(*) FROM forum_posts WHERE thread_id = ?", array($threadID)) / $postsPerPage);
|
||||
$threadTitle = $this->get_thread_title($threadID);
|
||||
|
||||
if(is_null($pageNumber) || !is_numeric($pageNumber))
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber <= 0)
|
||||
$pageNumber = 0;
|
||||
else if ($pageNumber >= $totalPages)
|
||||
$pageNumber = $totalPages - 1;
|
||||
else
|
||||
$pageNumber--;
|
||||
|
||||
$posts = $database->get_all(
|
||||
"SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class ".
|
||||
"FROM forum_posts AS p ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON p.user_id = u.id ".
|
||||
"WHERE thread_id = :thread_id ".
|
||||
"ORDER BY p.date ASC ".
|
||||
"LIMIT :limit OFFSET :offset"
|
||||
, array("thread_id"=>$threadID, "offset"=>$pageNumber * $postsPerPage, "limit"=>$postsPerPage)
|
||||
);
|
||||
$this->theme->display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber + 1, $totalPages);
|
||||
}
|
||||
|
||||
private function save_new_thread(User $user)
|
||||
{
|
||||
$title = html_escape($_POST["title"]);
|
||||
$sticky = !empty($_POST["sticky"]) ? html_escape($_POST["sticky"]) : "N";
|
||||
|
||||
if($sticky == ""){
|
||||
$sticky = "N";
|
||||
}
|
||||
|
||||
global $database;
|
||||
$database->execute("
|
||||
INSERT INTO forum_threads
|
||||
(title, sticky, user_id, date, uptodate)
|
||||
VALUES
|
||||
(?, ?, ?, now(), now())",
|
||||
array($title, $sticky, $user->id));
|
||||
|
||||
$threadID = $database->get_last_insert_id("forum_threads_id_seq");
|
||||
|
||||
log_info("forum", "Thread {$threadID} created by {$user->name}");
|
||||
|
||||
return $threadID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function save_new_post($threadID, User $user)
|
||||
{
|
||||
global $config;
|
||||
$userID = $user->id;
|
||||
$message = html_escape($_POST["message"]);
|
||||
|
||||
$max_characters = $config->get_int('forumMaxCharsPerPost');
|
||||
$message = substr($message, 0, $max_characters);
|
||||
|
||||
global $database;
|
||||
$database->execute("INSERT INTO forum_posts
|
||||
(thread_id, user_id, date, message)
|
||||
VALUES
|
||||
(?, ?, now(), ?)"
|
||||
, array($threadID, $userID, $message));
|
||||
|
||||
$postID = $database->get_last_insert_id("forum_posts_id_seq");
|
||||
|
||||
log_info("forum", "Post {$postID} created by {$user->name}");
|
||||
|
||||
$database->execute("UPDATE forum_threads SET uptodate=now() WHERE id=?", array ($threadID));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
* @param int $pageNumber
|
||||
*/
|
||||
private function retrieve_posts($threadID, $pageNumber)
|
||||
{
|
||||
global $database, $config;
|
||||
$postsPerPage = $config->get_int('forumPostsPerPage', 15);
|
||||
|
||||
return $database->get_all(
|
||||
"SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class ".
|
||||
"FROM forum_posts AS p ".
|
||||
"INNER JOIN users AS u ".
|
||||
"ON p.user_id = u.id ".
|
||||
"WHERE thread_id = :thread_id ".
|
||||
"ORDER BY p.date ASC ".
|
||||
"LIMIT :limit OFFSET :offset "
|
||||
, array("thread_id"=>$threadID, "offset"=>($pageNumber - 1) * $postsPerPage, "limit"=>$postsPerPage));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function delete_thread($threadID)
|
||||
{
|
||||
global $database;
|
||||
$database->execute("DELETE FROM forum_threads WHERE id = ?", array($threadID));
|
||||
$database->execute("DELETE FROM forum_posts WHERE thread_id = ?", array($threadID));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $postID
|
||||
*/
|
||||
private function delete_post($postID)
|
||||
{
|
||||
global $database;
|
||||
$database->execute("DELETE FROM forum_posts WHERE id = ?", array($postID));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threadID
|
||||
*/
|
||||
private function threadExists($threadID)
|
||||
{
|
||||
global $database;
|
||||
$result=$database->get_one("SELECT EXISTS (SELECT * FROM forum_threads WHERE id= ?)", array($threadID));
|
||||
if ($result==1){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ class MiniSVGParser {
|
||||
/** @var int */
|
||||
public $height=0;
|
||||
|
||||
/** @param string $file */
|
||||
function __construct($file) {
|
||||
$xml_parser = xml_parser_create();
|
||||
xml_set_element_handler($xml_parser, array($this, "startElement"), array($this, "endElement"));
|
||||
|
@ -133,7 +133,7 @@ class VideoFileHandler extends DataHandlerExtension {
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param mixed[] $metadata
|
||||
* @return Image|null
|
||||
* @return Image
|
||||
*/
|
||||
protected function create_image_from_data($filename, $metadata) {
|
||||
|
||||
|
@ -587,9 +587,9 @@ class OuroborosAPI extends Extension
|
||||
|
||||
/**
|
||||
* Wrapper for getting a list of posts
|
||||
* @param $limit
|
||||
* @param $page
|
||||
* @param $tags
|
||||
* @param int $limit
|
||||
* @param int $page
|
||||
* @param string[] $tags
|
||||
*/
|
||||
protected function postIndex($limit, $page, $tags)
|
||||
{
|
||||
@ -611,13 +611,13 @@ class OuroborosAPI extends Extension
|
||||
|
||||
/**
|
||||
* Wrapper for getting a list of tags
|
||||
* @param $limit
|
||||
* @param $page
|
||||
* @param $order
|
||||
* @param $id
|
||||
* @param $after_id
|
||||
* @param $name
|
||||
* @param $name_pattern
|
||||
* @param int $limit
|
||||
* @param int $page
|
||||
* @param string $order
|
||||
* @param int $id
|
||||
* @param int $after_id
|
||||
* @param string $name
|
||||
* @param string $name_pattern
|
||||
*/
|
||||
protected function tagIndex($limit, $page, $order, $id, $after_id, $name, $name_pattern)
|
||||
{
|
||||
@ -830,7 +830,7 @@ class OuroborosAPI extends Extension
|
||||
|
||||
/**
|
||||
* Helper for matching API methods from event
|
||||
* @param $page
|
||||
* @param string $page
|
||||
* @return bool
|
||||
*/
|
||||
private function match($page)
|
||||
|
@ -18,6 +18,7 @@
|
||||
class ImageResizeException extends SCoreException {
|
||||
var $error;
|
||||
|
||||
/** @param string $error */
|
||||
public function __construct($error) {
|
||||
$this->error = $error;
|
||||
}
|
||||
@ -282,7 +283,7 @@ class ResizeImage extends Extension {
|
||||
* Check Memory usage limits
|
||||
*
|
||||
* Old check: $memory_use = (filesize($image_filename)*2) + ($width*$height*4) + (4*1024*1024);
|
||||
* New check: memory_use = width * height * (bits per channel) * channels * 2.5
|
||||
* New check: $memory_use = $width * $height * ($bits_per_channel) * channels * 2.5
|
||||
*
|
||||
* It didn't make sense to compute the memory usage based on the NEW size for the image. ($width*$height*4)
|
||||
* We need to consider the size that we are GOING TO instead.
|
||||
@ -290,24 +291,25 @@ class ResizeImage extends Extension {
|
||||
* The factor of 2.5 is simply a rough guideline.
|
||||
* http://stackoverflow.com/questions/527532/reasonable-php-memory-limit-for-image-resize
|
||||
*
|
||||
* @param $info
|
||||
* @param mixed[] $info
|
||||
* @return int
|
||||
*/
|
||||
private function calc_memory_use($info) {
|
||||
if (isset($info['bits']) && isset($info['channels'])) {
|
||||
return $memory_use = ($info[0] * $info[1] * ($info['bits'] / 8) * $info['channels'] * 2.5) / 1024;
|
||||
$memory_use = ($info[0] * $info[1] * ($info['bits'] / 8) * $info['channels'] * 2.5) / 1024;
|
||||
}
|
||||
else {
|
||||
// If we don't have bits and channel info from the image then assume default values
|
||||
// of 8 bits per color and 4 channels (R,G,B,A) -- ie: regular 24-bit color
|
||||
return $memory_use = ($info[0] * $info[1] * 1 * 4 * 2.5) / 1024;
|
||||
$memory_use = ($info[0] * $info[1] * 1 * 4 * 2.5) / 1024;
|
||||
}
|
||||
return (int)$memory_use;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Image $image_obj
|
||||
* @param $width
|
||||
* @param $height
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return int[]
|
||||
*/
|
||||
private function calc_new_size(Image $image_obj, $width, $height) {
|
||||
@ -320,7 +322,7 @@ class ResizeImage extends Extension {
|
||||
// Scale the new image
|
||||
if ($width == 0) $factor = $height / $image_obj->height;
|
||||
elseif ($height == 0) $factor = $width / $image_obj->width;
|
||||
else $factor = min($width / $image_obj->width, $height / $image_obj->height);
|
||||
else $factor = min($width / $image_obj->width, $height / $image_obj->height);
|
||||
|
||||
$new_width = round($image_obj->width * $factor);
|
||||
$new_height = round($image_obj->height * $factor);
|
||||
|
@ -128,8 +128,8 @@ class ShimmieApi extends Extension {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @param $query
|
||||
* @param string $type
|
||||
* @param string $query
|
||||
* @return array
|
||||
*/
|
||||
private function api_get_user($type, $query) {
|
||||
|
@ -18,6 +18,7 @@ function dstat($name, $val) {
|
||||
class StatsDInterface extends Extension {
|
||||
public static $stats = array();
|
||||
|
||||
/** @param string $type */
|
||||
private function _stats($type) {
|
||||
global $_shm_event_count, $database, $_shm_load_start;
|
||||
$time = microtime(true) - $_shm_load_start;
|
||||
@ -32,7 +33,7 @@ class StatsDInterface extends Extension {
|
||||
StatsDInterface::$stats["shimmie.$type.cache-misses"] = $database->cache->get_misses()."|c";
|
||||
}
|
||||
|
||||
public function onPageRequest($event) {
|
||||
public function onPageRequest(PageRequestEvent $event) {
|
||||
$this->_stats("overall");
|
||||
|
||||
if($event->page_matches("post/view")) { # 40%
|
||||
@ -64,19 +65,19 @@ class StatsDInterface extends Extension {
|
||||
StatsDInterface::$stats = array();
|
||||
}
|
||||
|
||||
public function onUserCreation($event) {
|
||||
public function onUserCreation(UserCreationEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.user_creations"] = "1|c";
|
||||
}
|
||||
|
||||
public function onDataUpload($event) {
|
||||
public function onDataUpload(DataUploadEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.uploads"] = "1|c";
|
||||
}
|
||||
|
||||
public function onCommentPosting($event) {
|
||||
public function onCommentPosting(CommentPostingEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.comments"] = "1|c";
|
||||
}
|
||||
|
||||
public function onImageInfoSet($event) {
|
||||
public function onImageInfoSet(ImageInfoSetEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.info-sets"] = "1|c";
|
||||
}
|
||||
|
||||
@ -85,7 +86,10 @@ class StatsDInterface extends Extension {
|
||||
*/
|
||||
public function get_priority() {return 99;}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param int $sampleRate
|
||||
*/
|
||||
private function send($data, $sampleRate=1) {
|
||||
if (!STATSD_HOST) { return; }
|
||||
|
||||
|
@ -98,6 +98,10 @@ class TagSetEvent extends Event {
|
||||
public $tags;
|
||||
public $metatags;
|
||||
|
||||
/**
|
||||
* @param Image $image
|
||||
* @param string $tags
|
||||
*/
|
||||
public function __construct(Image $image, $tags) {
|
||||
$this->image = $image;
|
||||
|
||||
@ -165,6 +169,11 @@ class TagTermParseEvent extends Event {
|
||||
/** @var bool */
|
||||
public $parse = TRUE; //marks the tag to be parsed, and not just checked if valid metatag
|
||||
|
||||
/**
|
||||
* @param string $term
|
||||
* @param int $id
|
||||
* @param bool $parse
|
||||
*/
|
||||
public function __construct($term, $id, $parse) {
|
||||
$this->term = $term;
|
||||
$this->id = $id;
|
||||
|
@ -248,8 +248,12 @@ class Tag_History extends Extension {
|
||||
return ($row ? $row : array());
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* This function attempts to revert all changes by a given IP within an (optional) timeframe.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $ip
|
||||
* @param string $date
|
||||
*/
|
||||
public function process_revert_all_changes($name, $ip, $date) {
|
||||
global $database;
|
||||
|
@ -57,6 +57,7 @@ class TaggerXML extends Extension {
|
||||
}
|
||||
}
|
||||
|
||||
/** @param string $s */
|
||||
private function match_tag_list ($s) {
|
||||
global $database, $config;
|
||||
|
||||
@ -101,6 +102,7 @@ class TaggerXML extends Extension {
|
||||
return $this->list_to_xml($tags,"search",$s,$count);
|
||||
}
|
||||
|
||||
/** @param int $image_id */
|
||||
private function image_tag_list ($image_id) {
|
||||
global $database;
|
||||
$tags = $database->Execute("
|
||||
@ -110,6 +112,12 @@ class TaggerXML extends Extension {
|
||||
return $this->list_to_xml($tags,"image",$image_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PDOStatement $tags
|
||||
* @param string $type
|
||||
* @param string $query
|
||||
* @param array $misc
|
||||
*/
|
||||
private function list_to_xml ($tags,$type,$query,$misc=null) {
|
||||
$r = $tags->_numOfRows;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
class CustomIndexTheme extends IndexTheme {
|
||||
/**
|
||||
* @param Page $page
|
||||
* @param null|Image[] $images
|
||||
* @param Image[] $images
|
||||
*/
|
||||
public function display_page(Page $page, $images) {
|
||||
global $config;
|
||||
@ -40,7 +40,7 @@ class CustomIndexTheme extends IndexTheme {
|
||||
/**
|
||||
* @param int $page_number
|
||||
* @param int $total_pages
|
||||
* @param array $search_terms
|
||||
* @param string[] $search_terms
|
||||
* @return string
|
||||
*/
|
||||
protected function build_navigation($page_number, $total_pages, $search_terms) {
|
||||
|
@ -43,7 +43,7 @@ Tips
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class Layout {
|
||||
public function display_page($page) {
|
||||
public function display_page(Page $page) {
|
||||
global $config, $user;
|
||||
|
||||
$theme_name = $config->get_string('theme');
|
||||
@ -233,10 +233,16 @@ $header_html
|
||||
EOD;
|
||||
}
|
||||
|
||||
private function navlinks($link, $desc, $pages_matched) {
|
||||
/**
|
||||
* Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.)
|
||||
* @param string $link
|
||||
* @param string $desc
|
||||
* @param string[] $pages_matched
|
||||
* @return string
|
||||
*/
|
||||
private function navlinks($link, $desc, $pages_matched) {
|
||||
/**
|
||||
* Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.)
|
||||
*/
|
||||
$html = null;
|
||||
$url = ltrim(_get_query(), "/");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user