From 34b05cca7c6b19815bdee9233aa47a3d0ff57bc9 Mon Sep 17 00:00:00 2001 From: Shish Date: Tue, 28 May 2019 17:59:38 +0100 Subject: [PATCH] PSR-2. I'm not a huge fan, but ugly consistency beats no consistency... --- .editorconfig | 2 +- .gitignore | 1 + .php_cs.dist | 18 + core/_bootstrap.php | 18 +- core/_install.php | 316 ++--- core/basethemelet.php | 206 +-- core/block.php | 147 ++- core/cacheengine.php | 348 +++--- core/captcha.php | 81 +- core/config.php | 430 ++++--- core/database.php | 687 +++++----- core/dbengine.php | 292 +++-- core/email.php | 136 +- core/event.php | 453 +++---- core/exceptions.php | 16 +- core/extension.php | 259 ++-- core/imageboard/event.php | 179 +-- core/imageboard/image.php | 1592 ++++++++++++------------ core/imageboard/misc.php | 128 +- core/imageboard/search.php | 83 +- core/imageboard/tag.php | 151 +-- core/logging.php | 68 +- core/page.php | 581 ++++----- core/polyfills.php | 995 ++++++++------- core/send_event.php | 189 +-- core/sys_config.php | 9 +- core/tests/polyfills.test.php | 71 +- core/urls.php | 128 +- core/user.php | 382 +++--- core/userclass.php | 302 ++--- core/util.php | 725 ++++++----- ext/admin/main.php | 410 +++--- ext/admin/test.php | 137 +- ext/admin/theme.php | 115 +- ext/alias_editor/main.php | 295 ++--- ext/alias_editor/test.php | 179 +-- ext/alias_editor/theme.php | 78 +- ext/amazon_s3/main.php | 124 +- ext/arrowkey_navigation/main.php | 135 +- ext/artists/main.php | 539 ++++---- ext/artists/test.php | 15 +- ext/artists/theme.php | 607 ++++----- ext/autocomplete/main.php | 85 +- ext/autocomplete/theme.php | 20 +- ext/ban_words/main.php | 149 +-- ext/ban_words/test.php | 55 +- ext/bbcode/main.php | 255 ++-- ext/bbcode/test.php | 171 +-- ext/blocks/main.php | 129 +- ext/blocks/test.php | 17 +- ext/blocks/theme.php | 85 +- ext/blotter/main.php | 241 ++-- ext/blotter/test.php | 58 +- ext/blotter/theme.php | 244 ++-- ext/browser_search/main.php | 129 +- ext/browser_search/test.php | 13 +- ext/bulk_add/main.php | 107 +- ext/bulk_add/test.php | 57 +- ext/bulk_add/theme.php | 60 +- ext/bulk_add_csv/main.php | 232 ++-- ext/bulk_add_csv/theme.php | 57 +- ext/bulk_remove/main.php | 175 +-- ext/chatbox/cp/ajax.php | 373 +++--- ext/chatbox/cp/index.php | 8 +- ext/chatbox/history/index.php | 139 +-- ext/chatbox/include.php | 13 +- ext/chatbox/main.php | 28 +- ext/chatbox/php/ajaxcall.class.php | 510 ++++---- ext/chatbox/php/filestorage.class.php | 162 +-- ext/chatbox/php/functions.php | 265 ++-- ext/chatbox/php/yshout.class.php | 437 ++++--- ext/chatbox/preferences.php | 123 +- ext/chatbox/yshout.php | 53 +- ext/comment/main.php | 921 +++++++------- ext/comment/test.php | 177 +-- ext/comment/theme.php | 464 +++---- ext/cron_uploader/main.php | 722 +++++------ ext/custom_html_headers/main.php | 100 +- ext/danbooru_api/main.php | 591 ++++----- ext/danbooru_api/test.php | 34 +- ext/downtime/main.php | 64 +- ext/downtime/test.php | 61 +- ext/downtime/theme.php | 50 +- ext/emoticons/main.php | 36 +- ext/emoticons/test.php | 27 +- ext/emoticons/theme.php | 41 +- ext/et/main.php | 126 +- ext/et/test.php | 14 +- ext/et/theme.php | 40 +- ext/ext_manager/main.php | 345 ++--- ext/ext_manager/test.php | 38 +- ext/ext_manager/theme.php | 201 +-- ext/favorites/main.php | 333 ++--- ext/favorites/test.php | 43 +- ext/favorites/theme.php | 45 +- ext/featured/main.php | 132 +- ext/featured/test.php | 49 +- ext/featured/theme.php | 37 +- ext/forum/main.php | 625 +++++----- ext/forum/theme.php | 201 ++- ext/google_analytics/main.php | 34 +- ext/handle_404/main.php | 53 +- ext/handle_404/test.php | 19 +- ext/handle_archive/main.php | 77 +- ext/handle_flash/main.php | 74 +- ext/handle_flash/theme.php | 17 +- ext/handle_ico/main.php | 156 +-- ext/handle_ico/test.php | 19 +- ext/handle_ico/theme.php | 15 +- ext/handle_mp3/main.php | 67 +- ext/handle_mp3/theme.php | 21 +- ext/handle_pixel/main.php | 290 +++-- ext/handle_pixel/test.php | 19 +- ext/handle_pixel/theme.php | 53 +- ext/handle_static/main.php | 75 +- ext/handle_static/test.php | 13 +- ext/handle_svg/main.php | 201 +-- ext/handle_svg/test.php | 38 +- ext/handle_svg/theme.php | 17 +- ext/handle_video/main.php | 270 ++-- ext/handle_video/theme.php | 82 +- ext/hellban/main.php | 33 +- ext/holiday/main.php | 43 +- ext/holiday/theme.php | 33 +- ext/home/main.php | 118 +- ext/home/test.php | 18 +- ext/home/theme.php | 35 +- ext/image/main.php | 538 ++++---- ext/image/test.php | 28 +- ext/image/theme.php | 38 +- ext/image_hash_ban/main.php | 245 ++-- ext/image_hash_ban/test.php | 51 +- ext/image_hash_ban/theme.php | 78 +- ext/image_view_counter/main.php | 193 +-- ext/index/main.php | 393 +++--- ext/index/test.php | 331 ++--- ext/index/theme.php | 209 ++-- ext/ipban/main.php | 477 +++---- ext/ipban/test.php | 41 +- ext/ipban/theme.php | 53 +- ext/link_image/main.php | 54 +- ext/link_image/test.php | 39 +- ext/link_image/theme.php | 117 +- ext/livefeed/main.php | 95 +- ext/log_db/main.php | 234 ++-- ext/log_db/test.php | 20 +- ext/log_db/theme.php | 171 +-- ext/log_logstash/main.php | 86 +- ext/log_net/main.php | 73 +- ext/mail/main.php | 72 +- ext/mass_tagger/main.php | 99 +- ext/mass_tagger/theme.php | 17 +- ext/not_a_tag/main.php | 198 +-- ext/not_a_tag/theme.php | 41 +- ext/notes/main.php | 778 ++++++------ ext/notes/theme.php | 266 ++-- ext/numeric_score/main.php | 514 ++++---- ext/numeric_score/test.php | 93 +- ext/numeric_score/theme.php | 78 +- ext/oekaki/main.php | 151 +-- ext/oekaki/test.php | 12 +- ext/oekaki/theme.php | 83 +- ext/ouroboros_api/main.php | 37 +- ext/pm/main.php | 331 ++--- ext/pm/test.php | 96 +- ext/pm/theme.php | 89 +- ext/pm_triggers/main.php | 40 +- ext/pools/main.php | 1353 ++++++++++---------- ext/pools/test.php | 61 +- ext/pools/theme.php | 470 +++---- ext/qr_code/main.php | 11 +- ext/qr_code/theme.php | 19 +- ext/random_image/main.php | 103 +- ext/random_image/test.php | 86 +- ext/random_image/theme.php | 29 +- ext/random_list/main.php | 108 +- ext/random_list/theme.php | 70 +- ext/rating/main.php | 454 +++---- ext/rating/test.php | 81 +- ext/rating/theme.php | 33 +- ext/regen_thumb/main.php | 69 +- ext/regen_thumb/test.php | 21 +- ext/regen_thumb/theme.php | 49 +- ext/relatationships/main.php | 208 ++-- ext/relatationships/theme.php | 75 +- ext/report_image/main.php | 370 +++--- ext/report_image/test.php | 67 +- ext/report_image/theme.php | 117 +- ext/res_limit/main.php | 124 +- ext/res_limit/test.php | 144 +-- ext/resize/main.php | 561 +++++---- ext/resize/theme.php | 52 +- ext/rotate/main.php | 407 +++--- ext/rotate/theme.php | 40 +- ext/rss_comments/main.php | 68 +- ext/rss_comments/test.php | 23 +- ext/rss_images/main.php | 144 +-- ext/rss_images/test.php | 49 +- ext/rss_images/theme.php | 5 +- ext/rule34/main.php | 258 ++-- ext/rule34/theme.php | 53 +- ext/setup/main.php | 466 +++---- ext/setup/test.php | 71 +- ext/setup/theme.php | 125 +- ext/shimmie_api/main.php | 277 +++-- ext/shimmie_api/test.php | 40 +- ext/site_description/main.php | 40 +- ext/site_description/test.php | 42 +- ext/sitemap/main.php | 281 +++-- ext/sitemap/test.php | 14 +- ext/source_history/main.php | 631 +++++----- ext/source_history/theme.php | 159 +-- ext/statsd/main.php | 140 ++- ext/tag_categories/main.php | 235 ++-- ext/tag_categories/theme.php | 10 +- ext/tag_edit/main.php | 533 ++++---- ext/tag_edit/test.php | 134 +- ext/tag_edit/theme.php | 137 +- ext/tag_editcloud/main.php | 261 ++-- ext/tag_history/main.php | 631 +++++----- ext/tag_history/test.php | 39 +- ext/tag_history/theme.php | 171 +-- ext/tag_list/main.php | 779 ++++++------ ext/tag_list/test.php | 53 +- ext/tag_list/theme.php | 489 ++++---- ext/tagger/main.php | 227 ++-- ext/tagger/theme.php | 61 +- ext/tips/main.php | 230 ++-- ext/tips/test.php | 122 +- ext/tips/theme.php | 117 +- ext/update/main.php | 178 +-- ext/update/theme.php | 23 +- ext/upgrade/main.php | 200 +-- ext/upload/main.php | 735 +++++------ ext/upload/test.php | 79 +- ext/upload/theme.php | 381 +++--- ext/user/main.php | 1147 +++++++++-------- ext/user/test.php | 68 +- ext/user/theme.php | 405 +++--- ext/varnish/main.php | 58 +- ext/view/main.php | 228 ++-- ext/view/test.php | 107 +- ext/view/theme.php | 127 +- ext/wiki/main.php | 816 ++++++------ ext/wiki/test.php | 210 ++-- ext/wiki/theme.php | 123 +- ext/word_filter/main.php | 96 +- ext/word_filter/test.php | 123 +- index.php | 63 +- tests/bootstrap.php | 261 ++-- tests/router.php | 18 +- themes/danbooru/comment.theme.php | 190 +-- themes/danbooru/custompage.class.php | 15 +- themes/danbooru/index.theme.php | 104 +- themes/danbooru/layout.class.php | 338 ++--- themes/danbooru/tag_list.theme.php | 13 +- themes/danbooru/themelet.class.php | 93 +- themes/danbooru/upload.theme.php | 22 +- themes/danbooru/user.theme.php | 138 +- themes/danbooru/view.theme.php | 80 +- themes/danbooru2/admin.theme.php | 16 +- themes/danbooru2/comment.theme.php | 190 +-- themes/danbooru2/custompage.class.php | 13 +- themes/danbooru2/ext_manager.theme.php | 23 +- themes/danbooru2/index.theme.php | 110 +- themes/danbooru2/layout.class.php | 376 +++--- themes/danbooru2/tag_list.theme.php | 13 +- themes/danbooru2/themelet.class.php | 93 +- themes/danbooru2/upload.theme.php | 22 +- themes/danbooru2/user.theme.php | 138 +- themes/danbooru2/view.theme.php | 91 +- themes/default/layout.class.php | 87 +- themes/default/themelet.class.php | 5 +- themes/futaba/comment.theme.php | 157 +-- themes/futaba/custompage.class.php | 13 +- themes/futaba/layout.class.php | 99 +- themes/futaba/themelet.class.php | 102 +- themes/futaba/view.theme.php | 17 +- themes/lite/comment.theme.php | 17 +- themes/lite/custompage.class.php | 15 +- themes/lite/layout.class.php | 395 +++--- themes/lite/setup.theme.php | 19 +- themes/lite/themelet.class.php | 103 +- themes/lite/user.theme.php | 134 +- themes/lite/view.theme.php | 78 +- themes/material/home.theme.php | 35 +- themes/material/layout.class.php | 263 ++-- themes/material/themelet.class.php | 5 +- themes/material/upload.theme.php | 15 +- themes/material/user.theme.php | 37 +- themes/material/view.theme.php | 102 +- themes/warm/layout.class.php | 103 +- themes/warm/themelet.class.php | 5 +- themes/warm/upload.theme.php | 18 +- themes/warm/user.theme.php | 38 +- 295 files changed, 27094 insertions(+), 24632 deletions(-) create mode 100644 .php_cs.dist diff --git a/.editorconfig b/.editorconfig index 9c622947..15d2c086 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,6 @@ insert_final_newline = true [*.{js,css,php}] charset = utf-8 -indent_style = tab +indent_style = space indent_size = 4 diff --git a/.gitignore b/.gitignore index 98c90ae5..e2053c51 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ images thumbs *.phar *.sqlite +.php_cs.cache #Composer composer.phar diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 00000000..9430b4e5 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,18 @@ +exclude('ext/amazon_s3/lib') + ->exclude('vendor') + ->in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setRules([ + '@PSR2' => true, + //'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], + ]) + ->setFinder($finder) +; + +?> diff --git a/core/_bootstrap.php b/core/_bootstrap.php index 025a4e6a..2611854e 100644 --- a/core/_bootstrap.php +++ b/core/_bootstrap.php @@ -19,14 +19,14 @@ _sanitise_environment(); // load base files $_shm_ctx->log_start("Opening files"); $_shm_files = array_merge( - zglob("core/*.php"), - zglob("core/{".ENABLED_MODS."}/*.php"), - zglob("ext/{".ENABLED_EXTS."}/main.php") + zglob("core/*.php"), + zglob("core/{".ENABLED_MODS."}/*.php"), + zglob("ext/{".ENABLED_EXTS."}/main.php") ); -foreach($_shm_files as $_shm_filename) { - if(basename($_shm_filename)[0] != "_") { - require_once $_shm_filename; - } +foreach ($_shm_files as $_shm_filename) { + if (basename($_shm_filename)[0] != "_") { + require_once $_shm_filename; + } } unset($_shm_files); unset($_shm_filename); @@ -40,8 +40,8 @@ $_shm_ctx->log_endok(); // load the theme parts $_shm_ctx->log_start("Loading themelets"); -foreach(_get_themelet_files(get_theme()) as $themelet) { - require_once $themelet; +foreach (_get_themelet_files(get_theme()) as $themelet) { + require_once $themelet; } unset($themelet); $page = class_exists("CustomPage") ? new CustomPage() : new Page(); diff --git a/core/_install.php b/core/_install.php index 177a1267..527708fa 100644 --- a/core/_install.php +++ b/core/_install.php @@ -7,7 +7,7 @@ * @author Shish [webmaster at shishnet.org], jgen [jeffgenovy at gmail.com] * @link http://code.shishnet.org/shimmie2/ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 - * + * * Initialise the database, check that folder * permissions are set properly. * @@ -30,7 +30,7 @@ date_default_timezone_set('UTC'); - +

Install Error

@@ -43,7 +43,7 @@ date_default_timezone_set('UTC');
-
+
 		

Install Error

Warning: Composer vendor folder does not exist!

@@ -65,112 +65,114 @@ require_once "core/cacheengine.php"; require_once "core/dbengine.php"; require_once "core/database.php"; -if(is_readable("data/config/shimmie.conf.php")) die("Shimmie is already installed."); +if (is_readable("data/config/shimmie.conf.php")) { + die("Shimmie is already installed."); +} do_install(); // utilities {{{ - // TODO: Can some of these be pushed into "core/???.inc.php" ? + // TODO: Can some of these be pushed into "core/???.inc.php" ? -function check_gd_version(): int { - $gdversion = 0; +function check_gd_version(): int +{ + $gdversion = 0; - if (function_exists('gd_info')){ - $gd_info = gd_info(); - if (substr_count($gd_info['GD Version'], '2.')) { - $gdversion = 2; - } else if (substr_count($gd_info['GD Version'], '1.')) { - $gdversion = 1; - } - } + if (function_exists('gd_info')) { + $gd_info = gd_info(); + if (substr_count($gd_info['GD Version'], '2.')) { + $gdversion = 2; + } elseif (substr_count($gd_info['GD Version'], '1.')) { + $gdversion = 1; + } + } - return $gdversion; + return $gdversion; } -function check_im_version(): int { - $convert_check = exec("convert"); +function check_im_version(): int +{ + $convert_check = exec("convert"); - return (empty($convert_check) ? 0 : 1); + return (empty($convert_check) ? 0 : 1); } -function eok($name, $value) { - echo "
$name ... "; - if($value) { - echo "ok\n"; - } - else { - echo "failed\n"; - } +function eok($name, $value) +{ + echo "
$name ... "; + if ($value) { + echo "ok\n"; + } else { + echo "failed\n"; + } } // }}} -function do_install() { // {{{ - if(file_exists("data/config/auto_install.conf.php")) { - require_once "data/config/auto_install.conf.php"; - } - else if(@$_POST["database_type"] == "sqlite") { - $id = bin2hex(random_bytes(5)); - define('DATABASE_DSN', "sqlite:data/shimmie.{$id}.sqlite"); - } - else if(isset($_POST['database_type']) && isset($_POST['database_host']) && isset($_POST['database_user']) && isset($_POST['database_name'])) { - define('DATABASE_DSN', "{$_POST['database_type']}:user={$_POST['database_user']};password={$_POST['database_password']};host={$_POST['database_host']};dbname={$_POST['database_name']}"); - } - else { - ask_questions(); - return; - } +function do_install() +{ // {{{ + if (file_exists("data/config/auto_install.conf.php")) { + require_once "data/config/auto_install.conf.php"; + } elseif (@$_POST["database_type"] == "sqlite") { + $id = bin2hex(random_bytes(5)); + define('DATABASE_DSN', "sqlite:data/shimmie.{$id}.sqlite"); + } elseif (isset($_POST['database_type']) && isset($_POST['database_host']) && isset($_POST['database_user']) && isset($_POST['database_name'])) { + define('DATABASE_DSN', "{$_POST['database_type']}:user={$_POST['database_user']};password={$_POST['database_password']};host={$_POST['database_host']};dbname={$_POST['database_name']}"); + } else { + ask_questions(); + return; + } - define("CACHE_DSN", null); - define("DEBUG_SQL", false); - define("DATABASE_KA", true); - install_process(); + define("CACHE_DSN", null); + define("DEBUG_SQL", false); + define("DATABASE_KA", true); + install_process(); } // }}} -function ask_questions() { // {{{ - $warnings = array(); - $errors = array(); +function ask_questions() +{ // {{{ + $warnings = []; + $errors = []; - if(check_gd_version() == 0 && check_im_version() == 0) { - $errors[] = " + if (check_gd_version() == 0 && check_im_version() == 0) { + $errors[] = " No thumbnailers could be found - install the imagemagick tools (or the PHP-GD library, if imagemagick is unavailable). "; - } - else if(check_im_version() == 0) { - $warnings[] = " + } elseif (check_im_version() == 0) { + $warnings[] = " The 'convert' command (from the imagemagick package) could not be found - PHP-GD can be used instead, but the size of thumbnails will be limited. "; - } + } - if(!function_exists('mb_strlen')) { - $errors[] = " + if (!function_exists('mb_strlen')) { + $errors[] = " The mbstring PHP extension is missing - multibyte languages (eg non-english languages) may not work right. "; - } + } - $drivers = PDO::getAvailableDrivers(); - if( - !in_array("mysql", $drivers) && - !in_array("pgsql", $drivers) && - !in_array("sqlite", $drivers) - ) { - $errors[] = " + $drivers = PDO::getAvailableDrivers(); + if ( + !in_array("mysql", $drivers) && + !in_array("pgsql", $drivers) && + !in_array("sqlite", $drivers) + ) { + $errors[] = " No database connection library could be found; shimmie needs PDO with either Postgres, MySQL, or SQLite drivers "; - } + } - $db_m = in_array("mysql", $drivers) ? '' : ""; - $db_p = in_array("pgsql", $drivers) ? '' : ""; - $db_s = in_array("sqlite", $drivers) ? '' : ""; + $db_m = in_array("mysql", $drivers) ? '' : ""; + $db_p = in_array("pgsql", $drivers) ? '' : ""; + $db_s = in_array("sqlite", $drivers) ? '' : ""; - $warn_msg = $warnings ? "

Warnings

".implode("\n

", $warnings) : ""; - $err_msg = $errors ? "

Errors

".implode("\n

", $errors) : ""; + $warn_msg = $warnings ? "

Warnings

".implode("\n

", $warnings) : ""; + $err_msg = $errors ? "

Errors

".implode("\n

", $errors) : ""; - print <<

Shimmie Installer

@@ -243,19 +245,21 @@ EOD; /** * This is where the install really takes place. */ -function install_process() { // {{{ - build_dirs(); - create_tables(); - insert_defaults(); - write_config(); +function install_process() +{ // {{{ + build_dirs(); + create_tables(); + insert_defaults(); + write_config(); } // }}} -function create_tables() { // {{{ - try { - $db = new Database(); +function create_tables() +{ // {{{ + try { + $db = new Database(); - if ( $db->count_tables() > 0 ) { - print <<count_tables() > 0) { + print <<

Shimmie Installer

Warning: The Database schema is not empty!

@@ -266,22 +270,22 @@ function create_tables() { // {{{
EOD; - exit(2); - } + exit(2); + } - $db->create_table("aliases", " + $db->create_table("aliases", " oldtag VARCHAR(128) NOT NULL, newtag VARCHAR(128) NOT NULL, PRIMARY KEY (oldtag) "); - $db->execute("CREATE INDEX aliases_newtag_idx ON aliases(newtag)", array()); + $db->execute("CREATE INDEX aliases_newtag_idx ON aliases(newtag)", []); - $db->create_table("config", " + $db->create_table("config", " name VARCHAR(128) NOT NULL, value TEXT, PRIMARY KEY (name) "); - $db->create_table("users", " + $db->create_table("users", " id SCORE_AIPK, name VARCHAR(32) UNIQUE NOT NULL, pass VARCHAR(250), @@ -289,9 +293,9 @@ EOD; class VARCHAR(32) NOT NULL DEFAULT 'user', email VARCHAR(128) "); - $db->execute("CREATE INDEX users_name_idx ON users(name)", array()); + $db->execute("CREATE INDEX users_name_idx ON users(name)", []); - $db->create_table("images", " + $db->create_table("images", " id SCORE_AIPK, owner_id INTEGER NOT NULL, owner_ip SCORE_INET NOT NULL, @@ -306,69 +310,72 @@ EOD; locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT "); - $db->execute("CREATE INDEX images_owner_id_idx ON images(owner_id)", array()); - $db->execute("CREATE INDEX images_width_idx ON images(width)", array()); - $db->execute("CREATE INDEX images_height_idx ON images(height)", array()); - $db->execute("CREATE INDEX images_hash_idx ON images(hash)", array()); + $db->execute("CREATE INDEX images_owner_id_idx ON images(owner_id)", []); + $db->execute("CREATE INDEX images_width_idx ON images(width)", []); + $db->execute("CREATE INDEX images_height_idx ON images(height)", []); + $db->execute("CREATE INDEX images_hash_idx ON images(hash)", []); - $db->create_table("tags", " + $db->create_table("tags", " id SCORE_AIPK, tag VARCHAR(64) UNIQUE NOT NULL, count INTEGER NOT NULL DEFAULT 0 "); - $db->execute("CREATE INDEX tags_tag_idx ON tags(tag)", array()); + $db->execute("CREATE INDEX tags_tag_idx ON tags(tag)", []); - $db->create_table("image_tags", " + $db->create_table("image_tags", " image_id INTEGER NOT NULL, tag_id INTEGER NOT NULL, UNIQUE(image_id, tag_id), FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE "); - $db->execute("CREATE INDEX images_tags_image_id_idx ON image_tags(image_id)", array()); - $db->execute("CREATE INDEX images_tags_tag_id_idx ON image_tags(tag_id)", array()); + $db->execute("CREATE INDEX images_tags_image_id_idx ON image_tags(image_id)", []); + $db->execute("CREATE INDEX images_tags_tag_id_idx ON image_tags(tag_id)", []); - $db->execute("INSERT INTO config(name, value) VALUES('db_version', 11)"); - $db->commit(); - } - catch(PDOException $e) { - handle_db_errors(TRUE, "An error occurred while trying to create the database tables necessary for Shimmie.", $e->getMessage(), 3); - } catch (Exception $e) { - handle_db_errors(FALSE, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 4); - } + $db->execute("INSERT INTO config(name, value) VALUES('db_version', 11)"); + $db->commit(); + } catch (PDOException $e) { + handle_db_errors(true, "An error occurred while trying to create the database tables necessary for Shimmie.", $e->getMessage(), 3); + } catch (Exception $e) { + handle_db_errors(false, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 4); + } } // }}} -function insert_defaults() { // {{{ - try { - $db = new Database(); +function insert_defaults() +{ // {{{ + try { + $db = new Database(); - $db->execute("INSERT INTO users(name, pass, joindate, class) VALUES(:name, :pass, now(), :class)", Array("name" => 'Anonymous', "pass" => null, "class" => 'anonymous')); - $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", Array("name" => 'anon_id', "value" => $db->get_last_insert_id('users_id_seq'))); + $db->execute("INSERT INTO users(name, pass, joindate, class) VALUES(:name, :pass, now(), :class)", ["name" => 'Anonymous', "pass" => null, "class" => 'anonymous']); + $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'anon_id', "value" => $db->get_last_insert_id('users_id_seq')]); - if(check_im_version() > 0) { - $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", Array("name" => 'thumb_engine', "value" => 'convert')); - } - $db->commit(); - } - catch(PDOException $e) { - handle_db_errors(TRUE, "An error occurred while trying to insert data into the database.", $e->getMessage(), 5); - } - catch (Exception $e) { - handle_db_errors(FALSE, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 6); - } + if (check_im_version() > 0) { + $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'thumb_engine', "value" => 'convert']); + } + $db->commit(); + } catch (PDOException $e) { + handle_db_errors(true, "An error occurred while trying to insert data into the database.", $e->getMessage(), 5); + } catch (Exception $e) { + handle_db_errors(false, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 6); + } } // }}} -function build_dirs() { // {{{ - // *try* and make default dirs. Ignore any errors -- - // if something is amiss, we'll tell the user later - if(!file_exists("data")) @mkdir("data"); - if(!is_writable("data")) @chmod("data", 0755); +function build_dirs() +{ // {{{ + // *try* and make default dirs. Ignore any errors -- + // if something is amiss, we'll tell the user later + if (!file_exists("data")) { + @mkdir("data"); + } + if (!is_writable("data")) { + @chmod("data", 0755); + } - // Clear file status cache before checking again. - clearstatcache(); + // Clear file status cache before checking again. + clearstatcache(); - if(!file_exists("data") || !is_writable("data")) { - print " + if (!file_exists("data") || !is_writable("data")) { + print "

Shimmie Installer

Directory Permissions Error:

@@ -381,22 +388,23 @@ function build_dirs() { // {{{
"; - exit(7); - } + exit(7); + } } // }}} -function write_config() { // {{{ - $file_content = '<' . '?php' . "\n" . - "define('DATABASE_DSN', '".DATABASE_DSN."');\n" . - '?' . '>'; +function write_config() +{ // {{{ + $file_content = '<' . '?php' . "\n" . + "define('DATABASE_DSN', '".DATABASE_DSN."');\n" . + '?' . '>'; - if(!file_exists("data/config")) { - mkdir("data/config", 0755, true); - } + if (!file_exists("data/config")) { + mkdir("data/config", 0755, true); + } - if(file_put_contents("data/config/shimmie.conf.php", $file_content, LOCK_EX)) { - header("Location: index.php"); - print <<

Shimmie Installer

Things are OK \o/

@@ -405,10 +413,9 @@ function write_config() { // {{{ EOD; - } - else { - $h_file_content = htmlentities($file_content); - print <<

Shimmie Installer

File Permissions Error:

@@ -425,13 +432,14 @@ EOD; EOD; - } - echo "\n"; + } + echo "\n"; } // }}} -function handle_db_errors(bool $isPDO, string $errorMessage1, string $errorMessage2, int $exitCode) { - $errorMessage1Extra = ($isPDO ? "Please check and ensure that the database configuration options are all correct." : "Please check the server log files for more information."); - print <<

Shimmie Installer

Unknown Error:

@@ -442,7 +450,7 @@ function handle_db_errors(bool $isPDO, string $errorMessage1, string $errorMessa EOD; - exit($exitCode); + exit($exitCode); } ?> diff --git a/core/basethemelet.php b/core/basethemelet.php index 77af37d4..8ff6eab1 100644 --- a/core/basethemelet.php +++ b/core/basethemelet.php @@ -5,117 +5,135 @@ * * A collection of common functions for theme parts */ -class BaseThemelet { +class BaseThemelet +{ - /** - * Generic error message display - */ - public function display_error(int $code, string $title, string $message): void { - global $page; - $page->set_code($code); - $page->set_title($title); - $page->set_heading($title); - $has_nav = false; - foreach($page->blocks as $block) { - if($block->header == "Navigation") { - $has_nav = true; - break; - } - } - if(!$has_nav) { - $page->add_block(new NavBlock()); - } - $page->add_block(new Block("Error", $message)); - } + /** + * Generic error message display + */ + public function display_error(int $code, string $title, string $message): void + { + global $page; + $page->set_code($code); + $page->set_title($title); + $page->set_heading($title); + $has_nav = false; + foreach ($page->blocks as $block) { + if ($block->header == "Navigation") { + $has_nav = true; + break; + } + } + if (!$has_nav) { + $page->add_block(new NavBlock()); + } + $page->add_block(new Block("Error", $message)); + } - /** - * A specific, common error message - */ - public function display_permission_denied(): void { - $this->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } + /** + * A specific, common error message + */ + public function display_permission_denied(): void + { + $this->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } - /** - * Generic thumbnail code; returns HTML rather than adding - * a block since thumbs tend to go inside blocks... - */ - public function build_thumb_html(Image $image): string { - global $config; + /** + * Generic thumbnail code; returns HTML rather than adding + * a block since thumbs tend to go inside blocks... + */ + public function build_thumb_html(Image $image): string + { + global $config; - $i_id = (int) $image->id; - $h_view_link = make_link('post/view/'.$i_id); - $h_thumb_link = $image->get_thumb_link(); - $h_tip = html_escape($image->get_tooltip()); - $h_tags = html_escape(strtolower($image->get_tag_list())); + $i_id = (int) $image->id; + $h_view_link = make_link('post/view/'.$i_id); + $h_thumb_link = $image->get_thumb_link(); + $h_tip = html_escape($image->get_tooltip()); + $h_tags = html_escape(strtolower($image->get_tag_list())); - $extArr = array_flip(array('swf', 'svg', 'mp3')); //List of thumbless filetypes - if(!isset($extArr[$image->ext])){ - $tsize = get_thumbnail_size($image->width, $image->height); - }else{ - //Use max thumbnail size if using thumbless filetype - $tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height')); - } + $extArr = array_flip(['swf', 'svg', 'mp3']); //List of thumbless filetypes + if (!isset($extArr[$image->ext])) { + $tsize = get_thumbnail_size($image->width, $image->height); + } else { + //Use max thumbnail size if using thumbless filetype + $tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height')); + } - $custom_classes = ""; - if(class_exists("Relationships")){ - if(property_exists($image, 'parent_id') && $image->parent_id !== NULL){ $custom_classes .= "shm-thumb-has_parent "; } - if(property_exists($image, 'has_children') && bool_escape($image->has_children)){ $custom_classes .= "shm-thumb-has_child "; } - } + $custom_classes = ""; + if (class_exists("Relationships")) { + if (property_exists($image, 'parent_id') && $image->parent_id !== null) { + $custom_classes .= "shm-thumb-has_parent "; + } + if (property_exists($image, 'has_children') && bool_escape($image->has_children)) { + $custom_classes .= "shm-thumb-has_child "; + } + } - return "". - "$h_tip". - "\n"; - } + return "". + "$h_tip". + "\n"; + } - public function display_paginator(Page $page, string $base, string $query=null, int $page_number, int $total_pages, bool $show_random = FALSE) { - if($total_pages == 0) $total_pages = 1; - $body = $this->build_paginator($page_number, $total_pages, $base, $query, $show_random); - $page->add_block(new Block(null, $body, "main", 90, "paginator")); - } + public function display_paginator(Page $page, string $base, string $query=null, int $page_number, int $total_pages, bool $show_random = false) + { + if ($total_pages == 0) { + $total_pages = 1; + } + $body = $this->build_paginator($page_number, $total_pages, $base, $query, $show_random); + $page->add_block(new Block(null, $body, "main", 90, "paginator")); + } - private function gen_page_link(string $base_url, string $query=null, string $page, string $name): string { - $link = make_link($base_url.'/'.$page, $query); - return ''.$name.''; - } + private function gen_page_link(string $base_url, string $query=null, string $page, string $name): string + { + $link = make_link($base_url.'/'.$page, $query); + return ''.$name.''; + } - private function gen_page_link_block(string $base_url, string $query=null, string $page, int $current_page, string $name): string { - $paginator = ""; - if($page == $current_page) $paginator .= ""; - $paginator .= $this->gen_page_link($base_url, $query, $page, $name); - if($page == $current_page) $paginator .= ""; - return $paginator; - } + private function gen_page_link_block(string $base_url, string $query=null, string $page, int $current_page, string $name): string + { + $paginator = ""; + if ($page == $current_page) { + $paginator .= ""; + } + $paginator .= $this->gen_page_link($base_url, $query, $page, $name); + if ($page == $current_page) { + $paginator .= ""; + } + return $paginator; + } - private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query=null, bool $show_random): string { - $next = $current_page + 1; - $prev = $current_page - 1; + private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query=null, bool $show_random): string + { + $next = $current_page + 1; + $prev = $current_page - 1; - $at_start = ($current_page <= 1 || $total_pages <= 1); - $at_end = ($current_page >= $total_pages); + $at_start = ($current_page <= 1 || $total_pages <= 1); + $at_end = ($current_page >= $total_pages); - $first_html = $at_start ? "First" : $this->gen_page_link($base_url, $query, 1, "First"); - $prev_html = $at_start ? "Prev" : $this->gen_page_link($base_url, $query, $prev, "Prev"); + $first_html = $at_start ? "First" : $this->gen_page_link($base_url, $query, 1, "First"); + $prev_html = $at_start ? "Prev" : $this->gen_page_link($base_url, $query, $prev, "Prev"); - $random_html = "-"; - if($show_random) { - $rand = mt_rand(1, $total_pages); - $random_html = $this->gen_page_link($base_url, $query, $rand, "Random"); - } + $random_html = "-"; + if ($show_random) { + $rand = mt_rand(1, $total_pages); + $random_html = $this->gen_page_link($base_url, $query, $rand, "Random"); + } - $next_html = $at_end ? "Next" : $this->gen_page_link($base_url, $query, $next, "Next"); - $last_html = $at_end ? "Last" : $this->gen_page_link($base_url, $query, $total_pages, "Last"); + $next_html = $at_end ? "Next" : $this->gen_page_link($base_url, $query, $next, "Next"); + $last_html = $at_end ? "Last" : $this->gen_page_link($base_url, $query, $total_pages, "Last"); - $start = $current_page-5 > 1 ? $current_page-5 : 1; - $end = $start+10 < $total_pages ? $start+10 : $total_pages; + $start = $current_page-5 > 1 ? $current_page-5 : 1; + $end = $start+10 < $total_pages ? $start+10 : $total_pages; - $pages = array(); - foreach(range($start, $end) as $i) { - $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); - } - $pages_html = implode(" | ", $pages); + $pages = []; + foreach (range($start, $end) as $i) { + $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); + } + $pages_html = implode(" | ", $pages); - return $first_html.' | '.$prev_html.' | '.$random_html.' | '.$next_html.' | '.$last_html - .'
<< '.$pages_html.' >>'; - } + return $first_html.' | '.$prev_html.' | '.$random_html.' | '.$next_html.' | '.$last_html + .'
<< '.$pages_html.' >>'; + } } diff --git a/core/block.php b/core/block.php index 737ca3f8..70c8c690 100644 --- a/core/block.php +++ b/core/block.php @@ -5,79 +5,86 @@ * * A basic chunk of a page. */ -class Block { - /** - * The block's title. - * - * @var string - */ - public $header; +class Block +{ + /** + * The block's title. + * + * @var string + */ + public $header; - /** - * The content of the block. - * - * @var string - */ - public $body; + /** + * The content of the block. + * + * @var string + */ + public $body; - /** - * Where the block should be placed. The default theme supports - * "main" and "left", other themes can add their own areas. - * - * @var string - */ - public $section; + /** + * Where the block should be placed. The default theme supports + * "main" and "left", other themes can add their own areas. + * + * @var string + */ + public $section; - /** - * How far down the section the block should appear, higher - * numbers appear lower. The scale is 0-100 by convention, - * though any number or string will work. - * - * @var int - */ - public $position; + /** + * How far down the section the block should appear, higher + * numbers appear lower. The scale is 0-100 by convention, + * though any number or string will work. + * + * @var int + */ + public $position; - /** - * A unique ID for the block. - * - * @var string - */ - public $id; + /** + * A unique ID for the block. + * + * @var string + */ + public $id; - /** - * Should this block count as content for the sake of - * the 404 handler - * - * @var boolean - */ - public $is_content = true; + /** + * Should this block count as content for the sake of + * the 404 handler + * + * @var boolean + */ + public $is_content = true; - public function __construct(string $header=null, string $body=null, string $section="main", int $position=50, string $id=null) { - $this->header = $header; - $this->body = $body; - $this->section = $section; - $this->position = $position; + public function __construct(string $header=null, string $body=null, string $section="main", int $position=50, string $id=null) + { + $this->header = $header; + $this->body = $body; + $this->section = $section; + $this->position = $position; - if(is_null($id)) { - $id = (empty($header) ? md5($body) : $header) . $section; - } - $this->id = preg_replace('/[^\w]/', '',str_replace(' ', '_', $id)); - } + if (is_null($id)) { + $id = (empty($header) ? md5($body) : $header) . $section; + } + $this->id = preg_replace('/[^\w]/', '', str_replace(' ', '_', $id)); + } - /** - * Get the HTML for this block. - */ - public function get_html(bool $hidable=false): string { - $h = $this->header; - $b = $this->body; - $i = $this->id; - $html = "
"; - $h_toggler = $hidable ? " shm-toggler" : ""; - if(!empty($h)) $html .= "

$h

"; - if(!empty($b)) $html .= "
$b
"; - $html .= "
\n"; - return $html; - } + /** + * Get the HTML for this block. + */ + public function get_html(bool $hidable=false): string + { + $h = $this->header; + $b = $this->body; + $i = $this->id; + $html = "
"; + $h_toggler = $hidable ? " shm-toggler" : ""; + if (!empty($h)) { + $html .= "

$h

"; + } + if (!empty($b)) { + $html .= "
$b
"; + } + $html .= "
\n"; + return $html; + } } @@ -89,8 +96,10 @@ class Block { * Used because "new NavBlock()" is easier than "new Block('Navigation', ..." * */ -class NavBlock extends Block { - public function __construct() { - parent::__construct("Navigation", "Index", "left", 0); - } +class NavBlock extends Block +{ + public function __construct() + { + parent::__construct("Navigation", "Index", "left", 0); + } } diff --git a/core/cacheengine.php b/core/cacheengine.php index 40be954e..c1e19e64 100644 --- a/core/cacheengine.php +++ b/core/cacheengine.php @@ -1,196 +1,228 @@ memcache = new Memcache; - @$this->memcache->pconnect($hp[0], $hp[1]); - } + public function __construct(string $args) + { + $hp = explode(":", $args); + $this->memcache = new Memcache; + @$this->memcache->pconnect($hp[0], $hp[1]); + } - public function get(string $key) { - return $this->memcache->get($key); - } + public function get(string $key) + { + return $this->memcache->get($key); + } - public function set(string $key, $val, int $time=0) { - $this->memcache->set($key, $val, false, $time); - } + public function set(string $key, $val, int $time=0) + { + $this->memcache->set($key, $val, false, $time); + } - public function delete(string $key) { - $this->memcache->delete($key); - } + public function delete(string $key) + { + $this->memcache->delete($key); + } } -class MemcachedCache implements CacheEngine { - /** @var \Memcached|null */ - public $memcache=null; +class MemcachedCache implements CacheEngine +{ + /** @var \Memcached|null */ + public $memcache=null; - public function __construct(string $args) { - $hp = explode(":", $args); - $this->memcache = new Memcached; - #$this->memcache->setOption(Memcached::OPT_COMPRESSION, False); - #$this->memcache->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP); - #$this->memcache->setOption(Memcached::OPT_PREFIX_KEY, phpversion()); - $this->memcache->addServer($hp[0], $hp[1]); - } + public function __construct(string $args) + { + $hp = explode(":", $args); + $this->memcache = new Memcached; + #$this->memcache->setOption(Memcached::OPT_COMPRESSION, False); + #$this->memcache->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP); + #$this->memcache->setOption(Memcached::OPT_PREFIX_KEY, phpversion()); + $this->memcache->addServer($hp[0], $hp[1]); + } - public function get(string $key) { - $key = urlencode($key); + public function get(string $key) + { + $key = urlencode($key); - $val = $this->memcache->get($key); - $res = $this->memcache->getResultCode(); + $val = $this->memcache->get($key); + $res = $this->memcache->getResultCode(); - if($res == Memcached::RES_SUCCESS) { - return $val; - } - else if($res == Memcached::RES_NOTFOUND) { - return false; - } - else { - error_log("Memcached error during get($key): $res"); - return false; - } - } + if ($res == Memcached::RES_SUCCESS) { + return $val; + } elseif ($res == Memcached::RES_NOTFOUND) { + return false; + } else { + error_log("Memcached error during get($key): $res"); + return false; + } + } - public function set(string $key, $val, int $time=0) { - $key = urlencode($key); + public function set(string $key, $val, int $time=0) + { + $key = urlencode($key); - $this->memcache->set($key, $val, $time); - $res = $this->memcache->getResultCode(); - if($res != Memcached::RES_SUCCESS) { - error_log("Memcached error during set($key): $res"); - } - } + $this->memcache->set($key, $val, $time); + $res = $this->memcache->getResultCode(); + if ($res != Memcached::RES_SUCCESS) { + error_log("Memcached error during set($key): $res"); + } + } - public function delete(string $key) { - $key = urlencode($key); + public function delete(string $key) + { + $key = urlencode($key); - $this->memcache->delete($key); - $res = $this->memcache->getResultCode(); - if($res != Memcached::RES_SUCCESS && $res != Memcached::RES_NOTFOUND) { - error_log("Memcached error during delete($key): $res"); - } - } + $this->memcache->delete($key); + $res = $this->memcache->getResultCode(); + if ($res != Memcached::RES_SUCCESS && $res != Memcached::RES_NOTFOUND) { + error_log("Memcached error during delete($key): $res"); + } + } } -class APCCache implements CacheEngine { - public function __construct(string $args) { - // $args is not used, but is passed in when APC cache is created. - } +class APCCache implements CacheEngine +{ + public function __construct(string $args) + { + // $args is not used, but is passed in when APC cache is created. + } - public function get(string $key) { - return apc_fetch($key); - } + public function get(string $key) + { + return apc_fetch($key); + } - public function set(string $key, $val, int $time=0) { - apc_store($key, $val, $time); - } + public function set(string $key, $val, int $time=0) + { + apc_store($key, $val, $time); + } - public function delete(string $key) { - apc_delete($key); - } + public function delete(string $key) + { + apc_delete($key); + } } -class RedisCache implements CacheEngine { - private $redis=null; +class RedisCache implements CacheEngine +{ + private $redis=null; - public function __construct(string $args) { - $this->redis = new Redis(); - $hp = explode(":", $args); - $this->redis->pconnect($hp[0], $hp[1]); - $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); - $this->redis->setOption(Redis::OPT_PREFIX, 'shm:'); - } + public function __construct(string $args) + { + $this->redis = new Redis(); + $hp = explode(":", $args); + $this->redis->pconnect($hp[0], $hp[1]); + $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); + $this->redis->setOption(Redis::OPT_PREFIX, 'shm:'); + } - public function get(string $key) { - return $this->redis->get($key); - } + public function get(string $key) + { + return $this->redis->get($key); + } - public function set(string $key, $val, int $time=0) { - if($time > 0) { - $this->redis->setEx($key, $time, $val); - } - else { - $this->redis->set($key, $val); - } - } + public function set(string $key, $val, int $time=0) + { + if ($time > 0) { + $this->redis->setEx($key, $time, $val); + } else { + $this->redis->set($key, $val); + } + } - public function delete(string $key) { - $this->redis->delete($key); - } + public function delete(string $key) + { + $this->redis->delete($key); + } } -class Cache { - public $engine; - public $hits=0, $misses=0; - public $time=0; +class Cache +{ + public $engine; + public $hits=0; + public $misses=0; + public $time=0; - public function __construct(?string $dsn) { - $matches = array(); - if($dsn && preg_match("#(.*)://(.*)#", $dsn, $matches)) { - if($matches[1] == "memcache") { - $c = new MemcacheCache($matches[2]); - } - else if($matches[1] == "memcached") { - $c = new MemcachedCache($matches[2]); - } - else if($matches[1] == "apc") { - $c = new APCCache($matches[2]); - } - else if($matches[1] == "redis") { - $c = new RedisCache($matches[2]); - } - } - else { - $c = new NoCache(); - } - $this->engine = $c; - } + public function __construct(?string $dsn) + { + $matches = []; + if ($dsn && preg_match("#(.*)://(.*)#", $dsn, $matches)) { + if ($matches[1] == "memcache") { + $c = new MemcacheCache($matches[2]); + } elseif ($matches[1] == "memcached") { + $c = new MemcachedCache($matches[2]); + } elseif ($matches[1] == "apc") { + $c = new APCCache($matches[2]); + } elseif ($matches[1] == "redis") { + $c = new RedisCache($matches[2]); + } + } else { + $c = new NoCache(); + } + $this->engine = $c; + } - public function get(string $key) { - $val = $this->engine->get($key); - if((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { - $hit = $val === false ? "hit" : "miss"; - file_put_contents("data/cache.log", "Cache $hit: $key\n", FILE_APPEND); - } - if($val !== false) { - $this->hits++; - return $val; - } - else { - $this->misses++; - return false; - } - } + public function get(string $key) + { + $val = $this->engine->get($key); + if ((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { + $hit = $val === false ? "hit" : "miss"; + file_put_contents("data/cache.log", "Cache $hit: $key\n", FILE_APPEND); + } + if ($val !== false) { + $this->hits++; + return $val; + } else { + $this->misses++; + return false; + } + } - public function set(string $key, $val, int $time=0) { - $this->engine->set($key, $val, $time); - if((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { - file_put_contents("data/cache.log", "Cache set: $key ($time)\n", FILE_APPEND); - } - } + public function set(string $key, $val, int $time=0) + { + $this->engine->set($key, $val, $time); + if ((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { + file_put_contents("data/cache.log", "Cache set: $key ($time)\n", FILE_APPEND); + } + } - public function delete(string $key) { - $this->engine->delete($key); - if((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { - file_put_contents("data/cache.log", "Cache delete: $key\n", FILE_APPEND); - } - } + public function delete(string $key) + { + $this->engine->delete($key); + if ((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { + file_put_contents("data/cache.log", "Cache delete: $key\n", FILE_APPEND); + } + } - public function get_hits(): int {return $this->hits;} - public function get_misses(): int {return $this->misses;} + public function get_hits(): int + { + return $this->hits; + } + public function get_misses(): int + { + return $this->misses; + } } - diff --git a/core/captcha.php b/core/captcha.php index 99f5e77d..291192f4 100644 --- a/core/captcha.php +++ b/core/captcha.php @@ -3,53 +3,56 @@ * CAPTCHA abstraction * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -function captcha_get_html(): string { - global $config, $user; +function captcha_get_html(): string +{ + global $config, $user; - if(DEBUG && ip_in_range($_SERVER['REMOTE_ADDR'], "127.0.0.0/8")) return ""; + if (DEBUG && ip_in_range($_SERVER['REMOTE_ADDR'], "127.0.0.0/8")) { + return ""; + } - $captcha = ""; - if($user->is_anonymous() && $config->get_bool("comment_captcha")) { - $r_publickey = $config->get_string("api_recaptcha_pubkey"); - if(!empty($r_publickey)) { - $captcha = " + $captcha = ""; + if ($user->is_anonymous() && $config->get_bool("comment_captcha")) { + $r_publickey = $config->get_string("api_recaptcha_pubkey"); + if (!empty($r_publickey)) { + $captcha = "
"; - } else { - session_start(); - $captcha = Securimage::getCaptchaHtml(['securimage_path' => './vendor/dapphp/securimage/']); - } - } - return $captcha; + } else { + session_start(); + $captcha = Securimage::getCaptchaHtml(['securimage_path' => './vendor/dapphp/securimage/']); + } + } + return $captcha; } -function captcha_check(): bool { - global $config, $user; +function captcha_check(): bool +{ + global $config, $user; - if(DEBUG && ip_in_range($_SERVER['REMOTE_ADDR'], "127.0.0.0/8")) return true; + if (DEBUG && ip_in_range($_SERVER['REMOTE_ADDR'], "127.0.0.0/8")) { + return true; + } - if($user->is_anonymous() && $config->get_bool("comment_captcha")) { - $r_privatekey = $config->get_string('api_recaptcha_privkey'); - if(!empty($r_privatekey)) { - $recaptcha = new \ReCaptcha\ReCaptcha($r_privatekey); - $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']); + if ($user->is_anonymous() && $config->get_bool("comment_captcha")) { + $r_privatekey = $config->get_string('api_recaptcha_privkey'); + if (!empty($r_privatekey)) { + $recaptcha = new \ReCaptcha\ReCaptcha($r_privatekey); + $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']); - if(!$resp->isSuccess()) { - log_info("core", "Captcha failed (ReCaptcha): " . implode("", $resp->getErrorCodes())); - return false; - } - } - else { - session_start(); - $securimg = new Securimage(); - if($securimg->check($_POST['captcha_code']) === false) { - log_info("core", "Captcha failed (Securimage)"); - return false; - } - } - } + if (!$resp->isSuccess()) { + log_info("core", "Captcha failed (ReCaptcha): " . implode("", $resp->getErrorCodes())); + return false; + } + } else { + session_start(); + $securimg = new Securimage(); + if ($securimg->check($_POST['captcha_code']) === false) { + log_info("core", "Captcha failed (Securimage)"); + return false; + } + } + } - return true; + return true; } - - diff --git a/core/config.php b/core/config.php index 7fee9760..889265c4 100644 --- a/core/config.php +++ b/core/config.php @@ -5,100 +5,101 @@ * * An abstract interface for altering a name:value pair list. */ -interface Config { - /** - * Save the list of name:value pairs to wherever they came from, - * so that the next time a page is loaded it will use the new - * configuration. - */ - public function save(string $name=null): void; +interface Config +{ + /** + * Save the list of name:value pairs to wherever they came from, + * so that the next time a page is loaded it will use the new + * configuration. + */ + public function save(string $name=null): void; - //@{ /*--------------------------------- SET ------------------------------------------------------*/ - /** - * Set a configuration option to a new value, regardless of what the value is at the moment. - */ - public function set_int(string $name, ?int $value): void; + //@{ /*--------------------------------- SET ------------------------------------------------------*/ + /** + * Set a configuration option to a new value, regardless of what the value is at the moment. + */ + public function set_int(string $name, ?int $value): void; - /** - * Set a configuration option to a new value, regardless of what the value is at the moment. - */ - public function set_string(string $name, ?string $value): void; + /** + * Set a configuration option to a new value, regardless of what the value is at the moment. + */ + public function set_string(string $name, ?string $value): void; - /** - * Set a configuration option to a new value, regardless of what the value is at the moment. - * @param null|bool|string $value - */ - public function set_bool(string $name, $value): void; + /** + * Set a configuration option to a new value, regardless of what the value is at the moment. + * @param null|bool|string $value + */ + public function set_bool(string $name, $value): void; - /** - * Set a configuration option to a new value, regardless of what the value is at the moment. - */ - public function set_array(string $name, array $value): void; - //@} /*--------------------------------------------------------------------------------------------*/ + /** + * Set a configuration option to a new value, regardless of what the value is at the moment. + */ + public function set_array(string $name, array $value): void; + //@} /*--------------------------------------------------------------------------------------------*/ - //@{ /*-------------------------------- SET DEFAULT -----------------------------------------------*/ - /** - * Set a configuration option to a new value, if there is no value currently. - * - * Extensions should generally call these from their InitExtEvent handlers. - * This has the advantage that the values will show up in the "advanced" setup - * page where they can be modified, while calling get_* with a "default" - * parameter won't show up. - */ - public function set_default_int(string $name, int $value): void; + //@{ /*-------------------------------- SET DEFAULT -----------------------------------------------*/ + /** + * Set a configuration option to a new value, if there is no value currently. + * + * Extensions should generally call these from their InitExtEvent handlers. + * This has the advantage that the values will show up in the "advanced" setup + * page where they can be modified, while calling get_* with a "default" + * parameter won't show up. + */ + public function set_default_int(string $name, int $value): void; - /** - * Set a configuration option to a new value, if there is no value currently. - * - * Extensions should generally call these from their InitExtEvent handlers. - * This has the advantage that the values will show up in the "advanced" setup - * page where they can be modified, while calling get_* with a "default" - * parameter won't show up. - */ - public function set_default_string(string $name, string $value): void; + /** + * Set a configuration option to a new value, if there is no value currently. + * + * Extensions should generally call these from their InitExtEvent handlers. + * This has the advantage that the values will show up in the "advanced" setup + * page where they can be modified, while calling get_* with a "default" + * parameter won't show up. + */ + public function set_default_string(string $name, string $value): void; - /** - * Set a configuration option to a new value, if there is no value currently. - * - * Extensions should generally call these from their InitExtEvent handlers. - * This has the advantage that the values will show up in the "advanced" setup - * page where they can be modified, while calling get_* with a "default" - * parameter won't show up. - */ - public function set_default_bool(string $name, bool $value): void; + /** + * Set a configuration option to a new value, if there is no value currently. + * + * Extensions should generally call these from their InitExtEvent handlers. + * This has the advantage that the values will show up in the "advanced" setup + * page where they can be modified, while calling get_* with a "default" + * parameter won't show up. + */ + public function set_default_bool(string $name, bool $value): void; - /** - * Set a configuration option to a new value, if there is no value currently. - * - * Extensions should generally call these from their InitExtEvent handlers. - * This has the advantage that the values will show up in the "advanced" setup - * page where they can be modified, while calling get_* with a "default" - * parameter won't show up. - */ - public function set_default_array(string $name, array $value): void; - //@} /*--------------------------------------------------------------------------------------------*/ + /** + * Set a configuration option to a new value, if there is no value currently. + * + * Extensions should generally call these from their InitExtEvent handlers. + * This has the advantage that the values will show up in the "advanced" setup + * page where they can be modified, while calling get_* with a "default" + * parameter won't show up. + */ + public function set_default_array(string $name, array $value): void; + //@} /*--------------------------------------------------------------------------------------------*/ - //@{ /*--------------------------------- GET ------------------------------------------------------*/ - /** - * Pick a value out of the table by name, cast to the appropriate data type. - */ - public function get_int(string $name, ?int $default=null): ?int; + //@{ /*--------------------------------- GET ------------------------------------------------------*/ + /** + * Pick a value out of the table by name, cast to the appropriate data type. + */ + public function get_int(string $name, ?int $default=null): ?int; - /** - * Pick a value out of the table by name, cast to the appropriate data type. - */ - public function get_string(string $name, ?string $default=null): ?string; + /** + * Pick a value out of the table by name, cast to the appropriate data type. + */ + public function get_string(string $name, ?string $default=null): ?string; - /** - * Pick a value out of the table by name, cast to the appropriate data type. - */ - public function get_bool(string $name, ?bool $default=null): ?bool; + /** + * Pick a value out of the table by name, cast to the appropriate data type. + */ + public function get_bool(string $name, ?bool $default=null): ?bool; - /** - * Pick a value out of the table by name, cast to the appropriate data type. - */ - public function get_array(string $name, ?array $default=array()): ?array; - //@} /*--------------------------------------------------------------------------------------------*/ + /** + * Pick a value out of the table by name, cast to the appropriate data type. + */ + public function get_array(string $name, ?array $default=[]): ?array; + //@} /*--------------------------------------------------------------------------------------------*/ } @@ -108,77 +109,90 @@ interface Config { * Common methods for manipulating the list, loading and saving is * left to the concrete implementation */ -abstract class BaseConfig implements Config { - public $values = array(); +abstract class BaseConfig implements Config +{ + public $values = []; - public function set_int(string $name, $value) { - $this->values[$name] = parse_shorthand_int($value); - $this->save($name); - } + public function set_int(string $name, $value) + { + $this->values[$name] = parse_shorthand_int($value); + $this->save($name); + } - public function set_string(string $name, $value) { - $this->values[$name] = $value; - $this->save($name); - } + public function set_string(string $name, $value) + { + $this->values[$name] = $value; + $this->save($name); + } - public function set_bool(string $name, $value) { - $this->values[$name] = bool_escape($value) ? 'Y' : 'N'; - $this->save($name); - } + public function set_bool(string $name, $value) + { + $this->values[$name] = bool_escape($value) ? 'Y' : 'N'; + $this->save($name); + } - public function set_array(string $name, array $value) { - $this->values[$name] = implode(",", $value); - $this->save($name); - } + public function set_array(string $name, array $value) + { + $this->values[$name] = implode(",", $value); + $this->save($name); + } - public function set_default_int(string $name, int $value) { - if(is_null($this->get($name))) { - $this->values[$name] = $value; - } - } + public function set_default_int(string $name, int $value) + { + if (is_null($this->get($name))) { + $this->values[$name] = $value; + } + } - public function set_default_string(string $name, string $value) { - if(is_null($this->get($name))) { - $this->values[$name] = $value; - } - } + public function set_default_string(string $name, string $value) + { + if (is_null($this->get($name))) { + $this->values[$name] = $value; + } + } - public function set_default_bool(string $name, bool $value) { - if(is_null($this->get($name))) { - $this->values[$name] = $value ? 'Y' : 'N'; - } - } + public function set_default_bool(string $name, bool $value) + { + if (is_null($this->get($name))) { + $this->values[$name] = $value ? 'Y' : 'N'; + } + } - public function set_default_array(string $name, array $value) { - if(is_null($this->get($name))) { - $this->values[$name] = implode(",", $value); - } - } + public function set_default_array(string $name, array $value) + { + if (is_null($this->get($name))) { + $this->values[$name] = implode(",", $value); + } + } - public function get_int(string $name, $default=null) { - return (int)($this->get($name, $default)); - } + public function get_int(string $name, $default=null) + { + return (int)($this->get($name, $default)); + } - public function get_string(string $name, $default=null) { - return $this->get($name, $default); - } + public function get_string(string $name, $default=null) + { + return $this->get($name, $default); + } - public function get_bool(string $name, $default=null) { - return bool_escape($this->get($name, $default)); - } + public function get_bool(string $name, $default=null) + { + return bool_escape($this->get($name, $default)); + } - public function get_array(string $name, array $default=array()): array { - return explode(",", $this->get($name, "")); - } + public function get_array(string $name, array $default=[]): array + { + return explode(",", $this->get($name, "")); + } - private function get(string $name, $default=null) { - if(isset($this->values[$name])) { - return $this->values[$name]; - } - else { - return $default; - } - } + private function get(string $name, $default=null) + { + if (isset($this->values[$name])) { + return $this->values[$name]; + } else { + return $default; + } + } } @@ -187,14 +201,17 @@ abstract class BaseConfig implements Config { * * For testing, mostly. */ -class HardcodeConfig extends BaseConfig { - public function __construct(array $dict) { - $this->values = $dict; - } +class HardcodeConfig extends BaseConfig +{ + public function __construct(array $dict) + { + $this->values = $dict; + } - public function save(string $name=null) { - // static config is static - } + public function save(string $name=null) + { + // static config is static + } } @@ -208,26 +225,27 @@ class HardcodeConfig extends BaseConfig { * $config['baz'] = "qux"; * ?> */ -class StaticConfig extends BaseConfig { - public function __construct(string $filename) { - if(file_exists($filename)) { - $config = array(); - require_once $filename; - if(!empty($config)) { - $this->values = $config; - } - else { - throw new Exception("Config file '$filename' doesn't contain any config"); - } - } - else { - throw new Exception("Config file '$filename' missing"); - } - } +class StaticConfig extends BaseConfig +{ + public function __construct(string $filename) + { + if (file_exists($filename)) { + $config = []; + require_once $filename; + if (!empty($config)) { + $this->values = $config; + } else { + throw new Exception("Config file '$filename' doesn't contain any config"); + } + } else { + throw new Exception("Config file '$filename' missing"); + } + } - public function save(string $name=null) { - // static config is static - } + public function save(string $name=null) + { + // static config is static + } } @@ -244,51 +262,53 @@ class StaticConfig extends BaseConfig { * ); * \endcode */ -class DatabaseConfig extends BaseConfig { - /** @var Database */ - private $database = null; +class DatabaseConfig extends BaseConfig +{ + /** @var Database */ + private $database = null; - public function __construct(Database $database) { - $this->database = $database; + public function __construct(Database $database) + { + $this->database = $database; - $cached = $this->database->cache->get("config"); - if($cached) { - $this->values = $cached; - } - else { - $this->values = array(); - foreach($this->database->get_all("SELECT name, value FROM config") as $row) { - $this->values[$row["name"]] = $row["value"]; - } - $this->database->cache->set("config", $this->values); - } - } + $cached = $this->database->cache->get("config"); + if ($cached) { + $this->values = $cached; + } else { + $this->values = []; + foreach ($this->database->get_all("SELECT name, value FROM config") as $row) { + $this->values[$row["name"]] = $row["value"]; + } + $this->database->cache->set("config", $this->values); + } + } - public function save(string $name=null) { - if(is_null($name)) { - reset($this->values); // rewind the array to the first element - foreach($this->values as $name => $value) { - $this->save($name); - } - } - else { - $this->database->Execute("DELETE FROM config WHERE name = :name", array("name"=>$name)); - $this->database->Execute("INSERT INTO config VALUES (:name, :value)", array("name"=>$name, "value"=>$this->values[$name])); - } - // rather than deleting and having some other request(s) do a thundering - // herd of race-conditioned updates, just save the updated version once here - $this->database->cache->set("config", $this->values); - } + public function save(string $name=null) + { + if (is_null($name)) { + reset($this->values); // rewind the array to the first element + foreach ($this->values as $name => $value) { + $this->save($name); + } + } else { + $this->database->Execute("DELETE FROM config WHERE name = :name", ["name"=>$name]); + $this->database->Execute("INSERT INTO config VALUES (:name, :value)", ["name"=>$name, "value"=>$this->values[$name]]); + } + // rather than deleting and having some other request(s) do a thundering + // herd of race-conditioned updates, just save the updated version once here + $this->database->cache->set("config", $this->values); + } } /** * Class MockConfig */ -class MockConfig extends HardcodeConfig { - public function __construct(array $config=array()) { - $config["db_version"] = "999"; - $config["anon_id"] = "0"; - parent::__construct($config); - } +class MockConfig extends HardcodeConfig +{ + public function __construct(array $config=[]) + { + $config["db_version"] = "999"; + $config["anon_id"] = "0"; + parent::__construct($config); + } } - diff --git a/core/database.php b/core/database.php index 57720293..9dd63b9e 100644 --- a/core/database.php +++ b/core/database.php @@ -2,353 +2,418 @@ /** * A class for controlled database access */ -class Database { - /** - * The PDO database connection object, for anyone who wants direct access. - * @var null|PDO - */ - private $db = null; - - /** - * @var float - */ - public $dbtime = 0.0; +class Database +{ + /** + * The PDO database connection object, for anyone who wants direct access. + * @var null|PDO + */ + private $db = null; + + /** + * @var float + */ + public $dbtime = 0.0; - /** - * Meta info about the database engine. - * @var DBEngine|null - */ - private $engine = null; + /** + * Meta info about the database engine. + * @var DBEngine|null + */ + private $engine = null; - /** - * The currently active cache engine. - * @var Cache|null - */ - public $cache = null; + /** + * The currently active cache engine. + * @var Cache|null + */ + public $cache = null; - /** - * A boolean flag to track if we already have an active transaction. - * (ie: True if beginTransaction() already called) - * - * @var bool - */ - public $transaction = false; + /** + * A boolean flag to track if we already have an active transaction. + * (ie: True if beginTransaction() already called) + * + * @var bool + */ + public $transaction = false; - /** - * How many queries this DB object has run - */ - public $query_count = 0; + /** + * How many queries this DB object has run + */ + public $query_count = 0; - /** - * For now, only connect to the cache, as we will pretty much certainly - * need it. There are some pages where all the data is in cache, so the - * DB connection is on-demand. - */ - public function __construct() { - $this->cache = new Cache(CACHE_DSN); - } + /** + * For now, only connect to the cache, as we will pretty much certainly + * need it. There are some pages where all the data is in cache, so the + * DB connection is on-demand. + */ + public function __construct() + { + $this->cache = new Cache(CACHE_DSN); + } - private function connect_db() { - # FIXME: detect ADODB URI, automatically translate PDO DSN + private function connect_db() + { + # FIXME: detect ADODB URI, automatically translate PDO DSN - /* - * Why does the abstraction layer act differently depending on the - * back-end? Because PHP is deliberately retarded. - * - * http://stackoverflow.com/questions/237367 - */ - $matches = array(); $db_user=null; $db_pass=null; - if(preg_match("/user=([^;]*)/", DATABASE_DSN, $matches)) $db_user=$matches[1]; - if(preg_match("/password=([^;]*)/", DATABASE_DSN, $matches)) $db_pass=$matches[1]; + /* + * Why does the abstraction layer act differently depending on the + * back-end? Because PHP is deliberately retarded. + * + * http://stackoverflow.com/questions/237367 + */ + $matches = []; + $db_user=null; + $db_pass=null; + if (preg_match("/user=([^;]*)/", DATABASE_DSN, $matches)) { + $db_user=$matches[1]; + } + if (preg_match("/password=([^;]*)/", DATABASE_DSN, $matches)) { + $db_pass=$matches[1]; + } - // https://bugs.php.net/bug.php?id=70221 - $ka = DATABASE_KA; - if(version_compare(PHP_VERSION, "6.9.9") == 1 && $this->get_driver_name() == "sqlite") { - $ka = false; - } + // https://bugs.php.net/bug.php?id=70221 + $ka = DATABASE_KA; + if (version_compare(PHP_VERSION, "6.9.9") == 1 && $this->get_driver_name() == "sqlite") { + $ka = false; + } - $db_params = array( - PDO::ATTR_PERSISTENT => $ka, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION - ); - $this->db = new PDO(DATABASE_DSN, $db_user, $db_pass, $db_params); + $db_params = [ + PDO::ATTR_PERSISTENT => $ka, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION + ]; + $this->db = new PDO(DATABASE_DSN, $db_user, $db_pass, $db_params); - $this->connect_engine(); - $this->engine->init($this->db); + $this->connect_engine(); + $this->engine->init($this->db); - $this->beginTransaction(); - } + $this->beginTransaction(); + } - private function connect_engine() { - if(preg_match("/^([^:]*)/", DATABASE_DSN, $matches)) $db_proto=$matches[1]; - else throw new SCoreException("Can't figure out database engine"); + private function connect_engine() + { + if (preg_match("/^([^:]*)/", DATABASE_DSN, $matches)) { + $db_proto=$matches[1]; + } else { + throw new SCoreException("Can't figure out database engine"); + } - if($db_proto === "mysql") { - $this->engine = new MySQL(); - } - else if($db_proto === "pgsql") { - $this->engine = new PostgreSQL(); - } - else if($db_proto === "sqlite") { - $this->engine = new SQLite(); - } - else { - die('Unknown PDO driver: '.$db_proto); - } - } + if ($db_proto === "mysql") { + $this->engine = new MySQL(); + } elseif ($db_proto === "pgsql") { + $this->engine = new PostgreSQL(); + } elseif ($db_proto === "sqlite") { + $this->engine = new SQLite(); + } else { + die('Unknown PDO driver: '.$db_proto); + } + } - public function beginTransaction() { - if ($this->transaction === false) { - $this->db->beginTransaction(); - $this->transaction = true; - } - } + public function beginTransaction() + { + if ($this->transaction === false) { + $this->db->beginTransaction(); + $this->transaction = true; + } + } - public function commit(): bool { - if(!is_null($this->db)) { - if ($this->transaction === true) { - $this->transaction = false; - return $this->db->commit(); - } - else { - throw new SCoreException("

Database Transaction Error: Unable to call commit() as there is no transaction currently open."); - } - } - else { - throw new SCoreException("

Database Transaction Error: Unable to call commit() as there is no connection currently open."); - } - } + public function commit(): bool + { + if (!is_null($this->db)) { + if ($this->transaction === true) { + $this->transaction = false; + return $this->db->commit(); + } else { + throw new SCoreException("

Database Transaction Error: Unable to call commit() as there is no transaction currently open."); + } + } else { + throw new SCoreException("

Database Transaction Error: Unable to call commit() as there is no connection currently open."); + } + } - public function rollback(): bool { - if(!is_null($this->db)) { - if ($this->transaction === true) { - $this->transaction = false; - return $this->db->rollback(); - } - else { - throw new SCoreException("

Database Transaction Error: Unable to call rollback() as there is no transaction currently open."); - } - } - else { - throw new SCoreException("

Database Transaction Error: Unable to call rollback() as there is no connection currently open."); - } - } + public function rollback(): bool + { + if (!is_null($this->db)) { + if ($this->transaction === true) { + $this->transaction = false; + return $this->db->rollback(); + } else { + throw new SCoreException("

Database Transaction Error: Unable to call rollback() as there is no transaction currently open."); + } + } else { + throw new SCoreException("

Database Transaction Error: Unable to call rollback() as there is no connection currently open."); + } + } - public function escape(string $input): string { - if(is_null($this->db)) $this->connect_db(); - return $this->db->Quote($input); - } + public function escape(string $input): string + { + if (is_null($this->db)) { + $this->connect_db(); + } + return $this->db->Quote($input); + } - public function scoreql_to_sql(string $input): string { - if(is_null($this->engine)) $this->connect_engine(); - return $this->engine->scoreql_to_sql($input); - } + public function scoreql_to_sql(string $input): string + { + if (is_null($this->engine)) { + $this->connect_engine(); + } + return $this->engine->scoreql_to_sql($input); + } - public function get_driver_name(): string { - if(is_null($this->engine)) $this->connect_engine(); - return $this->engine->name; - } + public function get_driver_name(): string + { + if (is_null($this->engine)) { + $this->connect_engine(); + } + return $this->engine->name; + } - private function count_execs(string $sql, array $inputarray) { - if((DEBUG_SQL === true) || (is_null(DEBUG_SQL) && @$_GET['DEBUG_SQL'])) { - $sql = trim(preg_replace('/\s+/msi', ' ', $sql)); - if(isset($inputarray) && is_array($inputarray) && !empty($inputarray)) { - $text = $sql." -- ".join(", ", $inputarray)."\n"; - } - else { - $text = $sql."\n"; - } - file_put_contents("data/sql.log", $text, FILE_APPEND); - } - if(!is_array($inputarray)) $this->query_count++; - # handle 2-dimensional input arrays - else if(is_array(reset($inputarray))) $this->query_count += sizeof($inputarray); - else $this->query_count++; - } + private function count_execs(string $sql, array $inputarray) + { + if ((DEBUG_SQL === true) || (is_null(DEBUG_SQL) && @$_GET['DEBUG_SQL'])) { + $sql = trim(preg_replace('/\s+/msi', ' ', $sql)); + if (isset($inputarray) && is_array($inputarray) && !empty($inputarray)) { + $text = $sql." -- ".join(", ", $inputarray)."\n"; + } else { + $text = $sql."\n"; + } + file_put_contents("data/sql.log", $text, FILE_APPEND); + } + if (!is_array($inputarray)) { + $this->query_count++; + } + # handle 2-dimensional input arrays + elseif (is_array(reset($inputarray))) { + $this->query_count += sizeof($inputarray); + } else { + $this->query_count++; + } + } - private function count_time(string $method, float $start) { - if((DEBUG_SQL === true) || (is_null(DEBUG_SQL) && @$_GET['DEBUG_SQL'])) { - $text = $method.":".(microtime(true) - $start)."\n"; - file_put_contents("data/sql.log", $text, FILE_APPEND); - } - $this->dbtime += microtime(true) - $start; - } + private function count_time(string $method, float $start) + { + if ((DEBUG_SQL === true) || (is_null(DEBUG_SQL) && @$_GET['DEBUG_SQL'])) { + $text = $method.":".(microtime(true) - $start)."\n"; + file_put_contents("data/sql.log", $text, FILE_APPEND); + } + $this->dbtime += microtime(true) - $start; + } - public function execute(string $query, array $args=array()): PDOStatement { - try { - if(is_null($this->db)) $this->connect_db(); - $this->count_execs($query, $args); - $stmt = $this->db->prepare( - "-- " . str_replace("%2F", "/", urlencode(@$_GET['q'])). "\n" . - $query - ); - // $stmt = $this->db->prepare($query); - if (!array_key_exists(0, $args)) { - foreach($args as $name=>$value) { - if(is_numeric($value)) { - $stmt->bindValue(':'.$name, $value, PDO::PARAM_INT); - } - else { - $stmt->bindValue(':'.$name, $value, PDO::PARAM_STR); - } - } - $stmt->execute(); - } - else { - $stmt->execute($args); - } - return $stmt; - } - catch(PDOException $pdoe) { - throw new SCoreException($pdoe->getMessage()."

Query: ".$query); - } - } + public function execute(string $query, array $args=[]): PDOStatement + { + try { + if (is_null($this->db)) { + $this->connect_db(); + } + $this->count_execs($query, $args); + $stmt = $this->db->prepare( + "-- " . str_replace("%2F", "/", urlencode(@$_GET['q'])). "\n" . + $query + ); + // $stmt = $this->db->prepare($query); + if (!array_key_exists(0, $args)) { + foreach ($args as $name=>$value) { + if (is_numeric($value)) { + $stmt->bindValue(':'.$name, $value, PDO::PARAM_INT); + } else { + $stmt->bindValue(':'.$name, $value, PDO::PARAM_STR); + } + } + $stmt->execute(); + } else { + $stmt->execute($args); + } + return $stmt; + } catch (PDOException $pdoe) { + throw new SCoreException($pdoe->getMessage()."

Query: ".$query); + } + } - /** - * Execute an SQL query and return a 2D array. - */ - public function get_all(string $query, array $args=array()): array { - $_start = microtime(true); - $data = $this->execute($query, $args)->fetchAll(); - $this->count_time("get_all", $_start); - return $data; - } + /** + * Execute an SQL query and return a 2D array. + */ + public function get_all(string $query, array $args=[]): array + { + $_start = microtime(true); + $data = $this->execute($query, $args)->fetchAll(); + $this->count_time("get_all", $_start); + return $data; + } - /** - * Execute an SQL query and return a single row. - */ - public function get_row(string $query, array $args=array()) { - $_start = microtime(true); - $row = $this->execute($query, $args)->fetch(); - $this->count_time("get_row", $_start); - return $row ? $row : null; - } + /** + * Execute an SQL query and return a single row. + */ + public function get_row(string $query, array $args=[]) + { + $_start = microtime(true); + $row = $this->execute($query, $args)->fetch(); + $this->count_time("get_row", $_start); + return $row ? $row : null; + } - /** - * Execute an SQL query and return the first column of each row. - */ - public function get_col(string $query, array $args=array()): array { - $_start = microtime(true); - $stmt = $this->execute($query, $args); - $res = array(); - foreach($stmt as $row) { - $res[] = $row[0]; - } - $this->count_time("get_col", $_start); - return $res; - } + /** + * Execute an SQL query and return the first column of each row. + */ + public function get_col(string $query, array $args=[]): array + { + $_start = microtime(true); + $stmt = $this->execute($query, $args); + $res = []; + foreach ($stmt as $row) { + $res[] = $row[0]; + } + $this->count_time("get_col", $_start); + return $res; + } - /** - * Execute an SQL query and return the the first row => the second row. - */ - public function get_pairs(string $query, array $args=array()): array { - $_start = microtime(true); - $stmt = $this->execute($query, $args); - $res = array(); - foreach($stmt as $row) { - $res[$row[0]] = $row[1]; - } - $this->count_time("get_pairs", $_start); - return $res; - } + /** + * Execute an SQL query and return the the first row => the second row. + */ + public function get_pairs(string $query, array $args=[]): array + { + $_start = microtime(true); + $stmt = $this->execute($query, $args); + $res = []; + foreach ($stmt as $row) { + $res[$row[0]] = $row[1]; + } + $this->count_time("get_pairs", $_start); + return $res; + } - /** - * Execute an SQL query and return a single value. - */ - public function get_one(string $query, array $args=array()) { - $_start = microtime(true); - $row = $this->execute($query, $args)->fetch(); - $this->count_time("get_one", $_start); - return $row[0]; - } + /** + * Execute an SQL query and return a single value. + */ + public function get_one(string $query, array $args=[]) + { + $_start = microtime(true); + $row = $this->execute($query, $args)->fetch(); + $this->count_time("get_one", $_start); + return $row[0]; + } - /** - * Get the ID of the last inserted row. - */ - public function get_last_insert_id(string $seq): int { - if($this->engine->name == "pgsql") { - return $this->db->lastInsertId($seq); - } - else { - return $this->db->lastInsertId(); - } - } + /** + * Get the ID of the last inserted row. + */ + public function get_last_insert_id(string $seq): int + { + if ($this->engine->name == "pgsql") { + return $this->db->lastInsertId($seq); + } else { + return $this->db->lastInsertId(); + } + } - /** - * Create a table from pseudo-SQL. - */ - public function create_table(string $name, string $data): void { - if(is_null($this->engine)) { $this->connect_engine(); } - $data = trim($data, ", \t\n\r\0\x0B"); // mysql doesn't like trailing commas - $this->execute($this->engine->create_table_sql($name, $data)); - } + /** + * Create a table from pseudo-SQL. + */ + public function create_table(string $name, string $data): void + { + if (is_null($this->engine)) { + $this->connect_engine(); + } + $data = trim($data, ", \t\n\r\0\x0B"); // mysql doesn't like trailing commas + $this->execute($this->engine->create_table_sql($name, $data)); + } - /** - * Returns the number of tables present in the current database. - * - * @throws SCoreException - */ - public function count_tables(): int { - if(is_null($this->db) || is_null($this->engine)) $this->connect_db(); + /** + * Returns the number of tables present in the current database. + * + * @throws SCoreException + */ + public function count_tables(): int + { + if (is_null($this->db) || is_null($this->engine)) { + $this->connect_db(); + } - if($this->engine->name === "mysql") { - return count( - $this->get_all("SHOW TABLES") - ); - } else if ($this->engine->name === "pgsql") { - return count( - $this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'") - ); - } else if ($this->engine->name === "sqlite") { - return count( - $this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'") - ); - } else { - throw new SCoreException("Can't count tables for database type {$this->engine->name}"); - } - } + if ($this->engine->name === "mysql") { + return count( + $this->get_all("SHOW TABLES") + ); + } elseif ($this->engine->name === "pgsql") { + return count( + $this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'") + ); + } elseif ($this->engine->name === "sqlite") { + return count( + $this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'") + ); + } else { + throw new SCoreException("Can't count tables for database type {$this->engine->name}"); + } + } } -class MockDatabase extends Database { - /** @var int */ - private $query_id = 0; - /** @var array */ - private $responses = array(); - /** @var \NoCache|null */ - public $cache = null; +class MockDatabase extends Database +{ + /** @var int */ + private $query_id = 0; + /** @var array */ + private $responses = []; + /** @var \NoCache|null */ + public $cache = null; - public function __construct(array $responses = array()) { - $this->cache = new NoCache(); - $this->responses = $responses; - } + public function __construct(array $responses = []) + { + $this->cache = new NoCache(); + $this->responses = $responses; + } - public function execute(string $query, array $params=array()): PDOStatement { - log_debug("mock-database", - "QUERY: " . $query . - "\nARGS: " . var_export($params, true) . - "\nRETURN: " . var_export($this->responses[$this->query_id], true) - ); - return $this->responses[$this->query_id++]; - } - public function _execute(string $query, array $params=array()) { - log_debug("mock-database", - "QUERY: " . $query . - "\nARGS: " . var_export($params, true) . - "\nRETURN: " . var_export($this->responses[$this->query_id], true) - ); - return $this->responses[$this->query_id++]; - } + public function execute(string $query, array $params=[]): PDOStatement + { + log_debug( + "mock-database", + "QUERY: " . $query . + "\nARGS: " . var_export($params, true) . + "\nRETURN: " . var_export($this->responses[$this->query_id], true) + ); + return $this->responses[$this->query_id++]; + } + public function _execute(string $query, array $params=[]) + { + log_debug( + "mock-database", + "QUERY: " . $query . + "\nARGS: " . var_export($params, true) . + "\nRETURN: " . var_export($this->responses[$this->query_id], true) + ); + return $this->responses[$this->query_id++]; + } - public function get_all(string $query, array $args=array()): array {return $this->_execute($query, $args);} - public function get_row(string $query, array $args=array()) {return $this->_execute($query, $args);} - public function get_col(string $query, array $args=array()): array {return $this->_execute($query, $args);} - public function get_pairs(string $query, array $args=array()): array {return $this->_execute($query, $args);} - public function get_one(string $query, array $args=array()) {return $this->_execute($query, $args);} + public function get_all(string $query, array $args=[]): array + { + return $this->_execute($query, $args); + } + public function get_row(string $query, array $args=[]) + { + return $this->_execute($query, $args); + } + public function get_col(string $query, array $args=[]): array + { + return $this->_execute($query, $args); + } + public function get_pairs(string $query, array $args=[]): array + { + return $this->_execute($query, $args); + } + public function get_one(string $query, array $args=[]) + { + return $this->_execute($query, $args); + } - public function get_last_insert_id(string $seq): int {return $this->query_id;} + public function get_last_insert_id(string $seq): int + { + return $this->query_id; + } - public function scoreql_to_sql(string $sql): string {return $sql;} - public function create_table(string $name, string $def) {} - public function connect_engine() {} + public function scoreql_to_sql(string $sql): string + { + return $sql; + } + public function create_table(string $name, string $def) + { + } + public function connect_engine() + { + } } - diff --git a/core/dbengine.php b/core/dbengine.php index 18b6f512..bb7c674b 100644 --- a/core/dbengine.php +++ b/core/dbengine.php @@ -1,142 +1,188 @@ exec("SET NAMES utf8;"); - } + public function init(PDO $db) + { + $db->exec("SET NAMES utf8;"); + } - public function scoreql_to_sql(string $data): string { - $data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY auto_increment", $data); - $data = str_replace("SCORE_INET", "VARCHAR(45)", $data); - $data = str_replace("SCORE_BOOL_Y", "'Y'", $data); - $data = str_replace("SCORE_BOOL_N", "'N'", $data); - $data = str_replace("SCORE_BOOL", "ENUM('Y', 'N')", $data); - $data = str_replace("SCORE_DATETIME", "DATETIME", $data); - $data = str_replace("SCORE_NOW", "\"1970-01-01\"", $data); - $data = str_replace("SCORE_STRNORM", "", $data); - $data = str_replace("SCORE_ILIKE", "LIKE", $data); - return $data; - } + public function scoreql_to_sql(string $data): string + { + $data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY auto_increment", $data); + $data = str_replace("SCORE_INET", "VARCHAR(45)", $data); + $data = str_replace("SCORE_BOOL_Y", "'Y'", $data); + $data = str_replace("SCORE_BOOL_N", "'N'", $data); + $data = str_replace("SCORE_BOOL", "ENUM('Y', 'N')", $data); + $data = str_replace("SCORE_DATETIME", "DATETIME", $data); + $data = str_replace("SCORE_NOW", "\"1970-01-01\"", $data); + $data = str_replace("SCORE_STRNORM", "", $data); + $data = str_replace("SCORE_ILIKE", "LIKE", $data); + return $data; + } - public function create_table_sql(string $name, string $data): string { - $data = $this->scoreql_to_sql($data); - $ctes = "ENGINE=InnoDB DEFAULT CHARSET='utf8'"; - return 'CREATE TABLE '.$name.' ('.$data.') '.$ctes; - } + public function create_table_sql(string $name, string $data): string + { + $data = $this->scoreql_to_sql($data); + $ctes = "ENGINE=InnoDB DEFAULT CHARSET='utf8'"; + return 'CREATE TABLE '.$name.' ('.$data.') '.$ctes; + } } -class PostgreSQL extends DBEngine { - /** @var string */ - public $name = "pgsql"; +class PostgreSQL extends DBEngine +{ + /** @var string */ + public $name = "pgsql"; - public function init(PDO $db) { - if(array_key_exists('REMOTE_ADDR', $_SERVER)) { - $db->exec("SET application_name TO 'shimmie [{$_SERVER['REMOTE_ADDR']}]';"); - } - else { - $db->exec("SET application_name TO 'shimmie [local]';"); - } - $db->exec("SET statement_timeout TO 10000;"); - } + public function init(PDO $db) + { + if (array_key_exists('REMOTE_ADDR', $_SERVER)) { + $db->exec("SET application_name TO 'shimmie [{$_SERVER['REMOTE_ADDR']}]';"); + } else { + $db->exec("SET application_name TO 'shimmie [local]';"); + } + $db->exec("SET statement_timeout TO 10000;"); + } - public function scoreql_to_sql(string $data): string { - $data = str_replace("SCORE_AIPK", "SERIAL PRIMARY KEY", $data); - $data = str_replace("SCORE_INET", "INET", $data); - $data = str_replace("SCORE_BOOL_Y", "'t'", $data); - $data = str_replace("SCORE_BOOL_N", "'f'", $data); - $data = str_replace("SCORE_BOOL", "BOOL", $data); - $data = str_replace("SCORE_DATETIME", "TIMESTAMP", $data); - $data = str_replace("SCORE_NOW", "current_timestamp", $data); - $data = str_replace("SCORE_STRNORM", "lower", $data); - $data = str_replace("SCORE_ILIKE", "ILIKE", $data); - return $data; - } + public function scoreql_to_sql(string $data): string + { + $data = str_replace("SCORE_AIPK", "SERIAL PRIMARY KEY", $data); + $data = str_replace("SCORE_INET", "INET", $data); + $data = str_replace("SCORE_BOOL_Y", "'t'", $data); + $data = str_replace("SCORE_BOOL_N", "'f'", $data); + $data = str_replace("SCORE_BOOL", "BOOL", $data); + $data = str_replace("SCORE_DATETIME", "TIMESTAMP", $data); + $data = str_replace("SCORE_NOW", "current_timestamp", $data); + $data = str_replace("SCORE_STRNORM", "lower", $data); + $data = str_replace("SCORE_ILIKE", "ILIKE", $data); + return $data; + } - public function create_table_sql(string $name, string $data): string { - $data = $this->scoreql_to_sql($data); - return "CREATE TABLE $name ($data)"; - } + public function create_table_sql(string $name, string $data): string + { + $data = $this->scoreql_to_sql($data); + return "CREATE TABLE $name ($data)"; + } } // shimmie functions for export to sqlite -function _unix_timestamp($date) { return strtotime($date); } -function _now() { return date("Y-m-d h:i:s"); } -function _floor($a) { return floor($a); } -function _log($a, $b=null) { - if(is_null($b)) return log($a); - else return log($a, $b); +function _unix_timestamp($date) +{ + return strtotime($date); } -function _isnull($a) { return is_null($a); } -function _md5($a) { return md5($a); } -function _concat($a, $b) { return $a . $b; } -function _lower($a) { return strtolower($a); } -function _rand() { return rand(); } -function _ln($n) { return log($n); } - -class SQLite extends DBEngine { - /** @var string */ - public $name = "sqlite"; - - public function init(PDO $db) { - ini_set('sqlite.assoc_case', 0); - $db->exec("PRAGMA foreign_keys = ON;"); - $db->sqliteCreateFunction('UNIX_TIMESTAMP', '_unix_timestamp', 1); - $db->sqliteCreateFunction('now', '_now', 0); - $db->sqliteCreateFunction('floor', '_floor', 1); - $db->sqliteCreateFunction('log', '_log'); - $db->sqliteCreateFunction('isnull', '_isnull', 1); - $db->sqliteCreateFunction('md5', '_md5', 1); - $db->sqliteCreateFunction('concat', '_concat', 2); - $db->sqliteCreateFunction('lower', '_lower', 1); - $db->sqliteCreateFunction('rand', '_rand', 0); - $db->sqliteCreateFunction('ln', '_ln', 1); - } - - public function scoreql_to_sql(string $data): string { - $data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY", $data); - $data = str_replace("SCORE_INET", "VARCHAR(45)", $data); - $data = str_replace("SCORE_BOOL_Y", "'Y'", $data); - $data = str_replace("SCORE_BOOL_N", "'N'", $data); - $data = str_replace("SCORE_BOOL", "CHAR(1)", $data); - $data = str_replace("SCORE_NOW", "\"1970-01-01\"", $data); - $data = str_replace("SCORE_STRNORM", "lower", $data); - $data = str_replace("SCORE_ILIKE", "LIKE", $data); - return $data; - } - - public function create_table_sql(string $name, string $data): string { - $data = $this->scoreql_to_sql($data); - $cols = array(); - $extras = ""; - foreach(explode(",", $data) as $bit) { - $matches = array(); - if(preg_match("/(UNIQUE)? ?INDEX\s*\((.*)\)/", $bit, $matches)) { - $uni = $matches[1]; - $col = $matches[2]; - $extras .= "CREATE $uni INDEX {$name}_{$col} ON {$name}({$col});"; - } - else { - $cols[] = $bit; - } - } - $cols_redone = implode(", ", $cols); - return "CREATE TABLE $name ($cols_redone); $extras"; - } +function _now() +{ + return date("Y-m-d h:i:s"); +} +function _floor($a) +{ + return floor($a); +} +function _log($a, $b=null) +{ + if (is_null($b)) { + return log($a); + } else { + return log($a, $b); + } +} +function _isnull($a) +{ + return is_null($a); +} +function _md5($a) +{ + return md5($a); +} +function _concat($a, $b) +{ + return $a . $b; +} +function _lower($a) +{ + return strtolower($a); +} +function _rand() +{ + return rand(); +} +function _ln($n) +{ + return log($n); +} + +class SQLite extends DBEngine +{ + /** @var string */ + public $name = "sqlite"; + + public function init(PDO $db) + { + ini_set('sqlite.assoc_case', 0); + $db->exec("PRAGMA foreign_keys = ON;"); + $db->sqliteCreateFunction('UNIX_TIMESTAMP', '_unix_timestamp', 1); + $db->sqliteCreateFunction('now', '_now', 0); + $db->sqliteCreateFunction('floor', '_floor', 1); + $db->sqliteCreateFunction('log', '_log'); + $db->sqliteCreateFunction('isnull', '_isnull', 1); + $db->sqliteCreateFunction('md5', '_md5', 1); + $db->sqliteCreateFunction('concat', '_concat', 2); + $db->sqliteCreateFunction('lower', '_lower', 1); + $db->sqliteCreateFunction('rand', '_rand', 0); + $db->sqliteCreateFunction('ln', '_ln', 1); + } + + public function scoreql_to_sql(string $data): string + { + $data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY", $data); + $data = str_replace("SCORE_INET", "VARCHAR(45)", $data); + $data = str_replace("SCORE_BOOL_Y", "'Y'", $data); + $data = str_replace("SCORE_BOOL_N", "'N'", $data); + $data = str_replace("SCORE_BOOL", "CHAR(1)", $data); + $data = str_replace("SCORE_NOW", "\"1970-01-01\"", $data); + $data = str_replace("SCORE_STRNORM", "lower", $data); + $data = str_replace("SCORE_ILIKE", "LIKE", $data); + return $data; + } + + public function create_table_sql(string $name, string $data): string + { + $data = $this->scoreql_to_sql($data); + $cols = []; + $extras = ""; + foreach (explode(",", $data) as $bit) { + $matches = []; + if (preg_match("/(UNIQUE)? ?INDEX\s*\((.*)\)/", $bit, $matches)) { + $uni = $matches[1]; + $col = $matches[2]; + $extras .= "CREATE $uni INDEX {$name}_{$col} ON {$name}({$col});"; + } else { + $cols[] = $bit; + } + } + $cols_redone = implode(", ", $cols); + return "CREATE TABLE $name ($cols_redone); $extras"; + } } diff --git a/core/email.php b/core/email.php index eff609f2..c7982212 100644 --- a/core/email.php +++ b/core/email.php @@ -5,64 +5,66 @@ * * A generic email. */ -class Email { - /** @var string */ - public $to; - /** @var string */ - public $subject; - /** @var string */ - public $header; - /** @var null|string */ - public $style; - /** @var null|string */ - public $header_img; - /** @var null|string */ - public $sitename; - /** @var null|string */ - public $sitedomain; - /** @var null|string */ - public $siteemail; - /** @var string */ - public $date; - /** @var string */ - public $body; - /** @var null|string */ - public $footer; +class Email +{ + /** @var string */ + public $to; + /** @var string */ + public $subject; + /** @var string */ + public $header; + /** @var null|string */ + public $style; + /** @var null|string */ + public $header_img; + /** @var null|string */ + public $sitename; + /** @var null|string */ + public $sitedomain; + /** @var null|string */ + public $siteemail; + /** @var string */ + public $date; + /** @var string */ + public $body; + /** @var null|string */ + public $footer; - public function __construct(string $to, string $subject, string $header, string $body) { - global $config; - $this->to = $to; - - $sub_prefix = $config->get_string("mail_sub"); - - if(!isset($sub_prefix)){ - $this->subject = $subject; - } - else{ - $this->subject = $sub_prefix." ".$subject; - } - - $this->style = $config->get_string("mail_style"); - - $this->header = html_escape($header); - $this->header_img = $config->get_string("mail_img"); - $this->sitename = $config->get_string("site_title"); - $this->sitedomain = make_http(make_link("")); - $this->siteemail = $config->get_string("site_email"); - $this->date = date("F j, Y"); - $this->body = $body; - $this->footer = $config->get_string("mail_fot"); - } - - public function send(): bool { - $headers = "From: ".$this->sitename." <".$this->siteemail.">\r\n"; - $headers .= "Reply-To: ".$this->siteemail."\r\n"; - $headers .= "X-Mailer: PHP/" . phpversion(). "\r\n"; - $headers .= "errors-to: ".$this->siteemail."\r\n"; - $headers .= "Date: " . date(DATE_RFC2822); - $headers .= 'MIME-Version: 1.0' . "\r\n"; - $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; - $message = ' + public function __construct(string $to, string $subject, string $header, string $body) + { + global $config; + $this->to = $to; + + $sub_prefix = $config->get_string("mail_sub"); + + if (!isset($sub_prefix)) { + $this->subject = $subject; + } else { + $this->subject = $sub_prefix." ".$subject; + } + + $this->style = $config->get_string("mail_style"); + + $this->header = html_escape($header); + $this->header_img = $config->get_string("mail_img"); + $this->sitename = $config->get_string("site_title"); + $this->sitedomain = make_http(make_link("")); + $this->siteemail = $config->get_string("site_email"); + $this->date = date("F j, Y"); + $this->body = $body; + $this->footer = $config->get_string("mail_fot"); + } + + public function send(): bool + { + $headers = "From: ".$this->sitename." <".$this->siteemail.">\r\n"; + $headers .= "Reply-To: ".$this->siteemail."\r\n"; + $headers .= "X-Mailer: PHP/" . phpversion(). "\r\n"; + $headers .= "errors-to: ".$this->siteemail."\r\n"; + $headers .= "Date: " . date(DATE_RFC2822); + $headers .= 'MIME-Version: 1.0' . "\r\n"; + $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; + $message = ' @@ -118,15 +120,13 @@ Copyright (C) '.$this->sitename.'
'; - $sent = mail($this->to, $this->subject, $message, $headers); - if($sent){ - log_info("mail", "Sent message '$this->subject' to '$this->to'"); - } - else{ - log_info("mail", "Error sending message '$this->subject' to '$this->to'"); - } - - return $sent; - } + $sent = mail($this->to, $this->subject, $message, $headers); + if ($sent) { + log_info("mail", "Sent message '$this->subject' to '$this->to'"); + } else { + log_info("mail", "Error sending message '$this->subject' to '$this->to'"); + } + + return $sent; + } } - diff --git a/core/event.php b/core/event.php index 3010da6f..292da5bf 100644 --- a/core/event.php +++ b/core/event.php @@ -4,8 +4,11 @@ * * An event is anything that can be passed around via send_event($blah) */ -abstract class Event { - public function __construct() {} +abstract class Event +{ + public function __construct() + { + } } @@ -16,7 +19,9 @@ abstract class Event { * * This event is sent before $user is set to anything */ -class InitExtEvent extends Event {} +class InitExtEvent extends Event +{ +} /** @@ -27,188 +32,197 @@ class InitExtEvent extends Event {} * true and ignores the matched part, such that $event->count_args() = 1 and * $event->get_arg(0) = "42" */ -class PageRequestEvent extends Event { - /** - * @var array - */ - public $args; +class PageRequestEvent extends Event +{ + /** + * @var array + */ + public $args; - /** - * @var int - */ - public $arg_count; + /** + * @var int + */ + public $arg_count; - /** - * @var int - */ - public $part_count; + /** + * @var int + */ + public $part_count; - public function __construct(string $path) { - global $config; + public function __construct(string $path) + { + global $config; - // trim starting slashes - $path = ltrim($path, "/"); + // trim starting slashes + $path = ltrim($path, "/"); - // if path is not specified, use the default front page - if(empty($path)) { /* empty is faster than strlen */ - $path = $config->get_string('front_page'); - } + // if path is not specified, use the default front page + if (empty($path)) { /* empty is faster than strlen */ + $path = $config->get_string('front_page'); + } - // break the path into parts - $args = explode('/', $path); + // break the path into parts + $args = explode('/', $path); - // voodoo so that an arg can contain a slash; is - // this still needed? - if(strpos($path, "^") !== FALSE) { - $unescaped = array(); - foreach($args as $part) { - $unescaped[] = _decaret($part); - } - $args = $unescaped; - } + // voodoo so that an arg can contain a slash; is + // this still needed? + if (strpos($path, "^") !== false) { + $unescaped = []; + foreach ($args as $part) { + $unescaped[] = _decaret($part); + } + $args = $unescaped; + } - $this->args = $args; - $this->arg_count = count($args); - } + $this->args = $args; + $this->arg_count = count($args); + } - /** - * Test if the requested path matches a given pattern. - * - * If it matches, store the remaining path elements in $args - */ - public function page_matches(string $name): bool { - $parts = explode("/", $name); - $this->part_count = count($parts); + /** + * Test if the requested path matches a given pattern. + * + * If it matches, store the remaining path elements in $args + */ + public function page_matches(string $name): bool + { + $parts = explode("/", $name); + $this->part_count = count($parts); - if($this->part_count > $this->arg_count) { - return false; - } + if ($this->part_count > $this->arg_count) { + return false; + } - for($i=0; $i<$this->part_count; $i++) { - if($parts[$i] != $this->args[$i]) { - return false; - } - } + for ($i=0; $i<$this->part_count; $i++) { + if ($parts[$i] != $this->args[$i]) { + return false; + } + } - return true; - } + return true; + } - /** - * Get the n th argument of the page request (if it exists.) - */ - public function get_arg(int $n): ?string { - $offset = $this->part_count + $n; - if($offset >= 0 && $offset < $this->arg_count) { - return $this->args[$offset]; - } - else { - return null; - } - } + /** + * Get the n th argument of the page request (if it exists.) + */ + public function get_arg(int $n): ?string + { + $offset = $this->part_count + $n; + if ($offset >= 0 && $offset < $this->arg_count) { + return $this->args[$offset]; + } else { + return null; + } + } - /** - * Returns the number of arguments the page request has. - */ - public function count_args(): int { - return int_escape($this->arg_count - $this->part_count); - } + /** + * Returns the number of arguments the page request has. + */ + public function count_args(): int + { + return int_escape($this->arg_count - $this->part_count); + } - /* - * Many things use these functions - */ + /* + * Many things use these functions + */ - public function get_search_terms(): array { - $search_terms = array(); - if($this->count_args() === 2) { - $search_terms = Tag::explode($this->get_arg(0)); - } - return $search_terms; - } + public function get_search_terms(): array + { + $search_terms = []; + if ($this->count_args() === 2) { + $search_terms = Tag::explode($this->get_arg(0)); + } + return $search_terms; + } - public function get_page_number(): int { - $page_number = 1; - if($this->count_args() === 1) { - $page_number = int_escape($this->get_arg(0)); - } - else if($this->count_args() === 2) { - $page_number = int_escape($this->get_arg(1)); - } - if($page_number === 0) $page_number = 1; // invalid -> 0 - return $page_number; - } + public function get_page_number(): int + { + $page_number = 1; + if ($this->count_args() === 1) { + $page_number = int_escape($this->get_arg(0)); + } elseif ($this->count_args() === 2) { + $page_number = int_escape($this->get_arg(1)); + } + if ($page_number === 0) { + $page_number = 1; + } // invalid -> 0 + return $page_number; + } - public function get_page_size(): int { - global $config; - return $config->get_int('index_images'); - } + public function get_page_size(): int + { + global $config; + return $config->get_int('index_images'); + } } /** * Sent when index.php is called from the command line */ -class CommandEvent extends Event { - /** - * @var string - */ - public $cmd = "help"; +class CommandEvent extends Event +{ + /** + * @var string + */ + public $cmd = "help"; - /** - * @var array - */ - public $args = array(); + /** + * @var array + */ + public $args = []; - /** - * #param string[] $args - */ - public function __construct(array $args) { - global $user; + /** + * #param string[] $args + */ + public function __construct(array $args) + { + global $user; - $opts = array(); - $log_level = SCORE_LOG_WARNING; + $opts = []; + $log_level = SCORE_LOG_WARNING; $arg_count = count($args); - for($i=1; $i<$arg_count; $i++) { - switch($args[$i]) { - case '-u': - $user = User::by_name($args[++$i]); - if(is_null($user)) { - die("Unknown user"); - } - break; - case '-q': - $log_level += 10; - break; - case '-v': - $log_level -= 10; - break; - default: - $opts[] = $args[$i]; - break; - } - } + for ($i=1; $i<$arg_count; $i++) { + switch ($args[$i]) { + case '-u': + $user = User::by_name($args[++$i]); + if (is_null($user)) { + die("Unknown user"); + } + break; + case '-q': + $log_level += 10; + break; + case '-v': + $log_level -= 10; + break; + default: + $opts[] = $args[$i]; + break; + } + } - define("CLI_LOG_LEVEL", $log_level); + define("CLI_LOG_LEVEL", $log_level); - if(count($opts) > 0) { - $this->cmd = $opts[0]; - $this->args = array_slice($opts, 1); - } - else { - print "\n"; - print "Usage: php {$args[0]} [flags] [command]\n"; - print "\n"; - print "Flags:\n"; - print " -u [username]\n"; - print " Log in as the specified user\n"; - print " -q / -v\n"; - print " Be quieter / more verbose\n"; - print " Scale is debug - info - warning - error - critical\n"; - print " Default is to show warnings and above\n"; - print " \n"; - print "Currently known commands:\n"; - } - } + if (count($opts) > 0) { + $this->cmd = $opts[0]; + $this->args = array_slice($opts, 1); + } else { + print "\n"; + print "Usage: php {$args[0]} [flags] [command]\n"; + print "\n"; + print "Flags:\n"; + print " -u [username]\n"; + print " Log in as the specified user\n"; + print " -q / -v\n"; + print " Be quieter / more verbose\n"; + print " Scale is debug - info - warning - error - critical\n"; + print " Default is to show warnings and above\n"; + print " \n"; + print "Currently known commands:\n"; + } + } } @@ -216,82 +230,85 @@ class CommandEvent extends Event { * A signal that some text needs formatting, the event carries * both the text and the result */ -class TextFormattingEvent extends Event { - /** - * For reference - * - * @var string - */ - public $original; +class TextFormattingEvent extends Event +{ + /** + * For reference + * + * @var string + */ + public $original; - /** - * with formatting applied - * - * @var string - */ - public $formatted; + /** + * with formatting applied + * + * @var string + */ + public $formatted; - /** - * with formatting removed - * - * @var string - */ - public $stripped; + /** + * with formatting removed + * + * @var string + */ + public $stripped; - public function __construct(string $text) { - $h_text = html_escape(trim($text)); - $this->original = $h_text; - $this->formatted = $h_text; - $this->stripped = $h_text; - } + public function __construct(string $text) + { + $h_text = html_escape(trim($text)); + $this->original = $h_text; + $this->formatted = $h_text; + $this->stripped = $h_text; + } } /** * A signal that something needs logging */ -class LogEvent extends Event { - /** - * a category, normally the extension name - * - * @var string - */ - public $section; +class LogEvent extends Event +{ + /** + * a category, normally the extension name + * + * @var string + */ + public $section; - /** - * See python... - * - * @var int - */ - public $priority = 0; + /** + * See python... + * + * @var int + */ + public $priority = 0; - /** - * Free text to be logged - * - * @var string - */ - public $message; + /** + * Free text to be logged + * + * @var string + */ + public $message; - /** - * The time that the event was created - * - * @var int - */ - public $time; + /** + * The time that the event was created + * + * @var int + */ + public $time; - /** - * Extra data to be held separate - * - * @var array - */ - public $args; + /** + * Extra data to be held separate + * + * @var array + */ + public $args; - public function __construct(string $section, int $priority, string $message, array $args) { - $this->section = $section; - $this->priority = $priority; - $this->message = $message; - $this->args = $args; - $this->time = time(); - } + public function __construct(string $section, int $priority, string $message, array $args) + { + $this->section = $section; + $this->priority = $priority; + $this->message = $message; + $this->args = $args; + $this->time = time(); + } } - diff --git a/core/exceptions.php b/core/exceptions.php index d2400893..a201eba4 100644 --- a/core/exceptions.php +++ b/core/exceptions.php @@ -5,14 +5,18 @@ * * A base exception to be caught by the upper levels. */ -class SCoreException extends Exception {} +class SCoreException extends Exception +{ +} /** * Class PermissionDeniedException * * A fairly common, generic exception. */ -class PermissionDeniedException extends SCoreException {} +class PermissionDeniedException extends SCoreException +{ +} /** * Class ImageDoesNotExist @@ -21,9 +25,13 @@ class PermissionDeniedException extends SCoreException {} * * Example: Image::by_id(-1) returns null */ -class ImageDoesNotExist extends SCoreException {} +class ImageDoesNotExist extends SCoreException +{ +} /* * For validate_input() */ -class InvalidInput extends SCoreException {} +class InvalidInput extends SCoreException +{ +} diff --git a/core/extension.php b/core/extension.php index 5aaf3975..0b6134f2 100644 --- a/core/extension.php +++ b/core/extension.php @@ -81,50 +81,53 @@ * Then re-implemented by Shish after he broke the forum and couldn't * find the thread where the original was posted >_< */ -abstract class Extension { - /** @var array which DBs this ext supports (blank for 'all') */ - protected $db_support = []; +abstract class Extension +{ + /** @var array which DBs this ext supports (blank for 'all') */ + protected $db_support = []; - /** @var Themelet this theme's Themelet object */ - public $theme; + /** @var Themelet this theme's Themelet object */ + public $theme; - public function __construct() { - $this->theme = $this->get_theme_object(get_called_class()); - } + public function __construct() + { + $this->theme = $this->get_theme_object(get_called_class()); + } - public function is_live(): bool { - global $database; - return ( - empty($this->db_support) || - in_array($database->get_driver_name(), $this->db_support) - ); - } + public function is_live(): bool + { + global $database; + return ( + empty($this->db_support) || + in_array($database->get_driver_name(), $this->db_support) + ); + } - /** - * Find the theme object for a given extension. - */ - private function get_theme_object(string $base): ?Themelet { - $custom = 'Custom'.$base.'Theme'; - $normal = $base.'Theme'; + /** + * Find the theme object for a given extension. + */ + private function get_theme_object(string $base): ?Themelet + { + $custom = 'Custom'.$base.'Theme'; + $normal = $base.'Theme'; - if(class_exists($custom)) { - return new $custom(); - } - elseif(class_exists($normal)) { - return new $normal(); - } - else { - return null; - } - } + if (class_exists($custom)) { + return new $custom(); + } elseif (class_exists($normal)) { + return new $normal(); + } else { + return null; + } + } - /** - * Override this to change the priority of the extension, - * lower numbered ones will receive events first. - */ - public function get_priority(): int { - return 50; - } + /** + * Override this to change the priority of the extension, + * lower numbered ones will receive events first. + */ + public function get_priority(): int + { + return 50; + } } /** @@ -132,14 +135,16 @@ abstract class Extension { * * Several extensions have this in common, make a common API. */ -abstract class FormatterExtension extends Extension { - public function onTextFormatting(TextFormattingEvent $event) { - $event->formatted = $this->format($event->formatted); - $event->stripped = $this->strip($event->stripped); - } +abstract class FormatterExtension extends Extension +{ + public function onTextFormatting(TextFormattingEvent $event) + { + $event->formatted = $this->format($event->formatted); + $event->stripped = $this->strip($event->stripped); + } - abstract public function format(string $text): string; - abstract public function strip(string $text): string; + abstract public function format(string $text): string; + abstract public function strip(string $text): string; } /** @@ -148,100 +153,100 @@ abstract class FormatterExtension extends Extension { * This too is a common class of extension with many methods in common, * so we have a base class to extend from. */ -abstract class DataHandlerExtension extends Extension { - public function onDataUpload(DataUploadEvent $event) { - $supported_ext = $this->supported_ext($event->type); - $check_contents = $this->check_contents($event->tmpname); - if($supported_ext && $check_contents) { - move_upload_to_archive($event); - send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); +abstract class DataHandlerExtension extends Extension +{ + public function onDataUpload(DataUploadEvent $event) + { + $supported_ext = $this->supported_ext($event->type); + $check_contents = $this->check_contents($event->tmpname); + if ($supported_ext && $check_contents) { + move_upload_to_archive($event); + send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); - /* Check if we are replacing an image */ - if(array_key_exists('replace', $event->metadata) && isset($event->metadata['replace'])) { - /* hax: This seems like such a dirty way to do this.. */ + /* Check if we are replacing an image */ + if (array_key_exists('replace', $event->metadata) && isset($event->metadata['replace'])) { + /* hax: This seems like such a dirty way to do this.. */ - /* Validate things */ - $image_id = int_escape($event->metadata['replace']); + /* Validate things */ + $image_id = int_escape($event->metadata['replace']); - /* Check to make sure the image exists. */ - $existing = Image::by_id($image_id); + /* Check to make sure the image exists. */ + $existing = Image::by_id($image_id); - if(is_null($existing)) { - throw new UploadException("Image to replace does not exist!"); - } - if ($existing->hash === $event->metadata['hash']) { - throw new UploadException("The uploaded image is the same as the one to replace."); - } + if (is_null($existing)) { + throw new UploadException("Image to replace does not exist!"); + } + if ($existing->hash === $event->metadata['hash']) { + throw new UploadException("The uploaded image is the same as the one to replace."); + } - // even more hax.. - $event->metadata['tags'] = $existing->get_tag_list(); - $image = $this->create_image_from_data(warehouse_path("images", $event->metadata['hash']), $event->metadata); + // even more hax.. + $event->metadata['tags'] = $existing->get_tag_list(); + $image = $this->create_image_from_data(warehouse_path("images", $event->metadata['hash']), $event->metadata); - if(is_null($image)) { - throw new UploadException("Data handler failed to create image object from data"); - } + if (is_null($image)) { + throw new UploadException("Data handler failed to create image object from data"); + } - $ire = new ImageReplaceEvent($image_id, $image); - send_event($ire); - $event->image_id = $image_id; - } - else { - $image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata); - if(is_null($image)) { - throw new UploadException("Data handler failed to create image object from data"); - } - $iae = new ImageAdditionEvent($image); - send_event($iae); - $event->image_id = $iae->image->id; + $ire = new ImageReplaceEvent($image_id, $image); + send_event($ire); + $event->image_id = $image_id; + } else { + $image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata); + if (is_null($image)) { + throw new UploadException("Data handler failed to create image object from data"); + } + $iae = new ImageAdditionEvent($image); + send_event($iae); + $event->image_id = $iae->image->id; - // Rating Stuff. - if(!empty($event->metadata['rating'])){ - $rating = $event->metadata['rating']; - send_event(new RatingSetEvent($image, $rating)); - } + // Rating Stuff. + if (!empty($event->metadata['rating'])) { + $rating = $event->metadata['rating']; + send_event(new RatingSetEvent($image, $rating)); + } - // Locked Stuff. - if(!empty($event->metadata['locked'])){ - $locked = $event->metadata['locked']; - send_event(new LockSetEvent($image, !empty($locked))); - } - } - } - elseif($supported_ext && !$check_contents){ - throw new UploadException("Invalid or corrupted file"); - } - } + // Locked Stuff. + if (!empty($event->metadata['locked'])) { + $locked = $event->metadata['locked']; + send_event(new LockSetEvent($image, !empty($locked))); + } + } + } elseif ($supported_ext && !$check_contents) { + throw new UploadException("Invalid or corrupted file"); + } + } - public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { - if($this->supported_ext($event->type)) { - if (method_exists($this, 'create_thumb_force') && $event->force == true) { - $this->create_thumb_force($event->hash); - } - else { - $this->create_thumb($event->hash); - } - } - } + public function onThumbnailGeneration(ThumbnailGenerationEvent $event) + { + if ($this->supported_ext($event->type)) { + if (method_exists($this, 'create_thumb_force') && $event->force == true) { + $this->create_thumb_force($event->hash); + } else { + $this->create_thumb($event->hash); + } + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $page; - if($this->supported_ext($event->image->ext)) { - $this->theme->display_image($page, $event->image); - } - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $page; + if ($this->supported_ext($event->image->ext)) { + $this->theme->display_image($page, $event->image); + } + } - /* - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = $this->setup(); - if($sb) $event->panel->add_block($sb); - } + /* + public function onSetupBuilding(SetupBuildingEvent $event) { + $sb = $this->setup(); + if($sb) $event->panel->add_block($sb); + } - protected function setup() {} - */ + protected function setup() {} + */ - abstract protected function supported_ext(string $ext): bool; - abstract protected function check_contents(string $tmpname): bool; - abstract protected function create_image_from_data(string $filename, array $metadata); - abstract protected function create_thumb(string $hash): bool; + abstract protected function supported_ext(string $ext): bool; + abstract protected function check_contents(string $tmpname): bool; + abstract protected function create_image_from_data(string $filename, array $metadata); + abstract protected function create_thumb(string $hash): bool; } - diff --git a/core/imageboard/event.php b/core/imageboard/event.php index ff7def1c..9f09655a 100644 --- a/core/imageboard/event.php +++ b/core/imageboard/event.php @@ -3,99 +3,111 @@ /** * An image is being added to the database. */ -class ImageAdditionEvent extends Event { - /** @var User */ - public $user; +class ImageAdditionEvent extends Event +{ + /** @var User */ + public $user; - /** @var Image */ - public $image; + /** @var Image */ + public $image; - /** - * Inserts a new image into the database with its associated - * information. Also calls TagSetEvent to set the tags for - * this new image. - */ - public function __construct(Image $image) { - $this->image = $image; - } + /** + * Inserts a new image into the database with its associated + * information. Also calls TagSetEvent to set the tags for + * this new image. + */ + public function __construct(Image $image) + { + $this->image = $image; + } } -class ImageAdditionException extends SCoreException { - public $error; +class ImageAdditionException extends SCoreException +{ + public $error; - public function __construct(string $error) { - $this->error = $error; - } + public function __construct(string $error) + { + $this->error = $error; + } } /** * An image is being deleted. */ -class ImageDeletionEvent extends Event { - /** @var \Image */ - public $image; +class ImageDeletionEvent extends Event +{ + /** @var \Image */ + public $image; - /** - * Deletes an image. - * - * Used by things like tags and comments handlers to - * clean out related rows in their tables. - */ - public function __construct(Image $image) { - $this->image = $image; - } + /** + * Deletes an image. + * + * Used by things like tags and comments handlers to + * clean out related rows in their tables. + */ + public function __construct(Image $image) + { + $this->image = $image; + } } /** * An image is being replaced. */ -class ImageReplaceEvent extends Event { - /** @var int */ - public $id; - /** @var \Image */ - public $image; +class ImageReplaceEvent extends Event +{ + /** @var int */ + public $id; + /** @var \Image */ + public $image; - /** - * Replaces an image. - * - * Updates an existing ID in the database to use a new image - * file, leaving the tags and such unchanged. Also removes - * the old image file and thumbnail from the disk. - */ - public function __construct(int $id, Image $image) { - $this->id = $id; - $this->image = $image; - } + /** + * Replaces an image. + * + * Updates an existing ID in the database to use a new image + * file, leaving the tags and such unchanged. Also removes + * the old image file and thumbnail from the disk. + */ + public function __construct(int $id, Image $image) + { + $this->id = $id; + $this->image = $image; + } } -class ImageReplaceException extends SCoreException { - /** @var string */ - public $error; +class ImageReplaceException extends SCoreException +{ + /** @var string */ + public $error; - public function __construct(string $error) { - $this->error = $error; - } + public function __construct(string $error) + { + $this->error = $error; + } } /** * Request a thumbnail be made for an image object. */ -class ThumbnailGenerationEvent extends Event { - /** @var string */ - public $hash; - /** @var string */ - public $type; - /** @var bool */ - public $force; +class ThumbnailGenerationEvent extends Event +{ + /** @var string */ + public $hash; + /** @var string */ + public $type; + /** @var bool */ + public $force; - /** - * Request a thumbnail be made for an image object - */ - public function __construct(string $hash, string $type, bool $force=false) { - $this->hash = $hash; - $this->type = $type; - $this->force = $force; - } + /** + * Request a thumbnail be made for an image object + */ + public function __construct(string $hash, string $type, bool $force=false) + { + $this->hash = $hash; + $this->type = $type; + $this->force = $force; + } } @@ -105,21 +117,24 @@ class ThumbnailGenerationEvent extends Event { * $original -- the formatting string, for reference * $image -- the image who's link is being parsed */ -class ParseLinkTemplateEvent extends Event { - /** @var string */ - public $link; - /** @var string */ - public $original; - /** @var \Image */ - public $image; +class ParseLinkTemplateEvent extends Event +{ + /** @var string */ + public $link; + /** @var string */ + public $original; + /** @var \Image */ + public $image; - public function __construct(string $link, Image $image) { - $this->link = $link; - $this->original = $link; - $this->image = $image; - } + public function __construct(string $link, Image $image) + { + $this->link = $link; + $this->original = $link; + $this->image = $image; + } - public function replace(string $needle, string $replace): void { - $this->link = str_replace($needle, $replace, $this->link); - } + public function replace(string $needle, string $replace): void + { + $this->link = str_replace($needle, $replace, $this->link); + } } diff --git a/core/imageboard/image.php b/core/imageboard/image.php index 7fa9d2e5..8c9e32c0 100644 --- a/core/imageboard/image.php +++ b/core/imageboard/image.php @@ -8,497 +8,545 @@ * image per se, but could be a video, sound file, or any * other supported upload type. */ -class Image { - private static $tag_n = 0; // temp hack - public static $order_sql = null; // this feels ugly +class Image +{ + private static $tag_n = 0; // temp hack + public static $order_sql = null; // this feels ugly - /** @var null|int */ - public $id = null; + /** @var null|int */ + public $id = null; - /** @var int */ - public $height; + /** @var int */ + public $height; - /** @var int */ - public $width; + /** @var int */ + public $width; - /** @var string */ - public $hash; + /** @var string */ + public $hash; - public $filesize; + public $filesize; - /** @var string */ - public $filename; + /** @var string */ + public $filename; - /** @var string */ - public $ext; + /** @var string */ + public $ext; - /** @var string[]|null */ - public $tag_array; + /** @var string[]|null */ + public $tag_array; - /** @var int */ - public $owner_id; - - /** @var string */ - public $owner_ip; - - /** @var string */ - public $posted; - - /** @var string */ - public $source; + /** @var int */ + public $owner_id; - /** @var boolean */ - public $locked = false; + /** @var string */ + public $owner_ip; + + /** @var string */ + public $posted; + + /** @var string */ + public $source; + + /** @var boolean */ + public $locked = false; - /** - * One will very rarely construct an image directly, more common - * would be to use Image::by_id, Image::by_hash, etc. - */ - public function __construct(?array $row=null) { - if(!is_null($row)) { - foreach($row as $name => $value) { - // some databases use table.name rather than name - $name = str_replace("images.", "", $name); - $this->$name = $value; // hax, this is likely the cause of much scrutinizer-ci complaints. - } - $this->locked = bool_escape($this->locked); + /** + * One will very rarely construct an image directly, more common + * would be to use Image::by_id, Image::by_hash, etc. + */ + public function __construct(?array $row=null) + { + if (!is_null($row)) { + foreach ($row as $name => $value) { + // some databases use table.name rather than name + $name = str_replace("images.", "", $name); + $this->$name = $value; // hax, this is likely the cause of much scrutinizer-ci complaints. + } + $this->locked = bool_escape($this->locked); - assert(is_numeric($this->id)); - assert(is_numeric($this->height)); - assert(is_numeric($this->width)); - } - } + assert(is_numeric($this->id)); + assert(is_numeric($this->height)); + assert(is_numeric($this->width)); + } + } - public static function by_id(int $id) { - global $database; - $row = $database->get_row("SELECT * FROM images WHERE images.id=:id", array("id"=>$id)); - return ($row ? new Image($row) : null); - } + public static function by_id(int $id) + { + global $database; + $row = $database->get_row("SELECT * FROM images WHERE images.id=:id", ["id"=>$id]); + return ($row ? new Image($row) : null); + } - public static function by_hash(string $hash) { - global $database; - $row = $database->get_row("SELECT images.* FROM images WHERE hash=:hash", array("hash"=>$hash)); - return ($row ? new Image($row) : null); - } + public static function by_hash(string $hash) + { + global $database; + $row = $database->get_row("SELECT images.* FROM images WHERE hash=:hash", ["hash"=>$hash]); + return ($row ? new Image($row) : null); + } - public static function by_random(array $tags=array()) { - $max = Image::count_images($tags); - if ($max < 1) return null; // From Issue #22 - opened by HungryFeline on May 30, 2011. - $rand = mt_rand(0, $max-1); - $set = Image::find_images($rand, 1, $tags); - if(count($set) > 0) return $set[0]; - else return null; - } + public static function by_random(array $tags=[]) + { + $max = Image::count_images($tags); + if ($max < 1) { + return null; + } // From Issue #22 - opened by HungryFeline on May 30, 2011. + $rand = mt_rand(0, $max-1); + $set = Image::find_images($rand, 1, $tags); + if (count($set) > 0) { + return $set[0]; + } else { + return null; + } + } - /** - * Search for an array of images - * - * #param string[] $tags - * #return Image[] - */ - public static function find_images(int $start, int $limit, array $tags=array()): array { - global $database, $user, $config; + /** + * Search for an array of images + * + * #param string[] $tags + * #return Image[] + */ + public static function find_images(int $start, int $limit, array $tags=[]): array + { + global $database, $user, $config; - $images = array(); + $images = []; - if($start < 0) $start = 0; - if($limit < 1) $limit = 1; + if ($start < 0) { + $start = 0; + } + if ($limit < 1) { + $limit = 1; + } - if(SPEED_HAX) { - if(!$user->can("big_search") and count($tags) > 3) { - throw new SCoreException("Anonymous users may only search for up to 3 tags at a time"); - } - } + if (SPEED_HAX) { + if (!$user->can("big_search") and count($tags) > 3) { + throw new SCoreException("Anonymous users may only search for up to 3 tags at a time"); + } + } - $result = null; - if(SEARCH_ACCEL) { - $result = Image::get_accelerated_result($tags, $start, $limit); - } + $result = null; + if (SEARCH_ACCEL) { + $result = Image::get_accelerated_result($tags, $start, $limit); + } - if(!$result) { - $querylet = Image::build_search_querylet($tags); - $querylet->append(new Querylet(" ORDER BY ".(Image::$order_sql ?: "images.".$config->get_string("index_order")))); - $querylet->append(new Querylet(" LIMIT :limit OFFSET :offset", array("limit"=>$limit, "offset"=>$start))); - #var_dump($querylet->sql); var_dump($querylet->variables); - $result = $database->execute($querylet->sql, $querylet->variables); - } + if (!$result) { + $querylet = Image::build_search_querylet($tags); + $querylet->append(new Querylet(" ORDER BY ".(Image::$order_sql ?: "images.".$config->get_string("index_order")))); + $querylet->append(new Querylet(" LIMIT :limit OFFSET :offset", ["limit"=>$limit, "offset"=>$start])); + #var_dump($querylet->sql); var_dump($querylet->variables); + $result = $database->execute($querylet->sql, $querylet->variables); + } - while($row = $result->fetch()) { - $images[] = new Image($row); - } - Image::$order_sql = null; - return $images; - } + while ($row = $result->fetch()) { + $images[] = new Image($row); + } + Image::$order_sql = null; + return $images; + } - /* - * Accelerator stuff - */ - public static function get_acceleratable(array $tags) { - $ret = array( - "yays" => array(), - "nays" => array(), - ); - $yays = 0; - $nays = 0; - foreach($tags as $tag) { - if(!preg_match("/^-?[a-zA-Z0-9_-]+$/", $tag)) { - return false; - } - if($tag[0] == "-") {$nays++; $ret["nays"][] = substr($tag, 1);} - else {$yays++; $ret["yays"][] = $tag;} - } - if($yays > 1 || $nays > 0) { - return $ret; - } - return false; - } + /* + * Accelerator stuff + */ + public static function get_acceleratable(array $tags) + { + $ret = [ + "yays" => [], + "nays" => [], + ]; + $yays = 0; + $nays = 0; + foreach ($tags as $tag) { + if (!preg_match("/^-?[a-zA-Z0-9_-]+$/", $tag)) { + return false; + } + if ($tag[0] == "-") { + $nays++; + $ret["nays"][] = substr($tag, 1); + } else { + $yays++; + $ret["yays"][] = $tag; + } + } + if ($yays > 1 || $nays > 0) { + return $ret; + } + return false; + } - public static function get_accelerated_result(array $tags, int $offset, int $limit) { - global $database; + public static function get_accelerated_result(array $tags, int $offset, int $limit) + { + global $database; - $req = Image::get_acceleratable($tags); - if(!$req) {return null;} - $req["offset"] = $offset; - $req["limit"] = $limit; + $req = Image::get_acceleratable($tags); + if (!$req) { + return null; + } + $req["offset"] = $offset; + $req["limit"] = $limit; - $response = Image::query_accelerator($req); - $list = implode(",", $response); - if($list) { - $result = $database->execute("SELECT * FROM images WHERE id IN ($list) ORDER BY images.id DESC"); - } - else { - $result = $database->execute("SELECT * FROM images WHERE 1=0 ORDER BY images.id DESC"); - } - return $result; - } + $response = Image::query_accelerator($req); + $list = implode(",", $response); + if ($list) { + $result = $database->execute("SELECT * FROM images WHERE id IN ($list) ORDER BY images.id DESC"); + } else { + $result = $database->execute("SELECT * FROM images WHERE 1=0 ORDER BY images.id DESC"); + } + return $result; + } - public static function get_accelerated_count(array $tags) { - $req = Image::get_acceleratable($tags); - if(!$req) {return null;} - $req["count"] = true; + public static function get_accelerated_count(array $tags) + { + $req = Image::get_acceleratable($tags); + if (!$req) { + return null; + } + $req["count"] = true; - return Image::query_accelerator($req); - } + return Image::query_accelerator($req); + } - public static function query_accelerator($req) { - $fp = @fsockopen("127.0.0.1", 21212); - if (!$fp) { - return null; - } - fwrite($fp, json_encode($req)); - $data = ""; - while (($buffer = fgets($fp, 4096)) !== false) { - $data .= $buffer; - } - if (!feof($fp)) { - die("Error: unexpected fgets() fail in query_accelerator($req)\n"); - } - fclose($fp); - return json_decode($data); - } + public static function query_accelerator($req) + { + $fp = @fsockopen("127.0.0.1", 21212); + if (!$fp) { + return null; + } + fwrite($fp, json_encode($req)); + $data = ""; + while (($buffer = fgets($fp, 4096)) !== false) { + $data .= $buffer; + } + if (!feof($fp)) { + die("Error: unexpected fgets() fail in query_accelerator($req)\n"); + } + fclose($fp); + return json_decode($data); + } - /* - * Image-related utility functions - */ + /* + * Image-related utility functions + */ - /** - * Count the number of image results for a given search - * - * #param string[] $tags - */ - public static function count_images(array $tags=array()): int { - global $database; - $tag_count = count($tags); + /** + * Count the number of image results for a given search + * + * #param string[] $tags + */ + public static function count_images(array $tags=[]): int + { + global $database; + $tag_count = count($tags); - if($tag_count === 0) { - $total = $database->cache->get("image-count"); - if(!$total) { - $total = $database->get_one("SELECT COUNT(*) FROM images"); - $database->cache->set("image-count", $total, 600); - } - } - else if($tag_count === 1 && !preg_match("/[:=><\*\?]/", $tags[0])) { - $total = $database->get_one( - $database->scoreql_to_sql("SELECT count FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)"), - array("tag"=>$tags[0])); - } - else { - $total = Image::get_accelerated_count($tags); - if(is_null($total)) { - $querylet = Image::build_search_querylet($tags); - $total = $database->get_one("SELECT COUNT(*) AS cnt FROM ($querylet->sql) AS tbl", $querylet->variables); - } - } - if(is_null($total)) return 0; - return $total; - } + if ($tag_count === 0) { + $total = $database->cache->get("image-count"); + if (!$total) { + $total = $database->get_one("SELECT COUNT(*) FROM images"); + $database->cache->set("image-count", $total, 600); + } + } elseif ($tag_count === 1 && !preg_match("/[:=><\*\?]/", $tags[0])) { + $total = $database->get_one( + $database->scoreql_to_sql("SELECT count FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)"), + ["tag"=>$tags[0]] + ); + } else { + $total = Image::get_accelerated_count($tags); + if (is_null($total)) { + $querylet = Image::build_search_querylet($tags); + $total = $database->get_one("SELECT COUNT(*) AS cnt FROM ($querylet->sql) AS tbl", $querylet->variables); + } + } + if (is_null($total)) { + return 0; + } + return $total; + } - /** - * Count the number of pages for a given search - * - * #param string[] $tags - */ - public static function count_pages(array $tags=array()): float { - global $config; - return ceil(Image::count_images($tags) / $config->get_int('index_images')); - } + /** + * Count the number of pages for a given search + * + * #param string[] $tags + */ + public static function count_pages(array $tags=[]): float + { + global $config; + return ceil(Image::count_images($tags) / $config->get_int('index_images')); + } - /* - * Accessors & mutators - */ + /* + * Accessors & mutators + */ - /** - * Find the next image in the sequence. - * - * Rather than simply $this_id + 1, one must take into account - * deleted images and search queries - * - * #param string[] $tags - */ - public function get_next(array $tags=array(), bool $next=true): ?Image { - global $database; + /** + * Find the next image in the sequence. + * + * Rather than simply $this_id + 1, one must take into account + * deleted images and search queries + * + * #param string[] $tags + */ + public function get_next(array $tags=[], bool $next=true): ?Image + { + global $database; - if($next) { - $gtlt = "<"; - $dir = "DESC"; - } - else { - $gtlt = ">"; - $dir = "ASC"; - } + if ($next) { + $gtlt = "<"; + $dir = "DESC"; + } else { + $gtlt = ">"; + $dir = "ASC"; + } - if(count($tags) === 0) { - $row = $database->get_row(' + if (count($tags) === 0) { + $row = $database->get_row(' SELECT images.* FROM images WHERE images.id '.$gtlt.' '.$this->id.' ORDER BY images.id '.$dir.' LIMIT 1 '); - } - else { - $tags[] = 'id'. $gtlt . $this->id; - $querylet = Image::build_search_querylet($tags); - $querylet->append_sql(' ORDER BY images.id '.$dir.' LIMIT 1'); - $row = $database->get_row($querylet->sql, $querylet->variables); - } + } else { + $tags[] = 'id'. $gtlt . $this->id; + $querylet = Image::build_search_querylet($tags); + $querylet->append_sql(' ORDER BY images.id '.$dir.' LIMIT 1'); + $row = $database->get_row($querylet->sql, $querylet->variables); + } - return ($row ? new Image($row) : null); - } + return ($row ? new Image($row) : null); + } - /** - * The reverse of get_next - * - * #param string[] $tags - */ - public function get_prev(array $tags=array()): ?Image { - return $this->get_next($tags, false); - } + /** + * The reverse of get_next + * + * #param string[] $tags + */ + public function get_prev(array $tags=[]): ?Image + { + return $this->get_next($tags, false); + } - /** - * Find the User who owns this Image - */ - public function get_owner(): User { - return User::by_id($this->owner_id); - } + /** + * Find the User who owns this Image + */ + public function get_owner(): User + { + return User::by_id($this->owner_id); + } - /** - * Set the image's owner. - */ - public function set_owner(User $owner) { - global $database; - if($owner->id != $this->owner_id) { - $database->execute(" + /** + * Set the image's owner. + */ + public function set_owner(User $owner) + { + global $database; + if ($owner->id != $this->owner_id) { + $database->execute(" UPDATE images SET owner_id=:owner_id WHERE id=:id - ", array("owner_id"=>$owner->id, "id"=>$this->id)); - log_info("core_image", "Owner for Image #{$this->id} set to {$owner->name}", null, array("image_id" => $this->id)); - } - } + ", ["owner_id"=>$owner->id, "id"=>$this->id]); + log_info("core_image", "Owner for Image #{$this->id} set to {$owner->name}", null, ["image_id" => $this->id]); + } + } - /** - * Get this image's tags as an array. - * - * #return string[] - */ - public function get_tag_array(): array { - global $database; - if(!isset($this->tag_array)) { - $this->tag_array = $database->get_col(" + /** + * Get this image's tags as an array. + * + * #return string[] + */ + public function get_tag_array(): array + { + global $database; + if (!isset($this->tag_array)) { + $this->tag_array = $database->get_col(" SELECT tag FROM image_tags JOIN tags ON image_tags.tag_id = tags.id WHERE image_id=:id ORDER BY tag - ", array("id"=>$this->id)); - } - return $this->tag_array; - } + ", ["id"=>$this->id]); + } + return $this->tag_array; + } - /** - * Get this image's tags as a string. - */ - public function get_tag_list(): string { - return Tag::implode($this->get_tag_array()); - } + /** + * Get this image's tags as a string. + */ + public function get_tag_list(): string + { + return Tag::implode($this->get_tag_array()); + } - /** - * Get the URL for the full size image - */ - public function get_image_link(): string { - return $this->get_link('image_ilink', '_images/$hash/$id%20-%20$tags.$ext', 'image/$id.$ext'); - } + /** + * Get the URL for the full size image + */ + public function get_image_link(): string + { + return $this->get_link('image_ilink', '_images/$hash/$id%20-%20$tags.$ext', 'image/$id.$ext'); + } - /** - * Get the URL for the thumbnail - */ - public function get_thumb_link(): string { - return $this->get_link('image_tlink', '_thumbs/$hash/thumb.jpg', 'thumb/$id.jpg'); - } + /** + * Get the URL for the thumbnail + */ + public function get_thumb_link(): string + { + return $this->get_link('image_tlink', '_thumbs/$hash/thumb.jpg', 'thumb/$id.jpg'); + } - /** - * Check configured template for a link, then try nice URL, then plain URL - */ - private function get_link(string $template, string $nice, string $plain): string { - global $config; + /** + * Check configured template for a link, then try nice URL, then plain URL + */ + private function get_link(string $template, string $nice, string $plain): string + { + global $config; - $image_link = $config->get_string($template); + $image_link = $config->get_string($template); - if(!empty($image_link)) { - if(!(strpos($image_link, "://") > 0) && !startsWith($image_link, "/")) { - $image_link = make_link($image_link); - } - return $this->parse_link_template($image_link); - } - else if($config->get_bool('nice_urls', false)) { - return $this->parse_link_template(make_link($nice)); - } - else { - return $this->parse_link_template(make_link($plain)); - } - } + if (!empty($image_link)) { + if (!(strpos($image_link, "://") > 0) && !startsWith($image_link, "/")) { + $image_link = make_link($image_link); + } + return $this->parse_link_template($image_link); + } elseif ($config->get_bool('nice_urls', false)) { + return $this->parse_link_template(make_link($nice)); + } else { + return $this->parse_link_template(make_link($plain)); + } + } - /** - * Get the tooltip for this image, formatted according to the - * configured template. - */ - public function get_tooltip(): string { - global $config; - $tt = $this->parse_link_template($config->get_string('image_tip'), "no_escape"); + /** + * Get the tooltip for this image, formatted according to the + * configured template. + */ + public function get_tooltip(): string + { + global $config; + $tt = $this->parse_link_template($config->get_string('image_tip'), "no_escape"); - // Removes the size tag if the file is an mp3 - if($this->ext === 'mp3'){ - $iitip = $tt; - $mp3tip = array("0x0"); - $h_tip = str_replace($mp3tip, " ", $iitip); + // Removes the size tag if the file is an mp3 + if ($this->ext === 'mp3') { + $iitip = $tt; + $mp3tip = ["0x0"]; + $h_tip = str_replace($mp3tip, " ", $iitip); - // Makes it work with a variation of the default tooltips (I.E $tags // $filesize // $size) - $justincase = array(" //", "// ", " //", "// ", " "); - if(strstr($h_tip, " ")) { - $h_tip = html_escape(str_replace($justincase, "", $h_tip)); - }else{ - $h_tip = html_escape($h_tip); - } - return $h_tip; - } - else { - return $tt; - } - } + // Makes it work with a variation of the default tooltips (I.E $tags // $filesize // $size) + $justincase = [" //", "// ", " //", "// ", " "]; + if (strstr($h_tip, " ")) { + $h_tip = html_escape(str_replace($justincase, "", $h_tip)); + } else { + $h_tip = html_escape($h_tip); + } + return $h_tip; + } else { + return $tt; + } + } - /** - * Figure out where the full size image is on disk. - */ - public function get_image_filename(): string { - return warehouse_path("images", $this->hash); - } + /** + * Figure out where the full size image is on disk. + */ + public function get_image_filename(): string + { + return warehouse_path("images", $this->hash); + } - /** - * Figure out where the thumbnail is on disk. - */ - public function get_thumb_filename(): string { - return warehouse_path("thumbs", $this->hash); - } + /** + * Figure out where the thumbnail is on disk. + */ + public function get_thumb_filename(): string + { + return warehouse_path("thumbs", $this->hash); + } - /** - * Get the original filename. - */ - public function get_filename(): string { - return $this->filename; - } + /** + * Get the original filename. + */ + public function get_filename(): string + { + return $this->filename; + } - /** - * Get the image's mime type. - */ - public function get_mime_type(): string { - return getMimeType($this->get_image_filename(), $this->get_ext()); - } + /** + * Get the image's mime type. + */ + public function get_mime_type(): string + { + return getMimeType($this->get_image_filename(), $this->get_ext()); + } - /** - * Get the image's filename extension - */ - public function get_ext(): string { - return $this->ext; - } + /** + * Get the image's filename extension + */ + public function get_ext(): string + { + return $this->ext; + } - /** - * Get the image's source URL - */ - public function get_source(): string { - return $this->source; - } + /** + * Get the image's source URL + */ + public function get_source(): string + { + return $this->source; + } - /** - * Set the image's source URL - */ - public function set_source(string $new_source): void { - global $database; - $old_source = $this->source; - if(empty($new_source)) $new_source = null; - if($new_source != $old_source) { - $database->execute("UPDATE images SET source=:source WHERE id=:id", array("source"=>$new_source, "id"=>$this->id)); - log_info("core_image", "Source for Image #{$this->id} set to: $new_source (was $old_source)", null, array("image_id" => $this->id)); - } - } + /** + * Set the image's source URL + */ + public function set_source(string $new_source): void + { + global $database; + $old_source = $this->source; + if (empty($new_source)) { + $new_source = null; + } + if ($new_source != $old_source) { + $database->execute("UPDATE images SET source=:source WHERE id=:id", ["source"=>$new_source, "id"=>$this->id]); + log_info("core_image", "Source for Image #{$this->id} set to: $new_source (was $old_source)", null, ["image_id" => $this->id]); + } + } - /** - * Check if the image is locked. - */ - public function is_locked(): bool { - return $this->locked; - } + /** + * Check if the image is locked. + */ + public function is_locked(): bool + { + return $this->locked; + } - public function set_locked(bool $tf) { - global $database; - $ln = $tf ? "Y" : "N"; - $sln = $database->scoreql_to_sql('SCORE_BOOL_'.$ln); - $sln = str_replace("'", "", $sln); - $sln = str_replace('"', "", $sln); - if(bool_escape($sln) !== $this->locked) { - $database->execute("UPDATE images SET locked=:yn WHERE id=:id", array("yn"=>$sln, "id"=>$this->id)); - log_info("core_image", "Setting Image #{$this->id} lock to: $ln", null, array("image_id" => $this->id)); - } - } + public function set_locked(bool $tf) + { + global $database; + $ln = $tf ? "Y" : "N"; + $sln = $database->scoreql_to_sql('SCORE_BOOL_'.$ln); + $sln = str_replace("'", "", $sln); + $sln = str_replace('"', "", $sln); + if (bool_escape($sln) !== $this->locked) { + $database->execute("UPDATE images SET locked=:yn WHERE id=:id", ["yn"=>$sln, "id"=>$this->id]); + log_info("core_image", "Setting Image #{$this->id} lock to: $ln", null, ["image_id" => $this->id]); + } + } - /** - * Delete all tags from this image. - * - * Normally in preparation to set them to a new set. - */ - public function delete_tags_from_image(): void { - global $database; - if($database->get_driver_name() == "mysql") { - //mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this - $database->execute(" + /** + * Delete all tags from this image. + * + * Normally in preparation to set them to a new set. + */ + public function delete_tags_from_image(): void + { + global $database; + if ($database->get_driver_name() == "mysql") { + //mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this + $database->execute( + " UPDATE tags t INNER JOIN image_tags it ON t.id = it.tag_id SET count = count - 1 WHERE it.image_id = :id", - array("id"=>$this->id) - ); - } else { - $database->execute(" + ["id"=>$this->id] + ); + } else { + $database->execute(" UPDATE tags SET count = count - 1 WHERE id IN ( @@ -506,270 +554,278 @@ class Image { FROM image_tags WHERE image_id = :id ) - ", array("id"=>$this->id)); - } - $database->execute(" + ", ["id"=>$this->id]); + } + $database->execute(" DELETE FROM image_tags WHERE image_id=:id - ", array("id"=>$this->id)); - } + ", ["id"=>$this->id]); + } - /** - * Set the tags for this image. - */ - public function set_tags(array $unfiltered_tags) { - global $database; + /** + * Set the tags for this image. + */ + public function set_tags(array $unfiltered_tags) + { + global $database; - $tags = []; - foreach ($unfiltered_tags as $tag) { - if(mb_strlen($tag, 'UTF-8') > 255){ - flash_message("Can't set a tag longer than 255 characters"); - continue; - } - if(startsWith($tag, "-")) { - flash_message("Can't set a tag which starts with a minus"); - continue; - } + $tags = []; + foreach ($unfiltered_tags as $tag) { + if (mb_strlen($tag, 'UTF-8') > 255) { + flash_message("Can't set a tag longer than 255 characters"); + continue; + } + if (startsWith($tag, "-")) { + flash_message("Can't set a tag which starts with a minus"); + continue; + } - $tags[] = $tag; - } + $tags[] = $tag; + } - if(count($tags) <= 0) { - throw new SCoreException('Tried to set zero tags'); - } + if (count($tags) <= 0) { + throw new SCoreException('Tried to set zero tags'); + } - if(Tag::implode($tags) != $this->get_tag_list()) { - // delete old - $this->delete_tags_from_image(); - // insert each new tags - foreach($tags as $tag) { - $id = $database->get_one( - $database->scoreql_to_sql(" + if (Tag::implode($tags) != $this->get_tag_list()) { + // delete old + $this->delete_tags_from_image(); + // insert each new tags + foreach ($tags as $tag) { + $id = $database->get_one( + $database->scoreql_to_sql(" SELECT id FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag) "), - array("tag"=>$tag) - ); - if(empty($id)) { - // a new tag - $database->execute( - "INSERT INTO tags(tag) VALUES (:tag)", - array("tag"=>$tag)); - $database->execute( - "INSERT INTO image_tags(image_id, tag_id) + ["tag"=>$tag] + ); + if (empty($id)) { + // a new tag + $database->execute( + "INSERT INTO tags(tag) VALUES (:tag)", + ["tag"=>$tag] + ); + $database->execute( + "INSERT INTO image_tags(image_id, tag_id) VALUES(:id, (SELECT id FROM tags WHERE tag = :tag))", - array("id"=>$this->id, "tag"=>$tag)); - } - else { - // user of an existing tag - $database->execute(" + ["id"=>$this->id, "tag"=>$tag] + ); + } else { + // user of an existing tag + $database->execute(" INSERT INTO image_tags(image_id, tag_id) VALUES(:iid, :tid) - ", array("iid"=>$this->id, "tid"=>$id)); - } - $database->execute( - $database->scoreql_to_sql(" + ", ["iid"=>$this->id, "tid"=>$id]); + } + $database->execute( + $database->scoreql_to_sql(" UPDATE tags SET count = count + 1 WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag) "), - array("tag"=>$tag) - ); - } + ["tag"=>$tag] + ); + } - log_info("core_image", "Tags for Image #{$this->id} set to: ".Tag::implode($tags), null, array("image_id" => $this->id)); - $database->cache->delete("image-{$this->id}-tags"); - } - } + log_info("core_image", "Tags for Image #{$this->id} set to: ".Tag::implode($tags), null, ["image_id" => $this->id]); + $database->cache->delete("image-{$this->id}-tags"); + } + } - /** - * Send list of metatags to be parsed. - * - * #param string[] $metatags - */ - public function parse_metatags(array $metatags, int $image_id): void { - foreach($metatags as $tag) { - $ttpe = new TagTermParseEvent($tag, $image_id, TRUE); - send_event($ttpe); - } - } + /** + * Send list of metatags to be parsed. + * + * #param string[] $metatags + */ + public function parse_metatags(array $metatags, int $image_id): void + { + foreach ($metatags as $tag) { + $ttpe = new TagTermParseEvent($tag, $image_id, true); + send_event($ttpe); + } + } - /** - * Delete this image from the database and disk - */ - public function delete(): void { - global $database; - $this->delete_tags_from_image(); - $database->execute("DELETE FROM images WHERE id=:id", array("id"=>$this->id)); - log_info("core_image", 'Deleted Image #'.$this->id.' ('.$this->hash.')', null, array("image_id" => $this->id)); + /** + * Delete this image from the database and disk + */ + public function delete(): void + { + global $database; + $this->delete_tags_from_image(); + $database->execute("DELETE FROM images WHERE id=:id", ["id"=>$this->id]); + log_info("core_image", 'Deleted Image #'.$this->id.' ('.$this->hash.')', null, ["image_id" => $this->id]); - unlink($this->get_image_filename()); - unlink($this->get_thumb_filename()); - } + unlink($this->get_image_filename()); + unlink($this->get_thumb_filename()); + } - /** - * This function removes an image (and thumbnail) from the DISK ONLY. - * It DOES NOT remove anything from the database. - */ - public function remove_image_only(): void { - log_info("core_image", 'Removed Image File ('.$this->hash.')', null, array("image_id" => $this->id)); - @unlink($this->get_image_filename()); - @unlink($this->get_thumb_filename()); - } + /** + * This function removes an image (and thumbnail) from the DISK ONLY. + * It DOES NOT remove anything from the database. + */ + public function remove_image_only(): void + { + log_info("core_image", 'Removed Image File ('.$this->hash.')', null, ["image_id" => $this->id]); + @unlink($this->get_image_filename()); + @unlink($this->get_thumb_filename()); + } - public function parse_link_template(string $tmpl, string $_escape="url_escape", int $n=0): string { - global $config; + public function parse_link_template(string $tmpl, string $_escape="url_escape", int $n=0): string + { + global $config; - // don't bother hitting the database if it won't be used... - $tags = ""; - if(strpos($tmpl, '$tags') !== false) { // * stabs dynamically typed languages with a rusty spoon * - $tags = $this->get_tag_list(); - $tags = str_replace("/", "", $tags); - $tags = preg_replace("/^\.+/", "", $tags); - } + // don't bother hitting the database if it won't be used... + $tags = ""; + if (strpos($tmpl, '$tags') !== false) { // * stabs dynamically typed languages with a rusty spoon * + $tags = $this->get_tag_list(); + $tags = str_replace("/", "", $tags); + $tags = preg_replace("/^\.+/", "", $tags); + } - $base_href = $config->get_string('base_href'); - $fname = $this->get_filename(); - $base_fname = strpos($fname, '.') ? substr($fname, 0, strrpos($fname, '.')) : $fname; + $base_href = $config->get_string('base_href'); + $fname = $this->get_filename(); + $base_fname = strpos($fname, '.') ? substr($fname, 0, strrpos($fname, '.')) : $fname; - $tmpl = str_replace('$id', $this->id, $tmpl); - $tmpl = str_replace('$hash_ab', substr($this->hash, 0, 2), $tmpl); - $tmpl = str_replace('$hash_cd', substr($this->hash, 2, 2), $tmpl); - $tmpl = str_replace('$hash', $this->hash, $tmpl); - $tmpl = str_replace('$tags', $_escape($tags), $tmpl); - $tmpl = str_replace('$base', $base_href, $tmpl); - $tmpl = str_replace('$ext', $this->ext, $tmpl); - $tmpl = str_replace('$size', "{$this->width}x{$this->height}", $tmpl); - $tmpl = str_replace('$filesize', to_shorthand_int($this->filesize), $tmpl); - $tmpl = str_replace('$filename', $_escape($base_fname), $tmpl); - $tmpl = str_replace('$title', $_escape($config->get_string("title")), $tmpl); - $tmpl = str_replace('$date', $_escape(autodate($this->posted, false)), $tmpl); + $tmpl = str_replace('$id', $this->id, $tmpl); + $tmpl = str_replace('$hash_ab', substr($this->hash, 0, 2), $tmpl); + $tmpl = str_replace('$hash_cd', substr($this->hash, 2, 2), $tmpl); + $tmpl = str_replace('$hash', $this->hash, $tmpl); + $tmpl = str_replace('$tags', $_escape($tags), $tmpl); + $tmpl = str_replace('$base', $base_href, $tmpl); + $tmpl = str_replace('$ext', $this->ext, $tmpl); + $tmpl = str_replace('$size', "{$this->width}x{$this->height}", $tmpl); + $tmpl = str_replace('$filesize', to_shorthand_int($this->filesize), $tmpl); + $tmpl = str_replace('$filename', $_escape($base_fname), $tmpl); + $tmpl = str_replace('$title', $_escape($config->get_string("title")), $tmpl); + $tmpl = str_replace('$date', $_escape(autodate($this->posted, false)), $tmpl); - // nothing seems to use this, sending the event out to 50 exts is a lot of overhead - if(!SPEED_HAX) { - $plte = new ParseLinkTemplateEvent($tmpl, $this); - send_event($plte); - $tmpl = $plte->link; - } + // nothing seems to use this, sending the event out to 50 exts is a lot of overhead + if (!SPEED_HAX) { + $plte = new ParseLinkTemplateEvent($tmpl, $this); + send_event($plte); + $tmpl = $plte->link; + } - static $flexihash = null; - static $fh_last_opts = null; - $matches = array(); - if(preg_match("/(.*){(.*)}(.*)/", $tmpl, $matches)) { - $pre = $matches[1]; - $opts = $matches[2]; - $post = $matches[3]; + static $flexihash = null; + static $fh_last_opts = null; + $matches = []; + if (preg_match("/(.*){(.*)}(.*)/", $tmpl, $matches)) { + $pre = $matches[1]; + $opts = $matches[2]; + $post = $matches[3]; - if($opts != $fh_last_opts) { - $fh_last_opts = $opts; - $flexihash = new Flexihash\Flexihash(); - foreach(explode(",", $opts) as $opt) { - $parts = explode("=", $opt); - $parts_count = count($parts); - $opt_val = ""; - $opt_weight = 0; - if($parts_count === 2) { - $opt_val = $parts[0]; - $opt_weight = $parts[1]; - } - elseif($parts_count === 1) { - $opt_val = $parts[0]; - $opt_weight = 1; - } - $flexihash->addTarget($opt_val, $opt_weight); - } - } + if ($opts != $fh_last_opts) { + $fh_last_opts = $opts; + $flexihash = new Flexihash\Flexihash(); + foreach (explode(",", $opts) as $opt) { + $parts = explode("=", $opt); + $parts_count = count($parts); + $opt_val = ""; + $opt_weight = 0; + if ($parts_count === 2) { + $opt_val = $parts[0]; + $opt_weight = $parts[1]; + } elseif ($parts_count === 1) { + $opt_val = $parts[0]; + $opt_weight = 1; + } + $flexihash->addTarget($opt_val, $opt_weight); + } + } - // $choice = $flexihash->lookup($pre.$post); - $choices = $flexihash->lookupList($this->hash, $n+1); // hash doesn't change - $choice = $choices[$n]; - $tmpl = $pre.$choice.$post; - } + // $choice = $flexihash->lookup($pre.$post); + $choices = $flexihash->lookupList($this->hash, $n+1); // hash doesn't change + $choice = $choices[$n]; + $tmpl = $pre.$choice.$post; + } - return $tmpl; - } + return $tmpl; + } - /** - * #param string[] $terms - */ - private static function build_search_querylet(array $terms): Querylet { - global $database; + /** + * #param string[] $terms + */ + private static function build_search_querylet(array $terms): Querylet + { + global $database; - $tag_querylets = array(); - $img_querylets = array(); - $positive_tag_count = 0; - $negative_tag_count = 0; + $tag_querylets = []; + $img_querylets = []; + $positive_tag_count = 0; + $negative_tag_count = 0; - /* - * Turn a bunch of strings into a bunch of TagQuerylet - * and ImgQuerylet objects - */ - $stpe = new SearchTermParseEvent(null, $terms); - send_event($stpe); - if ($stpe->is_querylet_set()) { - foreach ($stpe->get_querylets() as $querylet) { - $img_querylets[] = new ImgQuerylet($querylet, true); - } - } + /* + * Turn a bunch of strings into a bunch of TagQuerylet + * and ImgQuerylet objects + */ + $stpe = new SearchTermParseEvent(null, $terms); + send_event($stpe); + if ($stpe->is_querylet_set()) { + foreach ($stpe->get_querylets() as $querylet) { + $img_querylets[] = new ImgQuerylet($querylet, true); + } + } - foreach ($terms as $term) { - $positive = true; - if (is_string($term) && !empty($term) && ($term[0] == '-')) { - $positive = false; - $term = substr($term, 1); - } - if (strlen($term) === 0) { - continue; - } + foreach ($terms as $term) { + $positive = true; + if (is_string($term) && !empty($term) && ($term[0] == '-')) { + $positive = false; + $term = substr($term, 1); + } + if (strlen($term) === 0) { + continue; + } - $stpe = new SearchTermParseEvent($term, $terms); - send_event($stpe); - if ($stpe->is_querylet_set()) { - foreach ($stpe->get_querylets() as $querylet) { - $img_querylets[] = new ImgQuerylet($querylet, $positive); - } - } - else { - // if the whole match is wild, skip this; - // if not, translate into SQL - if(str_replace("*", "", $term) != "") { - $term = str_replace('_', '\_', $term); - $term = str_replace('%', '\%', $term); - $term = str_replace('*', '%', $term); - $tag_querylets[] = new TagQuerylet($term, $positive); - if ($positive) $positive_tag_count++; - else $negative_tag_count++; - } - } - } + $stpe = new SearchTermParseEvent($term, $terms); + send_event($stpe); + if ($stpe->is_querylet_set()) { + foreach ($stpe->get_querylets() as $querylet) { + $img_querylets[] = new ImgQuerylet($querylet, $positive); + } + } else { + // if the whole match is wild, skip this; + // if not, translate into SQL + if (str_replace("*", "", $term) != "") { + $term = str_replace('_', '\_', $term); + $term = str_replace('%', '\%', $term); + $term = str_replace('*', '%', $term); + $tag_querylets[] = new TagQuerylet($term, $positive); + if ($positive) { + $positive_tag_count++; + } else { + $negative_tag_count++; + } + } + } + } - /* - * Turn a bunch of Querylet objects into a base query - * - * Must follow the format - * - * SELECT images.* - * FROM (...) AS images - * WHERE (...) - * - * ie, return a set of images.* columns, and end with a WHERE - */ + /* + * Turn a bunch of Querylet objects into a base query + * + * Must follow the format + * + * SELECT images.* + * FROM (...) AS images + * WHERE (...) + * + * ie, return a set of images.* columns, and end with a WHERE + */ - // no tags, do a simple search - if($positive_tag_count === 0 && $negative_tag_count === 0) { - $query = new Querylet(" + // no tags, do a simple search + if ($positive_tag_count === 0 && $negative_tag_count === 0) { + $query = new Querylet(" SELECT images.* FROM images WHERE 1=1 "); - } + } - // one positive tag (a common case), do an optimised search - else if($positive_tag_count === 1 && $negative_tag_count === 0) { - # "LIKE" to account for wildcards - $query = new Querylet($database->scoreql_to_sql(" + // one positive tag (a common case), do an optimised search + elseif ($positive_tag_count === 1 && $negative_tag_count === 0) { + # "LIKE" to account for wildcards + $query = new Querylet($database->scoreql_to_sql(" SELECT * FROM ( SELECT images.* @@ -780,104 +836,110 @@ class Image { GROUP BY images.id ) AS images WHERE 1=1 - "), array("tag"=>$tag_querylets[0]->tag)); - } + "), ["tag"=>$tag_querylets[0]->tag]); + } - // more than one positive tag, or more than zero negative tags - else { - if($database->get_driver_name() === "mysql") - $query = Image::build_ugly_search_querylet($tag_querylets); - else - $query = Image::build_accurate_search_querylet($tag_querylets); - } + // more than one positive tag, or more than zero negative tags + else { + if ($database->get_driver_name() === "mysql") { + $query = Image::build_ugly_search_querylet($tag_querylets); + } else { + $query = Image::build_accurate_search_querylet($tag_querylets); + } + } - /* - * Merge all the image metadata searches into one generic querylet - * and append to the base querylet with "AND blah" - */ - if(!empty($img_querylets)) { - $n = 0; - $img_sql = ""; - $img_vars = array(); - foreach ($img_querylets as $iq) { - if ($n++ > 0) $img_sql .= " AND"; - if (!$iq->positive) $img_sql .= " NOT"; - $img_sql .= " (" . $iq->qlet->sql . ")"; - $img_vars = array_merge($img_vars, $iq->qlet->variables); - } - $query->append_sql(" AND "); - $query->append(new Querylet($img_sql, $img_vars)); - } + /* + * Merge all the image metadata searches into one generic querylet + * and append to the base querylet with "AND blah" + */ + if (!empty($img_querylets)) { + $n = 0; + $img_sql = ""; + $img_vars = []; + foreach ($img_querylets as $iq) { + if ($n++ > 0) { + $img_sql .= " AND"; + } + if (!$iq->positive) { + $img_sql .= " NOT"; + } + $img_sql .= " (" . $iq->qlet->sql . ")"; + $img_vars = array_merge($img_vars, $iq->qlet->variables); + } + $query->append_sql(" AND "); + $query->append(new Querylet($img_sql, $img_vars)); + } - return $query; - } + return $query; + } - /** - * WARNING: this description is no longer accurate, though it does get across - * the general idea - the actual method has a few extra optimisations - * - * "foo bar -baz user=foo" becomes - * - * SELECT * FROM images WHERE - * images.id IN (SELECT image_id FROM image_tags WHERE tag='foo') - * AND images.id IN (SELECT image_id FROM image_tags WHERE tag='bar') - * AND NOT images.id IN (SELECT image_id FROM image_tags WHERE tag='baz') - * AND images.id IN (SELECT id FROM images WHERE owner_name='foo') - * - * This is: - * A) Incredibly simple: - * Each search term maps to a list of image IDs - * B) Runs really fast on a good database: - * These lists are calculated once, and the set intersection taken - * C) Runs really slow on bad databases: - * All the subqueries are executed every time for every row in the - * images table. Yes, MySQL does suck this much. - * - * #param TagQuerylet[] $tag_querylets - */ - private static function build_accurate_search_querylet(array $tag_querylets): Querylet { - global $database; + /** + * WARNING: this description is no longer accurate, though it does get across + * the general idea - the actual method has a few extra optimisations + * + * "foo bar -baz user=foo" becomes + * + * SELECT * FROM images WHERE + * images.id IN (SELECT image_id FROM image_tags WHERE tag='foo') + * AND images.id IN (SELECT image_id FROM image_tags WHERE tag='bar') + * AND NOT images.id IN (SELECT image_id FROM image_tags WHERE tag='baz') + * AND images.id IN (SELECT id FROM images WHERE owner_name='foo') + * + * This is: + * A) Incredibly simple: + * Each search term maps to a list of image IDs + * B) Runs really fast on a good database: + * These lists are calculated once, and the set intersection taken + * C) Runs really slow on bad databases: + * All the subqueries are executed every time for every row in the + * images table. Yes, MySQL does suck this much. + * + * #param TagQuerylet[] $tag_querylets + */ + private static function build_accurate_search_querylet(array $tag_querylets): Querylet + { + global $database; - $positive_tag_id_array = array(); - $negative_tag_id_array = array(); + $positive_tag_id_array = []; + $negative_tag_id_array = []; - foreach ($tag_querylets as $tq) { - $tag_ids = $database->get_col( - $database->scoreql_to_sql(" + foreach ($tag_querylets as $tq) { + $tag_ids = $database->get_col( + $database->scoreql_to_sql(" SELECT id FROM tags WHERE SCORE_STRNORM(tag) LIKE SCORE_STRNORM(:tag) "), - array("tag" => $tq->tag) - ); - if ($tq->positive) { - $positive_tag_id_array = array_merge($positive_tag_id_array, $tag_ids); - if (count($tag_ids) == 0) { - # one of the positive tags had zero results, therefor there - # can be no results; "where 1=0" should shortcut things - return new Querylet(" + ["tag" => $tq->tag] + ); + if ($tq->positive) { + $positive_tag_id_array = array_merge($positive_tag_id_array, $tag_ids); + if (count($tag_ids) == 0) { + # one of the positive tags had zero results, therefor there + # can be no results; "where 1=0" should shortcut things + return new Querylet(" SELECT images.* FROM images WHERE 1=0 "); - } - } else { - $negative_tag_id_array = array_merge($negative_tag_id_array, $tag_ids); - } - } + } + } else { + $negative_tag_id_array = array_merge($negative_tag_id_array, $tag_ids); + } + } - assert($positive_tag_id_array || $negative_tag_id_array, @$_GET['q']); - $wheres = array(); - if (!empty($positive_tag_id_array)) { - $positive_tag_id_list = join(', ', $positive_tag_id_array); - $wheres[] = "tag_id IN ($positive_tag_id_list)"; - } - if (!empty($negative_tag_id_array)) { - $negative_tag_id_list = join(', ', $negative_tag_id_array); - $wheres[] = "tag_id NOT IN ($negative_tag_id_list)"; - } - $wheres_str = join(" AND ", $wheres); - return new Querylet(" + assert($positive_tag_id_array || $negative_tag_id_array, @$_GET['q']); + $wheres = []; + if (!empty($positive_tag_id_array)) { + $positive_tag_id_list = join(', ', $positive_tag_id_array); + $wheres[] = "tag_id IN ($positive_tag_id_list)"; + } + if (!empty($negative_tag_id_array)) { + $negative_tag_id_list = join(', ', $negative_tag_id_array); + $wheres[] = "tag_id NOT IN ($negative_tag_id_list)"; + } + $wheres_str = join(" AND ", $wheres); + return new Querylet(" SELECT images.* FROM images WHERE images.id IN ( @@ -887,71 +949,74 @@ class Image { GROUP BY image_id HAVING COUNT(image_id) >= :search_score ) - ", array("search_score"=>count($positive_tag_id_array))); - } + ", ["search_score"=>count($positive_tag_id_array)]); + } - /** - * this function exists because mysql is a turd, see the docs for - * build_accurate_search_querylet() for a full explanation - * - * #param TagQuerylet[] $tag_querylets - */ - private static function build_ugly_search_querylet(array $tag_querylets): Querylet { - global $database; + /** + * this function exists because mysql is a turd, see the docs for + * build_accurate_search_querylet() for a full explanation + * + * #param TagQuerylet[] $tag_querylets + */ + private static function build_ugly_search_querylet(array $tag_querylets): Querylet + { + global $database; - $positive_tag_count = 0; - foreach($tag_querylets as $tq) { - if($tq->positive) $positive_tag_count++; - } + $positive_tag_count = 0; + foreach ($tag_querylets as $tq) { + if ($tq->positive) { + $positive_tag_count++; + } + } - // only negative tags - shortcut to fail - if($positive_tag_count == 0) { - // TODO: This isn't currently implemented. - // SEE: https://github.com/shish/shimmie2/issues/66 - return new Querylet(" + // only negative tags - shortcut to fail + if ($positive_tag_count == 0) { + // TODO: This isn't currently implemented. + // SEE: https://github.com/shish/shimmie2/issues/66 + return new Querylet(" SELECT images.* FROM images WHERE 1=0 "); - } + } - // merge all the tag querylets into one generic one - $sql = "0"; - $terms = array(); - foreach($tag_querylets as $tq) { - $sign = $tq->positive ? "+" : "-"; - $sql .= ' '.$sign.' IF(SUM(tag LIKE :tag'.Image::$tag_n.'), 1, 0)'; - $terms['tag'.Image::$tag_n] = $tq->tag; - Image::$tag_n++; - } - $tag_search = new Querylet($sql, $terms); + // merge all the tag querylets into one generic one + $sql = "0"; + $terms = []; + foreach ($tag_querylets as $tq) { + $sign = $tq->positive ? "+" : "-"; + $sql .= ' '.$sign.' IF(SUM(tag LIKE :tag'.Image::$tag_n.'), 1, 0)'; + $terms['tag'.Image::$tag_n] = $tq->tag; + Image::$tag_n++; + } + $tag_search = new Querylet($sql, $terms); - $tag_id_array = array(); + $tag_id_array = []; - foreach($tag_querylets as $tq) { - $tag_ids = $database->get_col( - $database->scoreql_to_sql(" + foreach ($tag_querylets as $tq) { + $tag_ids = $database->get_col( + $database->scoreql_to_sql(" SELECT id FROM tags WHERE SCORE_STRNORM(tag) LIKE SCORE_STRNORM(:tag) "), - array("tag" => $tq->tag) - ); - $tag_id_array = array_merge($tag_id_array, $tag_ids); + ["tag" => $tq->tag] + ); + $tag_id_array = array_merge($tag_id_array, $tag_ids); - if($tq->positive && count($tag_ids) == 0) { - # one of the positive tags had zero results, therefor there - # can be no results; "where 1=0" should shortcut things - return new Querylet(" + if ($tq->positive && count($tag_ids) == 0) { + # one of the positive tags had zero results, therefor there + # can be no results; "where 1=0" should shortcut things + return new Querylet(" SELECT images.* FROM images WHERE 1=0 "); - } - } + } + } - Image::$tag_n = 0; - return new Querylet(' + Image::$tag_n = 0; + return new Querylet(' SELECT * FROM ( SELECT images.*, ('.$tag_search->sql.') AS score @@ -964,9 +1029,8 @@ class Image { ) AS images WHERE 1=1 ', array_merge( - $tag_search->variables, - array("score"=>$positive_tag_count) - )); - } + $tag_search->variables, + ["score"=>$positive_tag_count] + )); + } } - diff --git a/core/imageboard/misc.php b/core/imageboard/misc.php index 3f7fc599..cde0d981 100644 --- a/core/imageboard/misc.php +++ b/core/imageboard/misc.php @@ -9,15 +9,16 @@ * * @throws UploadException */ -function move_upload_to_archive(DataUploadEvent $event) { - $target = warehouse_path("images", $event->hash); - if(!@copy($event->tmpname, $target)) { - $errors = error_get_last(); - throw new UploadException( - "Failed to copy file from uploads ({$event->tmpname}) to archive ($target): ". - "{$errors['type']} / {$errors['message']}" - ); - } +function move_upload_to_archive(DataUploadEvent $event) +{ + $target = warehouse_path("images", $event->hash); + if (!@copy($event->tmpname, $target)) { + $errors = error_get_last(); + throw new UploadException( + "Failed to copy file from uploads ({$event->tmpname}) to archive ($target): ". + "{$errors['type']} / {$errors['message']}" + ); + } } /** @@ -25,45 +26,46 @@ function move_upload_to_archive(DataUploadEvent $event) { * * #return string[] */ -function add_dir(string $base): array { - $results = array(); +function add_dir(string $base): array +{ + $results = []; - foreach(list_files($base) as $full_path) { - $short_path = str_replace($base, "", $full_path); - $filename = basename($full_path); + foreach (list_files($base) as $full_path) { + $short_path = str_replace($base, "", $full_path); + $filename = basename($full_path); - $tags = path_to_tags($short_path); - $result = "$short_path (".str_replace(" ", ", ", $tags).")... "; - try { - add_image($full_path, $filename, $tags); - $result .= "ok"; - } - catch(UploadException $ex) { - $result .= "failed: ".$ex->getMessage(); - } - $results[] = $result; - } + $tags = path_to_tags($short_path); + $result = "$short_path (".str_replace(" ", ", ", $tags).")... "; + try { + add_image($full_path, $filename, $tags); + $result .= "ok"; + } catch (UploadException $ex) { + $result .= "failed: ".$ex->getMessage(); + } + $results[] = $result; + } - return $results; + return $results; } -function add_image(string $tmpname, string $filename, string $tags): void { - assert(file_exists($tmpname)); +function add_image(string $tmpname, string $filename, string $tags): void +{ + assert(file_exists($tmpname)); - $pathinfo = pathinfo($filename); - if(!array_key_exists('extension', $pathinfo)) { - throw new UploadException("File has no extension"); - } - $metadata = array(); - $metadata['filename'] = $pathinfo['basename']; - $metadata['extension'] = $pathinfo['extension']; - $metadata['tags'] = Tag::explode($tags); - $metadata['source'] = null; - $event = new DataUploadEvent($tmpname, $metadata); - send_event($event); - if($event->image_id == -1) { - throw new UploadException("File type not recognised"); - } + $pathinfo = pathinfo($filename); + if (!array_key_exists('extension', $pathinfo)) { + throw new UploadException("File has no extension"); + } + $metadata = []; + $metadata['filename'] = $pathinfo['basename']; + $metadata['extension'] = $pathinfo['extension']; + $metadata['tags'] = Tag::explode($tags); + $metadata['source'] = null; + $event = new DataUploadEvent($tmpname, $metadata); + send_event($event); + if ($event->image_id == -1) { + throw new UploadException("File type not recognised"); + } } /** @@ -72,26 +74,34 @@ function add_image(string $tmpname, string $filename, string $tags): void { * * #return int[] */ -function get_thumbnail_size(int $orig_width, int $orig_height): array { - global $config; +function get_thumbnail_size(int $orig_width, int $orig_height): array +{ + global $config; - if($orig_width === 0) $orig_width = 192; - if($orig_height === 0) $orig_height = 192; + if ($orig_width === 0) { + $orig_width = 192; + } + if ($orig_height === 0) { + $orig_height = 192; + } - if($orig_width > $orig_height * 5) $orig_width = $orig_height * 5; - if($orig_height > $orig_width * 5) $orig_height = $orig_width * 5; + if ($orig_width > $orig_height * 5) { + $orig_width = $orig_height * 5; + } + if ($orig_height > $orig_width * 5) { + $orig_height = $orig_width * 5; + } - $max_width = $config->get_int('thumb_width'); - $max_height = $config->get_int('thumb_height'); + $max_width = $config->get_int('thumb_width'); + $max_height = $config->get_int('thumb_height'); - $xscale = ($max_height / $orig_height); - $yscale = ($max_width / $orig_width); - $scale = ($xscale < $yscale) ? $xscale : $yscale; + $xscale = ($max_height / $orig_height); + $yscale = ($max_width / $orig_width); + $scale = ($xscale < $yscale) ? $xscale : $yscale; - if($scale > 1 && $config->get_bool('thumb_upscale')) { - return array((int)$orig_width, (int)$orig_height); - } - else { - return array((int)($orig_width*$scale), (int)($orig_height*$scale)); - } + if ($scale > 1 && $config->get_bool('thumb_upscale')) { + return [(int)$orig_width, (int)$orig_height]; + } else { + return [(int)($orig_width*$scale), (int)($orig_height*$scale)]; + } } diff --git a/core/imageboard/search.php b/core/imageboard/search.php index 8c1e4079..dd1712f7 100644 --- a/core/imageboard/search.php +++ b/core/imageboard/search.php @@ -1,49 +1,58 @@ sql = $sql; - $this->variables = $variables; - } + public function __construct(string $sql, array $variables=[]) + { + $this->sql = $sql; + $this->variables = $variables; + } - public function append(Querylet $querylet) { - $this->sql .= $querylet->sql; - $this->variables = array_merge($this->variables, $querylet->variables); - } + public function append(Querylet $querylet) + { + $this->sql .= $querylet->sql; + $this->variables = array_merge($this->variables, $querylet->variables); + } - public function append_sql(string $sql) { - $this->sql .= $sql; - } + public function append_sql(string $sql) + { + $this->sql .= $sql; + } - public function add_variable($var) { - $this->variables[] = $var; - } + public function add_variable($var) + { + $this->variables[] = $var; + } } -class TagQuerylet { - /** @var string */ - public $tag; - /** @var bool */ - public $positive; +class TagQuerylet +{ + /** @var string */ + public $tag; + /** @var bool */ + public $positive; - public function __construct(string $tag, bool $positive) { - $this->tag = $tag; - $this->positive = $positive; - } + public function __construct(string $tag, bool $positive) + { + $this->tag = $tag; + $this->positive = $positive; + } } -class ImgQuerylet { - /** @var \Querylet */ - public $qlet; - /** @var bool */ - public $positive; +class ImgQuerylet +{ + /** @var \Querylet */ + public $qlet; + /** @var bool */ + public $positive; - public function __construct(Querylet $qlet, bool $positive) { - $this->qlet = $qlet; - $this->positive = $positive; - } + public function __construct(Querylet $qlet, bool $positive) + { + $this->qlet = $qlet; + $this->positive = $positive; + } } diff --git a/core/imageboard/tag.php b/core/imageboard/tag.php index 594c731b..3e32d524 100644 --- a/core/imageboard/tag.php +++ b/core/imageboard/tag.php @@ -7,96 +7,97 @@ * All the methods are static, one should never actually use a tag object. * */ -class Tag { - public static function implode(array $tags): string { - sort($tags); - $tags = implode(' ', $tags); +class Tag +{ + public static function implode(array $tags): string + { + sort($tags); + $tags = implode(' ', $tags); - return $tags; - } + return $tags; + } - /** - * Turn a human-supplied string into a valid tag array. - * - * #return string[] - */ - public static function explode(string $tags, bool $tagme=true): array { - global $database; + /** + * Turn a human-supplied string into a valid tag array. + * + * #return string[] + */ + public static function explode(string $tags, bool $tagme=true): array + { + global $database; - $tags = explode(' ', trim($tags)); + $tags = explode(' ', trim($tags)); - /* sanitise by removing invisible / dodgy characters */ - $tag_array = array(); - foreach($tags as $tag) { - $tag = preg_replace("/\s/", "", $tag); # whitespace - $tag = preg_replace('/\x20(\x0e|\x0f)/', '', $tag); # unicode RTL - $tag = preg_replace("/\.+/", ".", $tag); # strings of dots? - $tag = preg_replace("/^(\.+[\/\\\\])+/", "", $tag); # trailing slashes? - $tag = trim($tag, ", \t\n\r\0\x0B"); + /* sanitise by removing invisible / dodgy characters */ + $tag_array = []; + foreach ($tags as $tag) { + $tag = preg_replace("/\s/", "", $tag); # whitespace + $tag = preg_replace('/\x20(\x0e|\x0f)/', '', $tag); # unicode RTL + $tag = preg_replace("/\.+/", ".", $tag); # strings of dots? + $tag = preg_replace("/^(\.+[\/\\\\])+/", "", $tag); # trailing slashes? + $tag = trim($tag, ", \t\n\r\0\x0B"); - if(mb_strlen($tag, 'UTF-8') > 255){ - flash_message("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n"); - continue; - } + if (mb_strlen($tag, 'UTF-8') > 255) { + flash_message("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n"); + continue; + } - if(!empty($tag)) { - $tag_array[] = $tag; - } - } + if (!empty($tag)) { + $tag_array[] = $tag; + } + } - /* if user supplied a blank string, add "tagme" */ - if(count($tag_array) === 0 && $tagme) { - $tag_array = array("tagme"); - } + /* if user supplied a blank string, add "tagme" */ + if (count($tag_array) === 0 && $tagme) { + $tag_array = ["tagme"]; + } - /* resolve aliases */ - $new = array(); - $i = 0; - $tag_count = count($tag_array); - while($i<$tag_count) { - $tag = $tag_array[$i]; - $negative = ''; - if(!empty($tag) && ($tag[0] == '-')) { - $negative = '-'; - $tag = substr($tag, 1); - } + /* resolve aliases */ + $new = []; + $i = 0; + $tag_count = count($tag_array); + while ($i<$tag_count) { + $tag = $tag_array[$i]; + $negative = ''; + if (!empty($tag) && ($tag[0] == '-')) { + $negative = '-'; + $tag = substr($tag, 1); + } - $newtags = $database->get_one( - $database->scoreql_to_sql(" + $newtags = $database->get_one( + $database->scoreql_to_sql(" SELECT newtag FROM aliases WHERE SCORE_STRNORM(oldtag)=SCORE_STRNORM(:tag) "), - array("tag"=>$tag) - ); - if(empty($newtags)) { - //tag has no alias, use old tag - $aliases = array($tag); - } - else { - $aliases = explode(" ", $newtags); // Tag::explode($newtags); - recursion can be infinite - } + ["tag"=>$tag] + ); + if (empty($newtags)) { + //tag has no alias, use old tag + $aliases = [$tag]; + } else { + $aliases = explode(" ", $newtags); // Tag::explode($newtags); - recursion can be infinite + } - foreach($aliases as $alias) { - if(!in_array($alias, $new)) { - if($tag == $alias) { - $new[] = $negative.$alias; - } - elseif(!in_array($alias, $tag_array)) { - $tag_array[] = $negative.$alias; - $tag_count++; - } - } - } - $i++; - } + foreach ($aliases as $alias) { + if (!in_array($alias, $new)) { + if ($tag == $alias) { + $new[] = $negative.$alias; + } elseif (!in_array($alias, $tag_array)) { + $tag_array[] = $negative.$alias; + $tag_count++; + } + } + } + $i++; + } - /* remove any duplicate tags */ - $tag_array = array_iunique($new); + /* remove any duplicate tags */ + $tag_array = array_iunique($new); - /* tidy up */ - sort($tag_array); + /* tidy up */ + sort($tag_array); - return $tag_array; - } + return $tag_array; + } } diff --git a/core/logging.php b/core/logging.php index 85d60c3e..22a0431d 100644 --- a/core/logging.php +++ b/core/logging.php @@ -17,39 +17,55 @@ define("SCORE_LOG_NOTSET", 0); * When taking action, a log event should be stored by the server * Quite often, both of these happen at once, hence log_*() having $flash */ -function log_msg(string $section, int $priority, string $message, ?string $flash=null, $args=array()) { - send_event(new LogEvent($section, $priority, $message, $args)); - $threshold = defined("CLI_LOG_LEVEL") ? CLI_LOG_LEVEL : 0; +function log_msg(string $section, int $priority, string $message, ?string $flash=null, $args=[]) +{ + send_event(new LogEvent($section, $priority, $message, $args)); + $threshold = defined("CLI_LOG_LEVEL") ? CLI_LOG_LEVEL : 0; - if((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ($priority >= $threshold)) { - print date("c")." $section: $message\n"; - } - if(!is_null($flash)) { - flash_message($flash); - } + if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ($priority >= $threshold)) { + print date("c")." $section: $message\n"; + } + if (!is_null($flash)) { + flash_message($flash); + } } // More shorthand ways of logging -function log_debug( string $section, string $message, ?string $flash=null, $args=array()) {log_msg($section, SCORE_LOG_DEBUG, $message, $flash, $args);} -function log_info( string $section, string $message, ?string $flash=null, $args=array()) {log_msg($section, SCORE_LOG_INFO, $message, $flash, $args);} -function log_warning( string $section, string $message, ?string $flash=null, $args=array()) {log_msg($section, SCORE_LOG_WARNING, $message, $flash, $args);} -function log_error( string $section, string $message, ?string $flash=null, $args=array()) {log_msg($section, SCORE_LOG_ERROR, $message, $flash, $args);} -function log_critical(string $section, string $message, ?string $flash=null, $args=array()) {log_msg($section, SCORE_LOG_CRITICAL, $message, $flash, $args);} +function log_debug(string $section, string $message, ?string $flash=null, $args=[]) +{ + log_msg($section, SCORE_LOG_DEBUG, $message, $flash, $args); +} +function log_info(string $section, string $message, ?string $flash=null, $args=[]) +{ + log_msg($section, SCORE_LOG_INFO, $message, $flash, $args); +} +function log_warning(string $section, string $message, ?string $flash=null, $args=[]) +{ + log_msg($section, SCORE_LOG_WARNING, $message, $flash, $args); +} +function log_error(string $section, string $message, ?string $flash=null, $args=[]) +{ + log_msg($section, SCORE_LOG_ERROR, $message, $flash, $args); +} +function log_critical(string $section, string $message, ?string $flash=null, $args=[]) +{ + log_msg($section, SCORE_LOG_CRITICAL, $message, $flash, $args); +} /** * Get a unique ID for this request, useful for grouping log messages. */ -function get_request_id(): string { - static $request_id = null; - if(!$request_id) { - // not completely trustworthy, as a user can spoof this - if(@$_SERVER['HTTP_X_VARNISH']) { - $request_id = $_SERVER['HTTP_X_VARNISH']; - } - else { - $request_id = "P" . uniqid(); - } - } - return $request_id; +function get_request_id(): string +{ + static $request_id = null; + if (!$request_id) { + // not completely trustworthy, as a user can spoof this + if (@$_SERVER['HTTP_X_VARNISH']) { + $request_id = $_SERVER['HTTP_X_VARNISH']; + } else { + $request_id = "P" . uniqid(); + } + } + return $request_id; } diff --git a/core/page.php b/core/page.php index c0f85ed0..6bd67e75 100644 --- a/core/page.php +++ b/core/page.php @@ -35,331 +35,352 @@ * The various extensions all add whatever they want to this structure, * then Layout turns it into HTML. */ -class Page { - /** @name Overall */ - //@{ - /** @var string */ - public $mode = "page"; - /** @var string */ - public $type = "text/html; charset=utf-8"; +class Page +{ + /** @name Overall */ + //@{ + /** @var string */ + public $mode = "page"; + /** @var string */ + public $type = "text/html; charset=utf-8"; - /** - * Set what this page should do; "page", "data", or "redirect". - */ - public function set_mode(string $mode) { - $this->mode = $mode; - } + /** + * Set what this page should do; "page", "data", or "redirect". + */ + public function set_mode(string $mode) + { + $this->mode = $mode; + } - /** - * Set the page's MIME type. - */ - public function set_type(string $type) { - $this->type = $type; - } + /** + * Set the page's MIME type. + */ + public function set_type(string $type) + { + $this->type = $type; + } - //@} - // ============================================== - /** @name "data" mode */ - //@{ + //@} + // ============================================== + /** @name "data" mode */ + //@{ - /** @var string; public only for unit test */ - public $data = ""; + /** @var string; public only for unit test */ + public $data = ""; - /** @var string; public only for unit test */ - public $filename = null; + /** @var string; public only for unit test */ + public $filename = null; - /** - * Set the raw data to be sent. - */ - public function set_data(string $data) { - $this->data = $data; - } + /** + * Set the raw data to be sent. + */ + public function set_data(string $data) + { + $this->data = $data; + } - /** - * Set the recommended download filename. - */ - public function set_filename(string $filename) { - $this->filename = $filename; - } + /** + * Set the recommended download filename. + */ + public function set_filename(string $filename) + { + $this->filename = $filename; + } - //@} - // ============================================== - /** @name "redirect" mode */ - //@{ + //@} + // ============================================== + /** @name "redirect" mode */ + //@{ - /** @var string */ - private $redirect = ""; + /** @var string */ + private $redirect = ""; - /** - * Set the URL to redirect to (remember to use make_link() if linking - * to a page in the same site). - */ - public function set_redirect(string $redirect) { - $this->redirect = $redirect; - } + /** + * Set the URL to redirect to (remember to use make_link() if linking + * to a page in the same site). + */ + public function set_redirect(string $redirect) + { + $this->redirect = $redirect; + } - //@} - // ============================================== - /** @name "page" mode */ - //@{ + //@} + // ============================================== + /** @name "page" mode */ + //@{ - /** @var int */ - public $code = 200; + /** @var int */ + public $code = 200; - /** @var string */ - public $title = ""; + /** @var string */ + public $title = ""; - /** @var string */ - public $heading = ""; + /** @var string */ + public $heading = ""; - /** @var string */ - public $subheading = ""; + /** @var string */ + public $subheading = ""; - /** @var string */ - public $quicknav = ""; + /** @var string */ + public $quicknav = ""; - /** @var string[] */ - public $html_headers = array(); + /** @var string[] */ + public $html_headers = []; - /** @var string[] */ - public $http_headers = array(); + /** @var string[] */ + public $http_headers = []; - /** @var string[][] */ - public $cookies = array(); + /** @var string[][] */ + public $cookies = []; - /** @var Block[] */ - public $blocks = array(); + /** @var Block[] */ + public $blocks = []; - /** - * Set the HTTP status code - */ - public function set_code(int $code): void { - $this->code = $code; - } + /** + * Set the HTTP status code + */ + public function set_code(int $code): void + { + $this->code = $code; + } - public function set_title(string $title): void { - $this->title = $title; - } + public function set_title(string $title): void + { + $this->title = $title; + } - public function set_heading(string $heading): void { - $this->heading = $heading; - } + public function set_heading(string $heading): void + { + $this->heading = $heading; + } - public function set_subheading(string $subheading): void { - $this->subheading = $subheading; - } + public function set_subheading(string $subheading): void + { + $this->subheading = $subheading; + } - /** - * Add a line to the HTML head section. - */ - public function add_html_header(string $line, int $position=50): void { - while(isset($this->html_headers[$position])) $position++; - $this->html_headers[$position] = $line; - } + /** + * Add a line to the HTML head section. + */ + public function add_html_header(string $line, int $position=50): void + { + while (isset($this->html_headers[$position])) { + $position++; + } + $this->html_headers[$position] = $line; + } - /** - * Add a http header to be sent to the client. - */ - public function add_http_header(string $line, int $position=50): void { - while(isset($this->http_headers[$position])) $position++; - $this->http_headers[$position] = $line; - } + /** + * Add a http header to be sent to the client. + */ + public function add_http_header(string $line, int $position=50): void + { + while (isset($this->http_headers[$position])) { + $position++; + } + $this->http_headers[$position] = $line; + } - /** - * The counterpart for get_cookie, this works like php's - * setcookie method, but prepends the site-wide cookie prefix to - * the $name argument before doing anything. - */ - public function add_cookie(string $name, string $value, int $time, string $path): void { - $full_name = COOKIE_PREFIX."_".$name; - $this->cookies[] = array($full_name, $value, $time, $path); - } + /** + * The counterpart for get_cookie, this works like php's + * setcookie method, but prepends the site-wide cookie prefix to + * the $name argument before doing anything. + */ + public function add_cookie(string $name, string $value, int $time, string $path): void + { + $full_name = COOKIE_PREFIX."_".$name; + $this->cookies[] = [$full_name, $value, $time, $path]; + } - public function get_cookie(string $name): ?string { - $full_name = COOKIE_PREFIX."_".$name; - if(isset($_COOKIE[$full_name])) { - return $_COOKIE[$full_name]; - } - else { - return null; - } - } + public function get_cookie(string $name): ?string + { + $full_name = COOKIE_PREFIX."_".$name; + if (isset($_COOKIE[$full_name])) { + return $_COOKIE[$full_name]; + } else { + return null; + } + } - /** - * Get all the HTML headers that are currently set and return as a string. - */ - public function get_all_html_headers(): string { - $data = ''; - ksort($this->html_headers); - foreach ($this->html_headers as $line) { - $data .= "\t\t" . $line . "\n"; - } - return $data; - } + /** + * Get all the HTML headers that are currently set and return as a string. + */ + public function get_all_html_headers(): string + { + $data = ''; + ksort($this->html_headers); + foreach ($this->html_headers as $line) { + $data .= "\t\t" . $line . "\n"; + } + return $data; + } - /** - * Removes all currently set HTML headers (Be careful..). - */ - public function delete_all_html_headers(): void { - $this->html_headers = array(); - } + /** + * Removes all currently set HTML headers (Be careful..). + */ + public function delete_all_html_headers(): void + { + $this->html_headers = []; + } - /** - * Add a Block of data to the page. - */ - public function add_block(Block $block) { - $this->blocks[] = $block; - } + /** + * Add a Block of data to the page. + */ + public function add_block(Block $block) + { + $this->blocks[] = $block; + } - //@} - // ============================================== + //@} + // ============================================== - /** - * Display the page according to the mode and data given. - */ - public function display(): void { - global $page, $user; + /** + * Display the page according to the mode and data given. + */ + public function display(): void + { + global $page, $user; - header("HTTP/1.0 {$this->code} Shimmie"); - header("Content-type: ".$this->type); - header("X-Powered-By: SCore-".SCORE_VERSION); + header("HTTP/1.0 {$this->code} Shimmie"); + header("Content-type: ".$this->type); + header("X-Powered-By: SCore-".SCORE_VERSION); - if (!headers_sent()) { - foreach($this->http_headers as $head) { - header($head); - } - foreach($this->cookies as $c) { - setcookie($c[0], $c[1], $c[2], $c[3]); - } - } else { - print "Error: Headers have already been sent to the client."; - } + if (!headers_sent()) { + foreach ($this->http_headers as $head) { + header($head); + } + foreach ($this->cookies as $c) { + setcookie($c[0], $c[1], $c[2], $c[3]); + } + } else { + print "Error: Headers have already been sent to the client."; + } - switch($this->mode) { - case "page": - if(CACHE_HTTP) { - header("Vary: Cookie, Accept-Encoding"); - if($user->is_anonymous() && $_SERVER["REQUEST_METHOD"] == "GET") { - header("Cache-control: public, max-age=600"); - header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 600) . ' GMT'); - } - else { - #header("Cache-control: private, max-age=0"); - header("Cache-control: no-cache"); - header('Expires: ' . gmdate('D, d M Y H:i:s', time() - 600) . ' GMT'); - } - } - #else { - # header("Cache-control: no-cache"); - # header('Expires: ' . gmdate('D, d M Y H:i:s', time() - 600) . ' GMT'); - #} - if($this->get_cookie("flash_message") !== null) { - $this->add_cookie("flash_message", "", -1, "/"); - } - usort($this->blocks, "blockcmp"); - $this->add_auto_html_headers(); - $layout = new Layout(); - $layout->display_page($page); - break; - case "data": - header("Content-Length: ".strlen($this->data)); - if(!is_null($this->filename)) { - header('Content-Disposition: attachment; filename='.$this->filename); - } - print $this->data; - break; - case "redirect": - header('Location: '.$this->redirect); - print 'You should be redirected to '.$this->redirect.''; - break; - default: - print "Invalid page mode"; - break; - } - } + switch ($this->mode) { + case "page": + if (CACHE_HTTP) { + header("Vary: Cookie, Accept-Encoding"); + if ($user->is_anonymous() && $_SERVER["REQUEST_METHOD"] == "GET") { + header("Cache-control: public, max-age=600"); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 600) . ' GMT'); + } else { + #header("Cache-control: private, max-age=0"); + header("Cache-control: no-cache"); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() - 600) . ' GMT'); + } + } + #else { + # header("Cache-control: no-cache"); + # header('Expires: ' . gmdate('D, d M Y H:i:s', time() - 600) . ' GMT'); + #} + if ($this->get_cookie("flash_message") !== null) { + $this->add_cookie("flash_message", "", -1, "/"); + } + usort($this->blocks, "blockcmp"); + $this->add_auto_html_headers(); + $layout = new Layout(); + $layout->display_page($page); + break; + case "data": + header("Content-Length: ".strlen($this->data)); + if (!is_null($this->filename)) { + header('Content-Disposition: attachment; filename='.$this->filename); + } + print $this->data; + break; + case "redirect": + header('Location: '.$this->redirect); + print 'You should be redirected to '.$this->redirect.''; + break; + default: + print "Invalid page mode"; + break; + } + } - /** - * This function grabs all the CSS and JavaScript files sprinkled throughout Shimmie's folders, - * concatenates them together into two large files (one for CSS and one for JS) and then stores - * them in the /cache/ directory for serving to the user. - * - * Why do this? Two reasons: - * 1. Reduces the number of files the user's browser needs to download. - * 2. Allows these cached files to be compressed/minified by the admin. - * - * TODO: This should really be configurable somehow... - */ - public function add_auto_html_headers(): void { - global $config; + /** + * This function grabs all the CSS and JavaScript files sprinkled throughout Shimmie's folders, + * concatenates them together into two large files (one for CSS and one for JS) and then stores + * them in the /cache/ directory for serving to the user. + * + * Why do this? Two reasons: + * 1. Reduces the number of files the user's browser needs to download. + * 2. Allows these cached files to be compressed/minified by the admin. + * + * TODO: This should really be configurable somehow... + */ + public function add_auto_html_headers(): void + { + global $config; - $data_href = get_base_href(); - $theme_name = $config->get_string('theme', 'default'); + $data_href = get_base_href(); + $theme_name = $config->get_string('theme', 'default'); - $this->add_html_header("", 40); + $this->add_html_header("", 40); - # static handler will map these to themes/foo/static/bar.ico or ext/handle_static/static/bar.ico - $this->add_html_header("", 41); - $this->add_html_header("", 42); + # static handler will map these to themes/foo/static/bar.ico or ext/handle_static/static/bar.ico + $this->add_html_header("", 41); + $this->add_html_header("", 42); - //We use $config_latest to make sure cache is reset if config is ever updated. - $config_latest = 0; - foreach(zglob("data/config/*") as $conf) { - $config_latest = max($config_latest, filemtime($conf)); - } + //We use $config_latest to make sure cache is reset if config is ever updated. + $config_latest = 0; + foreach (zglob("data/config/*") as $conf) { + $config_latest = max($config_latest, filemtime($conf)); + } - /*** Generate CSS cache files ***/ - $css_latest = $config_latest; - $css_files = array_merge( - zglob("ext/{".ENABLED_EXTS."}/style.css"), - zglob("themes/$theme_name/style.css") - ); - foreach($css_files as $css) { - $css_latest = max($css_latest, filemtime($css)); - } - $css_md5 = md5(serialize($css_files)); - $css_cache_file = data_path("cache/style/{$theme_name}.{$css_latest}.{$css_md5}.css"); - if(!file_exists($css_cache_file)) { - $css_data = ""; - foreach($css_files as $file) { - $file_data = file_get_contents($file); - $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; - $replace = 'url("../../../'.dirname($file).'/$1")'; - $file_data = preg_replace($pattern, $replace, $file_data); - $css_data .= $file_data . "\n"; - } - file_put_contents($css_cache_file, $css_data); - } - $this->add_html_header("", 43); + /*** Generate CSS cache files ***/ + $css_latest = $config_latest; + $css_files = array_merge( + zglob("ext/{".ENABLED_EXTS."}/style.css"), + zglob("themes/$theme_name/style.css") + ); + foreach ($css_files as $css) { + $css_latest = max($css_latest, filemtime($css)); + } + $css_md5 = md5(serialize($css_files)); + $css_cache_file = data_path("cache/style/{$theme_name}.{$css_latest}.{$css_md5}.css"); + if (!file_exists($css_cache_file)) { + $css_data = ""; + foreach ($css_files as $file) { + $file_data = file_get_contents($file); + $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; + $replace = 'url("../../../'.dirname($file).'/$1")'; + $file_data = preg_replace($pattern, $replace, $file_data); + $css_data .= $file_data . "\n"; + } + file_put_contents($css_cache_file, $css_data); + } + $this->add_html_header("", 43); - /*** Generate JS cache files ***/ - $js_latest = $config_latest; - $js_files = array_merge( - [ - "vendor/bower-asset/jquery/dist/jquery.min.js", - "vendor/bower-asset/jquery-timeago/jquery.timeago.js", - "vendor/bower-asset/tablesorter/jquery.tablesorter.min.js", - "vendor/bower-asset/js-cookie/src/js.cookie.js", - "ext/handle_static/modernizr-3.3.1.custom.js", - ], - zglob("ext/{".ENABLED_EXTS."}/script.js"), - zglob("themes/$theme_name/script.js") - ); - foreach($js_files as $js) { - $js_latest = max($js_latest, filemtime($js)); - } - $js_md5 = md5(serialize($js_files)); - $js_cache_file = data_path("cache/script/{$theme_name}.{$js_latest}.{$js_md5}.js"); - if(!file_exists($js_cache_file)) { - $js_data = ""; - foreach($js_files as $file) { - $js_data .= file_get_contents($file) . "\n"; - } - file_put_contents($js_cache_file, $js_data); - } - $this->add_html_header("", 44); - } + /*** Generate JS cache files ***/ + $js_latest = $config_latest; + $js_files = array_merge( + [ + "vendor/bower-asset/jquery/dist/jquery.min.js", + "vendor/bower-asset/jquery-timeago/jquery.timeago.js", + "vendor/bower-asset/tablesorter/jquery.tablesorter.min.js", + "vendor/bower-asset/js-cookie/src/js.cookie.js", + "ext/handle_static/modernizr-3.3.1.custom.js", + ], + zglob("ext/{".ENABLED_EXTS."}/script.js"), + zglob("themes/$theme_name/script.js") + ); + foreach ($js_files as $js) { + $js_latest = max($js_latest, filemtime($js)); + } + $js_md5 = md5(serialize($js_files)); + $js_cache_file = data_path("cache/script/{$theme_name}.{$js_latest}.{$js_md5}.js"); + if (!file_exists($js_cache_file)) { + $js_data = ""; + foreach ($js_files as $file) { + $js_data .= file_get_contents($file) . "\n"; + } + file_put_contents($js_cache_file, $js_data); + } + $this->add_html_header("", 44); + } } diff --git a/core/polyfills.php b/core/polyfills.php index 8081a0db..21a27031 100644 --- a/core/polyfills.php +++ b/core/polyfills.php @@ -6,15 +6,16 @@ /** * Remove an item from an array */ -function array_remove(array $array, $to_remove): array { - $array = array_unique($array); - $a2 = array(); - foreach($array as $existing) { - if($existing != $to_remove) { - $a2[] = $existing; - } - } - return $a2; +function array_remove(array $array, $to_remove): array +{ + $array = array_unique($array); + $a2 = []; + foreach ($array as $existing) { + if ($existing != $to_remove) { + $a2[] = $existing; + } + } + return $a2; } /** @@ -22,31 +23,34 @@ function array_remove(array $array, $to_remove): array { * * Also removes duplicate values from the array. */ -function array_add(array $array, $element): array { - // Could we just use array_push() ? - // http://www.php.net/manual/en/function.array-push.php - $array[] = $element; - $array = array_unique($array); - return $array; +function array_add(array $array, $element): array +{ + // Could we just use array_push() ? + // http://www.php.net/manual/en/function.array-push.php + $array[] = $element; + $array = array_unique($array); + return $array; } /** * Return the unique elements of an array, case insensitively */ -function array_iunique(array $array): array { - $ok = array(); - foreach($array as $element) { - $found = false; - foreach($ok as $existing) { - if(strtolower($element) == strtolower($existing)) { - $found = true; break; - } - } - if(!$found) { - $ok[] = $element; - } - } - return $ok; +function array_iunique(array $array): array +{ + $ok = []; + foreach ($array as $element) { + $found = false; + foreach ($ok as $existing) { + if (strtolower($element) == strtolower($existing)) { + $found = true; + break; + } + } + if (!$found) { + $ok[] = $element; + } + } + return $ok; } /** @@ -54,17 +58,18 @@ function array_iunique(array $array): array { * * from http://uk.php.net/network */ -function ip_in_range(string $IP, string $CIDR): bool { - list ($net, $mask) = explode("/", $CIDR); +function ip_in_range(string $IP, string $CIDR): bool +{ + list($net, $mask) = explode("/", $CIDR); - $ip_net = ip2long ($net); - $ip_mask = ~((1 << (32 - $mask)) - 1); + $ip_net = ip2long($net); + $ip_mask = ~((1 << (32 - $mask)) - 1); - $ip_ip = ip2long ($IP); + $ip_ip = ip2long($IP); - $ip_ip_net = $ip_ip & $ip_mask; + $ip_ip_net = $ip_ip & $ip_mask; - return ($ip_ip_net == $ip_net); + return ($ip_ip_net == $ip_net); } /** @@ -73,42 +78,38 @@ function ip_in_range(string $IP, string $CIDR): bool { * from a patch by Christian Walde; only intended for use in the * "extension manager" extension, but it seems to fit better here */ -function deltree(string $f) { - //Because Windows (I know, bad excuse) - if(PHP_OS === 'WINNT') { - $real = realpath($f); - $path = realpath('./').'\\'.str_replace('/', '\\', $f); - if($path != $real) { - rmdir($path); - } - else { - foreach(glob($f.'/*') as $sf) { - if (is_dir($sf) && !is_link($sf)) { - deltree($sf); - } - else { - unlink($sf); - } - } - rmdir($f); - } - } - else { - if (is_link($f)) { - unlink($f); - } - else if(is_dir($f)) { - foreach(glob($f.'/*') as $sf) { - if (is_dir($sf) && !is_link($sf)) { - deltree($sf); - } - else { - unlink($sf); - } - } - rmdir($f); - } - } +function deltree(string $f) +{ + //Because Windows (I know, bad excuse) + if (PHP_OS === 'WINNT') { + $real = realpath($f); + $path = realpath('./').'\\'.str_replace('/', '\\', $f); + if ($path != $real) { + rmdir($path); + } else { + foreach (glob($f.'/*') as $sf) { + if (is_dir($sf) && !is_link($sf)) { + deltree($sf); + } else { + unlink($sf); + } + } + rmdir($f); + } + } else { + if (is_link($f)) { + unlink($f); + } elseif (is_dir($f)) { + foreach (glob($f.'/*') as $sf) { + if (is_dir($sf) && !is_link($sf)) { + deltree($sf); + } else { + unlink($sf); + } + } + rmdir($f); + } + } } /** @@ -116,149 +117,154 @@ function deltree(string $f) { * * from a comment on http://uk.php.net/copy */ -function full_copy(string $source, string $target) { - if(is_dir($source)) { - @mkdir($target); +function full_copy(string $source, string $target) +{ + if (is_dir($source)) { + @mkdir($target); - $d = dir($source); + $d = dir($source); - while(FALSE !== ($entry = $d->read())) { - if($entry == '.' || $entry == '..') { - continue; - } + while (false !== ($entry = $d->read())) { + if ($entry == '.' || $entry == '..') { + continue; + } - $Entry = $source . '/' . $entry; - if(is_dir($Entry)) { - full_copy($Entry, $target . '/' . $entry); - continue; - } - copy($Entry, $target . '/' . $entry); - } - $d->close(); - } - else { - copy($source, $target); - } + $Entry = $source . '/' . $entry; + if (is_dir($Entry)) { + full_copy($Entry, $target . '/' . $entry); + continue; + } + copy($Entry, $target . '/' . $entry); + } + $d->close(); + } else { + copy($source, $target); + } } /** * Return a list of all the regular files in a directory and subdirectories */ -function list_files(string $base, string $_sub_dir=""): array { - assert(is_dir($base)); +function list_files(string $base, string $_sub_dir=""): array +{ + assert(is_dir($base)); - $file_list = array(); + $file_list = []; - $files = array(); - $dir = opendir("$base/$_sub_dir"); - while($f = readdir($dir)) { - $files[] = $f; - } - closedir($dir); - sort($files); + $files = []; + $dir = opendir("$base/$_sub_dir"); + while ($f = readdir($dir)) { + $files[] = $f; + } + closedir($dir); + sort($files); - foreach($files as $filename) { - $full_path = "$base/$_sub_dir/$filename"; + foreach ($files as $filename) { + $full_path = "$base/$_sub_dir/$filename"; - if(is_link($full_path)) { - // ignore - } - else if(is_dir($full_path)) { - if(!($filename == "." || $filename == "..")) { - //subdirectory found - $file_list = array_merge( - $file_list, - list_files($base, "$_sub_dir/$filename") - ); - } - } - else { - $full_path = str_replace("//", "/", $full_path); - $file_list[] = $full_path; - } - } + if (is_link($full_path)) { + // ignore + } elseif (is_dir($full_path)) { + if (!($filename == "." || $filename == "..")) { + //subdirectory found + $file_list = array_merge( + $file_list, + list_files($base, "$_sub_dir/$filename") + ); + } + } else { + $full_path = str_replace("//", "/", $full_path); + $file_list[] = $full_path; + } + } - return $file_list; + return $file_list; } if (!function_exists('http_parse_headers')) { #http://www.php.net/manual/en/function.http-parse-headers.php#112917 - /** - * #return string[] - */ - function http_parse_headers (string $raw_headers): array { - $headers = array(); // $headers = []; + /** + * #return string[] + */ + function http_parse_headers(string $raw_headers): array + { + $headers = []; // $headers = []; - foreach (explode("\n", $raw_headers) as $i => $h) { - $h = explode(':', $h, 2); + foreach (explode("\n", $raw_headers) as $i => $h) { + $h = explode(':', $h, 2); - if (isset($h[1])){ - if(!isset($headers[$h[0]])){ - $headers[$h[0]] = trim($h[1]); - }else if(is_array($headers[$h[0]])){ - $tmp = array_merge($headers[$h[0]],array(trim($h[1]))); - $headers[$h[0]] = $tmp; - }else{ - $tmp = array_merge(array($headers[$h[0]]),array(trim($h[1]))); - $headers[$h[0]] = $tmp; - } - } - } - return $headers; - } + if (isset($h[1])) { + if (!isset($headers[$h[0]])) { + $headers[$h[0]] = trim($h[1]); + } elseif (is_array($headers[$h[0]])) { + $tmp = array_merge($headers[$h[0]], [trim($h[1])]); + $headers[$h[0]] = $tmp; + } else { + $tmp = array_merge([$headers[$h[0]]], [trim($h[1])]); + $headers[$h[0]] = $tmp; + } + } + } + return $headers; + } } /** * HTTP Headers can sometimes be lowercase which will cause issues. * In cases like these, we need to make sure to check for them if the camelcase version does not exist. */ -function findHeader(array $headers, string $name): ?string { - if (!is_array($headers)) { - return null; - } +function findHeader(array $headers, string $name): ?string +{ + if (!is_array($headers)) { + return null; + } - $header = null; + $header = null; - if(array_key_exists($name, $headers)) { - $header = $headers[$name]; - } else { - $headers = array_change_key_case($headers); // convert all to lower case. - $lc_name = strtolower($name); + if (array_key_exists($name, $headers)) { + $header = $headers[$name]; + } else { + $headers = array_change_key_case($headers); // convert all to lower case. + $lc_name = strtolower($name); - if(array_key_exists($lc_name, $headers)) { - $header = $headers[$lc_name]; - } - } + if (array_key_exists($lc_name, $headers)) { + $header = $headers[$lc_name]; + } + } - return $header; + return $header; } if (!function_exists('mb_strlen')) { - // TODO: we should warn the admin that they are missing multibyte support - function mb_strlen($str, $encoding) { - return strlen($str); - } - function mb_internal_encoding($encoding) {} - function mb_strtolower($str) { - return strtolower($str); - } + // TODO: we should warn the admin that they are missing multibyte support + function mb_strlen($str, $encoding) + { + return strlen($str); + } + function mb_internal_encoding($encoding) + { + } + function mb_strtolower($str) + { + return strtolower($str); + } } const MIME_TYPE_MAP = [ - 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', - 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon', - 'swf' => 'application/x-shockwave-flash', 'video/x-flv' => 'flv', - 'svg' => 'image/svg+xml', 'pdf' => 'application/pdf', - 'zip' => 'application/zip', 'gz' => 'application/x-gzip', - 'tar' => 'application/x-tar', 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', 'txt' => 'text/plain', - 'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', - 'css' => 'text/css', 'js' => 'text/javascript', - 'xml' => 'text/xml', 'xsl' => 'application/xsl+xml', - 'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav', - 'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', - 'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php', - 'mp4' => 'video/mp4', 'ogv' => 'video/ogg', 'webm' => 'video/webm' + 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', + 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon', + 'swf' => 'application/x-shockwave-flash', 'video/x-flv' => 'flv', + 'svg' => 'image/svg+xml', 'pdf' => 'application/pdf', + 'zip' => 'application/zip', 'gz' => 'application/x-gzip', + 'tar' => 'application/x-tar', 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', 'txt' => 'text/plain', + 'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', + 'css' => 'text/css', 'js' => 'text/javascript', + 'xml' => 'text/xml', 'xsl' => 'application/xsl+xml', + 'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav', + 'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', + 'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php', + 'mp4' => 'video/mp4', 'ogv' => 'video/ogg', 'webm' => 'video/webm' ]; /** @@ -268,64 +274,72 @@ const MIME_TYPE_MAP = [ * from the "Amazon S3 PHP class" which is Copyright (c) 2008, Donovan Schönknecht * and released under the 'Simplified BSD License'. */ -function getMimeType(string $file, string $ext=""): string { - // Static extension lookup - $ext = strtolower($ext); +function getMimeType(string $file, string $ext=""): string +{ + // Static extension lookup + $ext = strtolower($ext); - if (array_key_exists($ext, MIME_TYPE_MAP)) { return MIME_TYPE_MAP[$ext]; } + if (array_key_exists($ext, MIME_TYPE_MAP)) { + return MIME_TYPE_MAP[$ext]; + } - $type = false; - // Fileinfo documentation says fileinfo_open() will use the - // MAGIC env var for the magic file - if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) && - ($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) - { - if (($type = finfo_file($finfo, $file)) !== false) - { - // Remove the charset and grab the last content-type - $type = explode(' ', str_replace('; charset=', ';charset=', $type)); - $type = array_pop($type); - $type = explode(';', $type); - $type = trim(array_shift($type)); - } - finfo_close($finfo); + $type = false; + // Fileinfo documentation says fileinfo_open() will use the + // MAGIC env var for the magic file + if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) && + ($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) { + if (($type = finfo_file($finfo, $file)) !== false) { + // Remove the charset and grab the last content-type + $type = explode(' ', str_replace('; charset=', ';charset=', $type)); + $type = array_pop($type); + $type = explode(';', $type); + $type = trim(array_shift($type)); + } + finfo_close($finfo); - // If anyone is still using mime_content_type() - } elseif (function_exists('mime_content_type')) - $type = trim(mime_content_type($file)); + // If anyone is still using mime_content_type() + } elseif (function_exists('mime_content_type')) { + $type = trim(mime_content_type($file)); + } - if ($type !== false && strlen($type) > 0) return $type; + if ($type !== false && strlen($type) > 0) { + return $type; + } - return 'application/octet-stream'; + return 'application/octet-stream'; } -function getExtension(?string $mime_type): ?string { - if(empty($mime_type)){ - return null; - } +function getExtension(?string $mime_type): ?string +{ + if (empty($mime_type)) { + return null; + } - $ext = array_search($mime_type, MIME_TYPE_MAP); - return ($ext ? $ext : null); + $ext = array_search($mime_type, MIME_TYPE_MAP); + return ($ext ? $ext : null); } /** * Like glob, with support for matching very long patterns with braces. */ -function zglob(string $pattern): array { - $results = array(); - if(preg_match('/(.*)\{(.*)\}(.*)/', $pattern, $matches)) { - $braced = explode(",", $matches[2]); - foreach($braced as $b) { - $sub_pattern = $matches[1].$b.$matches[3]; - $results = array_merge($results, zglob($sub_pattern)); - } - return $results; - } - else { - $r = glob($pattern); - if($r) return $r; - else return array(); - } +function zglob(string $pattern): array +{ + $results = []; + if (preg_match('/(.*)\{(.*)\}(.*)/', $pattern, $matches)) { + $braced = explode(",", $matches[2]); + foreach ($braced as $b) { + $sub_pattern = $matches[1].$b.$matches[3]; + $results = array_merge($results, zglob($sub_pattern)); + } + return $results; + } else { + $r = glob($pattern); + if ($r) { + return $r; + } else { + return []; + } + } } /** @@ -336,33 +350,38 @@ function zglob(string $pattern): array { * * PHP really, really sucks. */ -function get_base_href(): string { - if(defined("BASE_HREF")) return BASE_HREF; - $possible_vars = array('SCRIPT_NAME', 'PHP_SELF', 'PATH_INFO', 'ORIG_PATH_INFO'); - $ok_var = null; - foreach($possible_vars as $var) { - if(isset($_SERVER[$var]) && substr($_SERVER[$var], -4) === '.php') { - $ok_var = $_SERVER[$var]; - break; - } - } - assert(!empty($ok_var)); - $dir = dirname($ok_var); - $dir = str_replace("\\", "/", $dir); - $dir = str_replace("//", "/", $dir); - $dir = rtrim($dir, "/"); - return $dir; +function get_base_href(): string +{ + if (defined("BASE_HREF")) { + return BASE_HREF; + } + $possible_vars = ['SCRIPT_NAME', 'PHP_SELF', 'PATH_INFO', 'ORIG_PATH_INFO']; + $ok_var = null; + foreach ($possible_vars as $var) { + if (isset($_SERVER[$var]) && substr($_SERVER[$var], -4) === '.php') { + $ok_var = $_SERVER[$var]; + break; + } + } + assert(!empty($ok_var)); + $dir = dirname($ok_var); + $dir = str_replace("\\", "/", $dir); + $dir = str_replace("//", "/", $dir); + $dir = rtrim($dir, "/"); + return $dir; } -function startsWith(string $haystack, string $needle): bool { - $length = strlen($needle); - return (substr($haystack, 0, $length) === $needle); +function startsWith(string $haystack, string $needle): bool +{ + $length = strlen($needle); + return (substr($haystack, 0, $length) === $needle); } -function endsWith(string $haystack, string $needle): bool { - $length = strlen($needle); - $start = $length * -1; //negative - return (substr($haystack, $start) === $needle); +function endsWith(string $haystack, string $needle): bool +{ + $length = strlen($needle); + $start = $length * -1; //negative + return (substr($haystack, $start) === $needle); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ @@ -372,323 +391,333 @@ function endsWith(string $haystack, string $needle): bool { /** * Make some data safe for printing into HTML */ -function html_escape(string $input): string { - return htmlentities($input, ENT_QUOTES, "UTF-8"); +function html_escape(string $input): string +{ + return htmlentities($input, ENT_QUOTES, "UTF-8"); } /** * Unescape data that was made safe for printing into HTML */ -function html_unescape(string $input): string { - return html_entity_decode($input, ENT_QUOTES, "UTF-8"); +function html_unescape(string $input): string +{ + return html_entity_decode($input, ENT_QUOTES, "UTF-8"); } /** * Make sure some data is safe to be used in integer context */ -function int_escape(string $input): int { - /* - Side note, Casting to an integer is FASTER than using intval. - http://hakre.wordpress.com/2010/05/13/php-casting-vs-intval/ - */ - return (int)$input; +function int_escape(string $input): int +{ + /* + Side note, Casting to an integer is FASTER than using intval. + http://hakre.wordpress.com/2010/05/13/php-casting-vs-intval/ + */ + return (int)$input; } /** * Make sure some data is safe to be used in URL context */ -function url_escape(string $input): string { - /* - Shish: I have a feeling that these three lines are important, possibly for searching for tags with slashes in them like fate/stay_night - green-ponies: indeed~ +function url_escape(string $input): string +{ + /* + Shish: I have a feeling that these three lines are important, possibly for searching for tags with slashes in them like fate/stay_night + green-ponies: indeed~ - $input = str_replace('^', '^^', $input); - $input = str_replace('/', '^s', $input); - $input = str_replace('\\', '^b', $input); + $input = str_replace('^', '^^', $input); + $input = str_replace('/', '^s', $input); + $input = str_replace('\\', '^b', $input); - /* The function idn_to_ascii is used to support Unicode domains / URLs as well. - See here for more: http://php.net/manual/en/function.filter-var.php - However, it is only supported by PHP version 5.3 and up + /* The function idn_to_ascii is used to support Unicode domains / URLs as well. + See here for more: http://php.net/manual/en/function.filter-var.php + However, it is only supported by PHP version 5.3 and up - if (function_exists('idn_to_ascii')) { - return filter_var(idn_to_ascii($input), FILTER_SANITIZE_URL); - } else { - return filter_var($input, FILTER_SANITIZE_URL); - } - */ - if(is_null($input)) { - return ""; - } - $input = str_replace('^', '^^', $input); - $input = str_replace('/', '^s', $input); - $input = str_replace('\\', '^b', $input); - $input = rawurlencode($input); - return $input; + if (function_exists('idn_to_ascii')) { + return filter_var(idn_to_ascii($input), FILTER_SANITIZE_URL); + } else { + return filter_var($input, FILTER_SANITIZE_URL); + } + */ + if (is_null($input)) { + return ""; + } + $input = str_replace('^', '^^', $input); + $input = str_replace('/', '^s', $input); + $input = str_replace('\\', '^b', $input); + $input = rawurlencode($input); + return $input; } /** * Make sure some data is safe to be used in SQL context */ -function sql_escape(string $input): string { - global $database; - return $database->escape($input); +function sql_escape(string $input): string +{ + global $database; + return $database->escape($input); } /** * Turn all manner of HTML / INI / JS / DB booleans into a PHP one */ -function bool_escape($input): bool { - /* - Sometimes, I don't like PHP -- this, is one of those times... - "a boolean FALSE is not considered a valid boolean value by this function." - Yay for Got'chas! - http://php.net/manual/en/filter.filters.validate.php - */ - if (is_bool($input)) { - return $input; - } else if (is_numeric($input)) { - return ($input === 1); - } else { - $value = filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); - if (!is_null($value)) { - return $value; - } else { - $input = strtolower( trim($input) ); - return ( - $input === "y" || - $input === "yes" || - $input === "t" || - $input === "true" || - $input === "on" || - $input === "1" - ); - } - } +function bool_escape($input): bool +{ + /* + Sometimes, I don't like PHP -- this, is one of those times... + "a boolean FALSE is not considered a valid boolean value by this function." + Yay for Got'chas! + http://php.net/manual/en/filter.filters.validate.php + */ + if (is_bool($input)) { + return $input; + } elseif (is_numeric($input)) { + return ($input === 1); + } else { + $value = filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + if (!is_null($value)) { + return $value; + } else { + $input = strtolower(trim($input)); + return ( + $input === "y" || + $input === "yes" || + $input === "t" || + $input === "true" || + $input === "on" || + $input === "1" + ); + } + } } /** * Some functions require a callback function for escaping, * but we might not want to alter the data */ -function no_escape(string $input): string { - return $input; +function no_escape(string $input): string +{ + return $input; } -function clamp(int $val, int $min=null, int $max=null): int { - if(!is_numeric($val) || (!is_null($min) && $val < $min)) { - $val = $min; - } - if(!is_null($max) && $val > $max) { - $val = $max; - } - if(!is_null($min) && !is_null($max)) { - assert($val >= $min && $val <= $max, "$min <= $val <= $max"); - } - return $val; +function clamp(int $val, int $min=null, int $max=null): int +{ + if (!is_numeric($val) || (!is_null($min) && $val < $min)) { + $val = $min; + } + if (!is_null($max) && $val > $max) { + $val = $max; + } + if (!is_null($min) && !is_null($max)) { + assert($val >= $min && $val <= $max, "$min <= $val <= $max"); + } + return $val; } -function xml_tag(string $name, array $attrs=array(), array $children=array()): string { - $xml = "<$name "; - foreach($attrs as $k => $v) { - $xv = str_replace(''', ''', htmlspecialchars($v, ENT_QUOTES)); - $xml .= "$k=\"$xv\" "; - } - if(count($children) > 0) { - $xml .= ">\n"; - foreach($children as $child) { - $xml .= xml_tag($child); - } - $xml .= "\n"; - } - else { - $xml .= "/>\n"; - } - return $xml; +function xml_tag(string $name, array $attrs=[], array $children=[]): string +{ + $xml = "<$name "; + foreach ($attrs as $k => $v) { + $xv = str_replace(''', ''', htmlspecialchars($v, ENT_QUOTES)); + $xml .= "$k=\"$xv\" "; + } + if (count($children) > 0) { + $xml .= ">\n"; + foreach ($children as $child) { + $xml .= xml_tag($child); + } + $xml .= "\n"; + } else { + $xml .= "/>\n"; + } + return $xml; } /** * Original PHP code by Chirp Internet: www.chirp.com.au * Please acknowledge use of this code by including this header. */ -function truncate(string $string, int $limit, string $break=" ", string $pad="..."): string{ - // return with no change if string is shorter than $limit - if(strlen($string) <= $limit) return $string; +function truncate(string $string, int $limit, string $break=" ", string $pad="..."): string +{ + // return with no change if string is shorter than $limit + if (strlen($string) <= $limit) { + return $string; + } - // is $break present between $limit and the end of the string? - if(false !== ($breakpoint = strpos($string, $break, $limit))) { - if($breakpoint < strlen($string) - 1) { - $string = substr($string, 0, $breakpoint) . $pad; - } - } + // is $break present between $limit and the end of the string? + if (false !== ($breakpoint = strpos($string, $break, $limit))) { + if ($breakpoint < strlen($string) - 1) { + $string = substr($string, 0, $breakpoint) . $pad; + } + } - return $string; + return $string; } /** * Turn a human readable filesize into an integer, eg 1KB -> 1024 */ -function parse_shorthand_int(string $limit): int { - if(preg_match('/^([\d\.]+)([gmk])?b?$/i', (string)$limit, $m)) { - $value = $m[1]; - if (isset($m[2])) { - switch(strtolower($m[2])) { - /** @noinspection PhpMissingBreakStatementInspection */ - case 'g': $value *= 1024; // fall through - /** @noinspection PhpMissingBreakStatementInspection */ - case 'm': $value *= 1024; // fall through - /** @noinspection PhpMissingBreakStatementInspection */ - case 'k': $value *= 1024; break; - default: $value = -1; - } - } - return (int)$value; - } else { - return -1; - } +function parse_shorthand_int(string $limit): int +{ + if (preg_match('/^([\d\.]+)([gmk])?b?$/i', (string)$limit, $m)) { + $value = $m[1]; + if (isset($m[2])) { + switch (strtolower($m[2])) { + /** @noinspection PhpMissingBreakStatementInspection */ + case 'g': $value *= 1024; // fall through + /** @noinspection PhpMissingBreakStatementInspection */ + // no break + case 'm': $value *= 1024; // fall through + /** @noinspection PhpMissingBreakStatementInspection */ + // no break + case 'k': $value *= 1024; break; + default: $value = -1; + } + } + return (int)$value; + } else { + return -1; + } } /** * Turn an integer into a human readable filesize, eg 1024 -> 1KB */ -function to_shorthand_int(int $int): string { - assert($int >= 0); +function to_shorthand_int(int $int): string +{ + assert($int >= 0); - if($int >= pow(1024, 3)) { - return sprintf("%.1fGB", $int / pow(1024, 3)); - } - else if($int >= pow(1024, 2)) { - return sprintf("%.1fMB", $int / pow(1024, 2)); - } - else if($int >= 1024) { - return sprintf("%.1fKB", $int / 1024); - } - else { - return (string)$int; - } + if ($int >= pow(1024, 3)) { + return sprintf("%.1fGB", $int / pow(1024, 3)); + } elseif ($int >= pow(1024, 2)) { + return sprintf("%.1fMB", $int / pow(1024, 2)); + } elseif ($int >= 1024) { + return sprintf("%.1fKB", $int / 1024); + } else { + return (string)$int; + } } /** * Turn a date into a time, a date, an "X minutes ago...", etc */ -function autodate(string $date, bool $html=true): string { - $cpu = date('c', strtotime($date)); - $hum = date('F j, Y; H:i', strtotime($date)); - return ($html ? "" : $hum); +function autodate(string $date, bool $html=true): string +{ + $cpu = date('c', strtotime($date)); + $hum = date('F j, Y; H:i', strtotime($date)); + return ($html ? "" : $hum); } /** * Check if a given string is a valid date-time. ( Format: yyyy-mm-dd hh:mm:ss ) */ -function isValidDateTime(string $dateTime): bool { - if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) { - if (checkdate($matches[2], $matches[3], $matches[1])) { - return true; - } - } +function isValidDateTime(string $dateTime): bool +{ + if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) { + if (checkdate($matches[2], $matches[3], $matches[1])) { + return true; + } + } - return false; + return false; } /** * Check if a given string is a valid date. ( Format: yyyy-mm-dd ) */ -function isValidDate(string $date): bool { - if (preg_match("/^(\d{4})-(\d{2})-(\d{2})$/", $date, $matches)) { - // checkdate wants (month, day, year) - if (checkdate($matches[2], $matches[3], $matches[1])) { - return true; - } - } +function isValidDate(string $date): bool +{ + if (preg_match("/^(\d{4})-(\d{2})-(\d{2})$/", $date, $matches)) { + // checkdate wants (month, day, year) + if (checkdate($matches[2], $matches[3], $matches[1])) { + return true; + } + } - return false; + return false; } -function validate_input(array $inputs): array { - $outputs = array(); +function validate_input(array $inputs): array +{ + $outputs = []; - foreach($inputs as $key => $validations) { - $flags = explode(',', $validations); + foreach ($inputs as $key => $validations) { + $flags = explode(',', $validations); - if(in_array('bool', $flags) && !isset($_POST[$key])) { - $_POST[$key] = 'off'; - } + if (in_array('bool', $flags) && !isset($_POST[$key])) { + $_POST[$key] = 'off'; + } - if(in_array('optional', $flags)) { - if(!isset($_POST[$key]) || trim($_POST[$key]) == "") { - $outputs[$key] = null; - continue; - } - } - if(!isset($_POST[$key]) || trim($_POST[$key]) == "") { - throw new InvalidInput("Input '$key' not set"); - } + if (in_array('optional', $flags)) { + if (!isset($_POST[$key]) || trim($_POST[$key]) == "") { + $outputs[$key] = null; + continue; + } + } + if (!isset($_POST[$key]) || trim($_POST[$key]) == "") { + throw new InvalidInput("Input '$key' not set"); + } - $value = trim($_POST[$key]); + $value = trim($_POST[$key]); - if(in_array('user_id', $flags)) { - $id = int_escape($value); - if(in_array('exists', $flags)) { - if(is_null(User::by_id($id))) { - throw new InvalidInput("User #$id does not exist"); - } - } - $outputs[$key] = $id; - } - else if(in_array('user_name', $flags)) { - if(strlen($value) < 1) { - throw new InvalidInput("Username must be at least 1 character"); - } - else if(!preg_match('/^[a-zA-Z0-9-_]+$/', $value)) { - throw new InvalidInput( - "Username contains invalid characters. Allowed characters are ". - "letters, numbers, dash, and underscore"); - } - $outputs[$key] = $value; - } - else if(in_array('user_class', $flags)) { - global $_shm_user_classes; - if(!array_key_exists($value, $_shm_user_classes)) { - throw new InvalidInput("Invalid user class: ".html_escape($value)); - } - $outputs[$key] = $value; - } - else if(in_array('email', $flags)) { - $outputs[$key] = trim($value); - } - else if(in_array('password', $flags)) { - $outputs[$key] = $value; - } - else if(in_array('int', $flags)) { - $value = trim($value); - if(empty($value) || !is_numeric($value)) { - throw new InvalidInput("Invalid int: ".html_escape($value)); - } - $outputs[$key] = (int)$value; - } - else if(in_array('bool', $flags)) { - $outputs[$key] = bool_escape($value); - } - else if(in_array('string', $flags)) { - if(in_array('trim', $flags)) { - $value = trim($value); - } - if(in_array('lower', $flags)) { - $value = strtolower($value); - } - if(in_array('not-empty', $flags)) { - throw new InvalidInput("$key must not be blank"); - } - if(in_array('nullify', $flags)) { - if(empty($value)) $value = null; - } - $outputs[$key] = $value; - } - else { - throw new InvalidInput("Unknown validation '$validations'"); - } - } + if (in_array('user_id', $flags)) { + $id = int_escape($value); + if (in_array('exists', $flags)) { + if (is_null(User::by_id($id))) { + throw new InvalidInput("User #$id does not exist"); + } + } + $outputs[$key] = $id; + } elseif (in_array('user_name', $flags)) { + if (strlen($value) < 1) { + throw new InvalidInput("Username must be at least 1 character"); + } elseif (!preg_match('/^[a-zA-Z0-9-_]+$/', $value)) { + throw new InvalidInput( + "Username contains invalid characters. Allowed characters are ". + "letters, numbers, dash, and underscore" + ); + } + $outputs[$key] = $value; + } elseif (in_array('user_class', $flags)) { + global $_shm_user_classes; + if (!array_key_exists($value, $_shm_user_classes)) { + throw new InvalidInput("Invalid user class: ".html_escape($value)); + } + $outputs[$key] = $value; + } elseif (in_array('email', $flags)) { + $outputs[$key] = trim($value); + } elseif (in_array('password', $flags)) { + $outputs[$key] = $value; + } elseif (in_array('int', $flags)) { + $value = trim($value); + if (empty($value) || !is_numeric($value)) { + throw new InvalidInput("Invalid int: ".html_escape($value)); + } + $outputs[$key] = (int)$value; + } elseif (in_array('bool', $flags)) { + $outputs[$key] = bool_escape($value); + } elseif (in_array('string', $flags)) { + if (in_array('trim', $flags)) { + $value = trim($value); + } + if (in_array('lower', $flags)) { + $value = strtolower($value); + } + if (in_array('not-empty', $flags)) { + throw new InvalidInput("$key must not be blank"); + } + if (in_array('nullify', $flags)) { + if (empty($value)) { + $value = null; + } + } + $outputs[$key] = $value; + } else { + throw new InvalidInput("Unknown validation '$validations'"); + } + } - return $outputs; + return $outputs; } diff --git a/core/send_event.php b/core/send_event.php index 55328935..52d6dadf 100644 --- a/core/send_event.php +++ b/core/send_event.php @@ -5,90 +5,94 @@ /** @private */ global $_shm_event_listeners; -$_shm_event_listeners = array(); +$_shm_event_listeners = []; -function _load_event_listeners() { - global $_shm_event_listeners, $_shm_ctx; +function _load_event_listeners() +{ + global $_shm_event_listeners, $_shm_ctx; - $_shm_ctx->log_start("Loading extensions"); + $_shm_ctx->log_start("Loading extensions"); - $cache_path = data_path("cache/shm_event_listeners.php"); - if(COMPILE_ELS && file_exists($cache_path)) { - require_once($cache_path); - } - else { - _set_event_listeners(); + $cache_path = data_path("cache/shm_event_listeners.php"); + if (COMPILE_ELS && file_exists($cache_path)) { + require_once($cache_path); + } else { + _set_event_listeners(); - if(COMPILE_ELS) { - _dump_event_listeners($_shm_event_listeners, $cache_path); - } - } + if (COMPILE_ELS) { + _dump_event_listeners($_shm_event_listeners, $cache_path); + } + } - $_shm_ctx->log_endok(); + $_shm_ctx->log_endok(); } -function _set_event_listeners() { - global $_shm_event_listeners; - $_shm_event_listeners = array(); +function _set_event_listeners() +{ + global $_shm_event_listeners; + $_shm_event_listeners = []; - foreach(get_declared_classes() as $class) { - $rclass = new ReflectionClass($class); - if($rclass->isAbstract()) { - // don't do anything - } - elseif(is_subclass_of($class, "Extension")) { - /** @var Extension $extension */ - $extension = new $class(); + foreach (get_declared_classes() as $class) { + $rclass = new ReflectionClass($class); + if ($rclass->isAbstract()) { + // don't do anything + } elseif (is_subclass_of($class, "Extension")) { + /** @var Extension $extension */ + $extension = new $class(); - // skip extensions which don't support our current database - if(!$extension->is_live()) continue; + // skip extensions which don't support our current database + if (!$extension->is_live()) { + continue; + } - foreach(get_class_methods($extension) as $method) { - if(substr($method, 0, 2) == "on") { - $event = substr($method, 2) . "Event"; - $pos = $extension->get_priority() * 100; - while(isset($_shm_event_listeners[$event][$pos])) { - $pos += 1; - } - $_shm_event_listeners[$event][$pos] = $extension; - } - } - } - } + foreach (get_class_methods($extension) as $method) { + if (substr($method, 0, 2) == "on") { + $event = substr($method, 2) . "Event"; + $pos = $extension->get_priority() * 100; + while (isset($_shm_event_listeners[$event][$pos])) { + $pos += 1; + } + $_shm_event_listeners[$event][$pos] = $extension; + } + } + } + } } -function _dump_event_listeners(array $event_listeners, string $path): void { - $p = "<"."?php\n"; +function _dump_event_listeners(array $event_listeners, string $path): void +{ + $p = "<"."?php\n"; - foreach(get_declared_classes() as $class) { - $rclass = new ReflectionClass($class); - if($rclass->isAbstract()) {} - elseif(is_subclass_of($class, "Extension")) { - $p .= "\$$class = new $class(); "; - } - } + foreach (get_declared_classes() as $class) { + $rclass = new ReflectionClass($class); + if ($rclass->isAbstract()) { + } elseif (is_subclass_of($class, "Extension")) { + $p .= "\$$class = new $class(); "; + } + } - $p .= "\$_shm_event_listeners = array(\n"; - foreach($event_listeners as $event => $listeners) { - $p .= "\t'$event' => array(\n"; - foreach($listeners as $id => $listener) { - $p .= "\t\t$id => \$".get_class($listener).",\n"; - } - $p .= "\t),\n"; - } - $p .= ");\n"; + $p .= "\$_shm_event_listeners = array(\n"; + foreach ($event_listeners as $event => $listeners) { + $p .= "\t'$event' => array(\n"; + foreach ($listeners as $id => $listener) { + $p .= "\t\t$id => \$".get_class($listener).",\n"; + } + $p .= "\t),\n"; + } + $p .= ");\n"; - $p .= "?".">"; - file_put_contents($path, $p); + $p .= "?".">"; + file_put_contents($path, $p); } -function ext_is_live(string $ext_name): bool { - if (class_exists($ext_name)) { - /** @var Extension $ext */ - $ext = new $ext_name(); - return $ext->is_live(); - } - return false; +function ext_is_live(string $ext_name): bool +{ + if (class_exists($ext_name)) { + /** @var Extension $ext */ + $ext = new $ext_name(); + return $ext->is_live(); + } + return false; } @@ -99,26 +103,37 @@ $_shm_event_count = 0; /** * Send an event to all registered Extensions. */ -function send_event(Event $event): void { - global $_shm_event_listeners, $_shm_event_count, $_shm_ctx; - if(!isset($_shm_event_listeners[get_class($event)])) return; - $method_name = "on".str_replace("Event", "", get_class($event)); +function send_event(Event $event): void +{ + global $_shm_event_listeners, $_shm_event_count, $_shm_ctx; + if (!isset($_shm_event_listeners[get_class($event)])) { + return; + } + $method_name = "on".str_replace("Event", "", get_class($event)); - // send_event() is performance sensitive, and with the number - // of times context gets called the time starts to add up - $ctx_enabled = constant('CONTEXT'); + // send_event() is performance sensitive, and with the number + // of times context gets called the time starts to add up + $ctx_enabled = constant('CONTEXT'); - if($ctx_enabled) $_shm_ctx->log_start(get_class($event)); - // SHIT: http://bugs.php.net/bug.php?id=35106 - $my_event_listeners = $_shm_event_listeners[get_class($event)]; - ksort($my_event_listeners); - foreach($my_event_listeners as $listener) { - if($ctx_enabled) $_shm_ctx->log_start(get_class($listener)); - if(method_exists($listener, $method_name)) { - $listener->$method_name($event); - } - if($ctx_enabled) $_shm_ctx->log_endok(); - } - $_shm_event_count++; - if($ctx_enabled) $_shm_ctx->log_endok(); + if ($ctx_enabled) { + $_shm_ctx->log_start(get_class($event)); + } + // SHIT: http://bugs.php.net/bug.php?id=35106 + $my_event_listeners = $_shm_event_listeners[get_class($event)]; + ksort($my_event_listeners); + foreach ($my_event_listeners as $listener) { + if ($ctx_enabled) { + $_shm_ctx->log_start(get_class($listener)); + } + if (method_exists($listener, $method_name)) { + $listener->$method_name($event); + } + if ($ctx_enabled) { + $_shm_ctx->log_endok(); + } + } + $_shm_event_count++; + if ($ctx_enabled) { + $_shm_ctx->log_endok(); + } } diff --git a/core/sys_config.php b/core/sys_config.php index 8c26f2a9..4c6d648e 100644 --- a/core/sys_config.php +++ b/core/sys_config.php @@ -19,7 +19,12 @@ * */ -function _d(string $name, $value) {if(!defined($name)) define($name, $value);} +function _d(string $name, $value) +{ + if (!defined($name)) { + define($name, $value); + } +} _d("DATABASE_DSN", null); // string PDO database connection details _d("DATABASE_KA", true); // string Keep database connection alive _d("CACHE_DSN", null); // string cache connection details @@ -50,5 +55,3 @@ _d("ENABLED_MODS", "imageboard"); */ _d("SCORE_VERSION", 'develop/'.VERSION); // string SCore version _d("ENABLED_EXTS", CORE_EXTS.",".EXTRA_EXTS); - - diff --git a/core/tests/polyfills.test.php b/core/tests/polyfills.test.php index c1797092..7aadec3d 100644 --- a/core/tests/polyfills.test.php +++ b/core/tests/polyfills.test.php @@ -1,43 +1,48 @@ assertEquals( - html_escape("Foo & "), - "Foo & <waffles>" - ); +class PolyfillsTest extends \PHPUnit\Framework\TestCase +{ + public function test_html_escape() + { + $this->assertEquals( + html_escape("Foo & "), + "Foo & <waffles>" + ); - $this->assertEquals( - html_unescape("Foo & <waffles>"), - "Foo & " - ); + $this->assertEquals( + html_unescape("Foo & <waffles>"), + "Foo & " + ); - $x = "Foo & <waffles>"; - $this->assertEquals(html_escape(html_unescape($x)), $x); - } + $x = "Foo & <waffles>"; + $this->assertEquals(html_escape(html_unescape($x)), $x); + } - public function test_int_escape() { - $this->assertEquals(int_escape(""), 0); - $this->assertEquals(int_escape("1"), 1); - $this->assertEquals(int_escape("-1"), -1); - $this->assertEquals(int_escape("-1.5"), -1); - } + public function test_int_escape() + { + $this->assertEquals(int_escape(""), 0); + $this->assertEquals(int_escape("1"), 1); + $this->assertEquals(int_escape("-1"), -1); + $this->assertEquals(int_escape("-1.5"), -1); + } - public function test_clamp() { - $this->assertEquals(clamp(0, 5, 10), 5); - $this->assertEquals(clamp(5, 5, 10), 5); - $this->assertEquals(clamp(7, 5, 10), 7); - $this->assertEquals(clamp(10, 5, 10), 10); - $this->assertEquals(clamp(15, 5, 10), 10); - } + public function test_clamp() + { + $this->assertEquals(clamp(0, 5, 10), 5); + $this->assertEquals(clamp(5, 5, 10), 5); + $this->assertEquals(clamp(7, 5, 10), 7); + $this->assertEquals(clamp(10, 5, 10), 10); + $this->assertEquals(clamp(15, 5, 10), 10); + } - public function test_shorthand_int() { - $this->assertEquals(to_shorthand_int(1231231231), "1.1GB"); + public function test_shorthand_int() + { + $this->assertEquals(to_shorthand_int(1231231231), "1.1GB"); - $this->assertEquals(parse_shorthand_int("foo"), -1); - $this->assertEquals(parse_shorthand_int("32M"), 33554432); - $this->assertEquals(parse_shorthand_int("43.4KB"), 44441); - $this->assertEquals(parse_shorthand_int("1231231231"), 1231231231); - } + $this->assertEquals(parse_shorthand_int("foo"), -1); + $this->assertEquals(parse_shorthand_int("32M"), 33554432); + $this->assertEquals(parse_shorthand_int("43.4KB"), 44441); + $this->assertEquals(parse_shorthand_int("1231231231"), 1231231231); + } } diff --git a/core/urls.php b/core/urls.php index 7185e839..e4fc0977 100644 --- a/core/urls.php +++ b/core/urls.php @@ -9,92 +9,94 @@ * * eg make_link("post/list") becomes "/v2/index.php?q=post/list" */ -function make_link(?string $page=null, ?string $query=null): string { - global $config; +function make_link(?string $page=null, ?string $query=null): string +{ + global $config; - if(is_null($page)) $page = $config->get_string('main_page'); + if (is_null($page)) { + $page = $config->get_string('main_page'); + } - if(!is_null(BASE_URL)) { - $base = BASE_URL; - } - elseif(NICE_URLS || $config->get_bool('nice_urls', false)) { - $base = str_replace('/'.basename($_SERVER["SCRIPT_FILENAME"]), "", $_SERVER["PHP_SELF"]); - } - else { - $base = "./".basename($_SERVER["SCRIPT_FILENAME"])."?q="; - } + if (!is_null(BASE_URL)) { + $base = BASE_URL; + } elseif (NICE_URLS || $config->get_bool('nice_urls', false)) { + $base = str_replace('/'.basename($_SERVER["SCRIPT_FILENAME"]), "", $_SERVER["PHP_SELF"]); + } else { + $base = "./".basename($_SERVER["SCRIPT_FILENAME"])."?q="; + } - if(is_null($query)) { - return str_replace("//", "/", $base.'/'.$page ); - } - else { - if(strpos($base, "?")) { - return $base .'/'. $page .'&'. $query; - } - else if(strpos($query, "#") === 0) { - return $base .'/'. $page . $query; - } - else { - return $base .'/'. $page .'?'. $query; - } - } + if (is_null($query)) { + return str_replace("//", "/", $base.'/'.$page); + } else { + if (strpos($base, "?")) { + return $base .'/'. $page .'&'. $query; + } elseif (strpos($query, "#") === 0) { + return $base .'/'. $page . $query; + } else { + return $base .'/'. $page .'?'. $query; + } + } } /** * Take the current URL and modify some parameters */ -function modify_current_url(array $changes): string { - return modify_url($_SERVER['QUERY_STRING'], $changes); +function modify_current_url(array $changes): string +{ + return modify_url($_SERVER['QUERY_STRING'], $changes); } -function modify_url(string $url, array $changes): string { - // SHIT: PHP is officially the worst web API ever because it does not - // have a built-in function to do this. +function modify_url(string $url, array $changes): string +{ + // SHIT: PHP is officially the worst web API ever because it does not + // have a built-in function to do this. - // SHIT: parse_str is magically retarded; not only is it a useless name, it also - // didn't return the parsed array, preferring to overwrite global variables with - // whatever data the user supplied. Thankfully, 4.0.3 added an extra option to - // give it an array to use... - $params = array(); - parse_str($url, $params); + // SHIT: parse_str is magically retarded; not only is it a useless name, it also + // didn't return the parsed array, preferring to overwrite global variables with + // whatever data the user supplied. Thankfully, 4.0.3 added an extra option to + // give it an array to use... + $params = []; + parse_str($url, $params); - if(isset($changes['q'])) { - $base = $changes['q']; - unset($changes['q']); - } - else { - $base = _get_query(); - } + if (isset($changes['q'])) { + $base = $changes['q']; + unset($changes['q']); + } else { + $base = _get_query(); + } - if(isset($params['q'])) { - unset($params['q']); - } + if (isset($params['q'])) { + unset($params['q']); + } - foreach($changes as $k => $v) { - if(is_null($v) and isset($params[$k])) unset($params[$k]); - $params[$k] = $v; - } + foreach ($changes as $k => $v) { + if (is_null($v) and isset($params[$k])) { + unset($params[$k]); + } + $params[$k] = $v; + } - return make_link($base, http_build_query($params)); + return make_link($base, http_build_query($params)); } /** * Turn a relative link into an absolute one, including hostname */ -function make_http(string $link): string { - if(strpos($link, "://") > 0) { - return $link; - } +function make_http(string $link): string +{ + if (strpos($link, "://") > 0) { + return $link; + } - if(strlen($link) > 0 && $link[0] != '/') { - $link = get_base_href() . '/' . $link; - } + if (strlen($link) > 0 && $link[0] != '/') { + $link = get_base_href() . '/' . $link; + } - $protocol = is_https_enabled() ? "https://" : "http://"; - $link = $protocol . $_SERVER["HTTP_HOST"] . $link; - $link = str_replace("/./", "/", $link); + $protocol = is_https_enabled() ? "https://" : "http://"; + $link = $protocol . $_SERVER["HTTP_HOST"] . $link; + $link = str_replace("/./", "/", $link); - return $link; + return $link; } diff --git a/core/user.php b/core/user.php index 68676738..ae3a0a5f 100644 --- a/core/user.php +++ b/core/user.php @@ -1,7 +1,8 @@ id = int_escape($row['id']); - $this->name = $row['name']; - $this->email = $row['email']; - $this->join_date = $row['joindate']; - $this->passhash = $row['pass']; + $this->id = int_escape($row['id']); + $this->name = $row['name']; + $this->email = $row['email']; + $this->join_date = $row['joindate']; + $this->passhash = $row['pass']; - if(array_key_exists($row["class"], $_shm_user_classes)) { - $this->class = $_shm_user_classes[$row["class"]]; - } - else { - throw new SCoreException("User '{$this->name}' has invalid class '{$row["class"]}'"); - } - } + if (array_key_exists($row["class"], $_shm_user_classes)) { + $this->class = $_shm_user_classes[$row["class"]]; + } else { + throw new SCoreException("User '{$this->name}' has invalid class '{$row["class"]}'"); + } + } - public static function by_session(string $name, string $session) { - global $config, $database; - $row = $database->cache->get("user-session:$name-$session"); - if(!$row) { - if($database->get_driver_name() === "mysql") { - $query = "SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess"; - } - else { - $query = "SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess"; - } - $row = $database->get_row($query, array("name"=>$name, "ip"=>get_session_ip($config), "sess"=>$session)); - $database->cache->set("user-session:$name-$session", $row, 600); - } - return is_null($row) ? null : new User($row); - } + public static function by_session(string $name, string $session) + { + global $config, $database; + $row = $database->cache->get("user-session:$name-$session"); + if (!$row) { + if ($database->get_driver_name() === "mysql") { + $query = "SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess"; + } else { + $query = "SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess"; + } + $row = $database->get_row($query, ["name"=>$name, "ip"=>get_session_ip($config), "sess"=>$session]); + $database->cache->set("user-session:$name-$session", $row, 600); + } + return is_null($row) ? null : new User($row); + } - public static function by_id(int $id) { - global $database; - if($id === 1) { - $cached = $database->cache->get('user-id:'.$id); - if($cached) return new User($cached); - } - $row = $database->get_row("SELECT * FROM users WHERE id = :id", array("id"=>$id)); - if($id === 1) $database->cache->set('user-id:'.$id, $row, 600); - return is_null($row) ? null : new User($row); - } + public static function by_id(int $id) + { + global $database; + if ($id === 1) { + $cached = $database->cache->get('user-id:'.$id); + if ($cached) { + return new User($cached); + } + } + $row = $database->get_row("SELECT * FROM users WHERE id = :id", ["id"=>$id]); + if ($id === 1) { + $database->cache->set('user-id:'.$id, $row, 600); + } + return is_null($row) ? null : new User($row); + } - public static function by_name(string $name) { - global $database; - $row = $database->get_row($database->scoreql_to_sql("SELECT * FROM users WHERE SCORE_STRNORM(name) = SCORE_STRNORM(:name)"), array("name"=>$name)); - return is_null($row) ? null : new User($row); - } + public static function by_name(string $name) + { + global $database; + $row = $database->get_row($database->scoreql_to_sql("SELECT * FROM users WHERE SCORE_STRNORM(name) = SCORE_STRNORM(:name)"), ["name"=>$name]); + return is_null($row) ? null : new User($row); + } - public static function by_name_and_pass(string $name, string $pass) { - $user = User::by_name($name); - if($user) { - if($user->passhash == md5(strtolower($name) . $pass)) { - log_info("core-user", "Migrating from md5 to bcrypt for ".html_escape($name)); - $user->set_password($pass); - } - if(password_verify($pass, $user->passhash)) { - log_info("core-user", "Logged in as ".html_escape($name)." ({$user->class->name})"); - return $user; - } - else { - log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid password)"); - } - } - else { - log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid username)"); - } - return null; - } + public static function by_name_and_pass(string $name, string $pass) + { + $user = User::by_name($name); + if ($user) { + if ($user->passhash == md5(strtolower($name) . $pass)) { + log_info("core-user", "Migrating from md5 to bcrypt for ".html_escape($name)); + $user->set_password($pass); + } + if (password_verify($pass, $user->passhash)) { + log_info("core-user", "Logged in as ".html_escape($name)." ({$user->class->name})"); + return $user; + } else { + log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid password)"); + } + } else { + log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid username)"); + } + return null; + } - /* useful user object functions start here */ + /* useful user object functions start here */ - public function can(string $ability): bool { - return $this->class->can($ability); - } + public function can(string $ability): bool + { + return $this->class->can($ability); + } - public function is_anonymous(): bool { - global $config; - return ($this->id === $config->get_int('anon_id')); - } + public function is_anonymous(): bool + { + global $config; + return ($this->id === $config->get_int('anon_id')); + } - public function is_logged_in(): bool { - global $config; - return ($this->id !== $config->get_int('anon_id')); - } + public function is_logged_in(): bool + { + global $config; + return ($this->id !== $config->get_int('anon_id')); + } - public function is_admin(): bool { - return ($this->class->name === "admin"); - } + public function is_admin(): bool + { + return ($this->class->name === "admin"); + } - public function set_class(string $class) { - global $database; - $database->Execute("UPDATE users SET class=:class WHERE id=:id", array("class"=>$class, "id"=>$this->id)); - log_info("core-user", 'Set class for '.$this->name.' to '.$class); - } + public function set_class(string $class) + { + global $database; + $database->Execute("UPDATE users SET class=:class WHERE id=:id", ["class"=>$class, "id"=>$this->id]); + log_info("core-user", 'Set class for '.$this->name.' to '.$class); + } - public function set_name(string $name) { - global $database; - if(User::by_name($name)) { - throw new Exception("Desired username is already in use"); - } - $old_name = $this->name; - $this->name = $name; - $database->Execute("UPDATE users SET name=:name WHERE id=:id", array("name"=>$this->name, "id"=>$this->id)); - log_info("core-user", "Changed username for {$old_name} to {$this->name}"); - } + public function set_name(string $name) + { + global $database; + if (User::by_name($name)) { + throw new Exception("Desired username is already in use"); + } + $old_name = $this->name; + $this->name = $name; + $database->Execute("UPDATE users SET name=:name WHERE id=:id", ["name"=>$this->name, "id"=>$this->id]); + log_info("core-user", "Changed username for {$old_name} to {$this->name}"); + } - public function set_password(string $password) { - global $database; - $hash = password_hash($password, PASSWORD_BCRYPT); - if(is_string($hash)) { - $this->passhash = $hash; - $database->Execute("UPDATE users SET pass=:hash WHERE id=:id", array("hash"=>$this->passhash, "id"=>$this->id)); - log_info("core-user", 'Set password for '.$this->name); - } - else { - throw new SCoreException("Failed to hash password"); - } - } + public function set_password(string $password) + { + global $database; + $hash = password_hash($password, PASSWORD_BCRYPT); + if (is_string($hash)) { + $this->passhash = $hash; + $database->Execute("UPDATE users SET pass=:hash WHERE id=:id", ["hash"=>$this->passhash, "id"=>$this->id]); + log_info("core-user", 'Set password for '.$this->name); + } else { + throw new SCoreException("Failed to hash password"); + } + } - public function set_email(string $address) { - global $database; - $database->Execute("UPDATE users SET email=:email WHERE id=:id", array("email"=>$address, "id"=>$this->id)); - log_info("core-user", 'Set email for '.$this->name); - } + public function set_email(string $address) + { + global $database; + $database->Execute("UPDATE users SET email=:email WHERE id=:id", ["email"=>$address, "id"=>$this->id]); + log_info("core-user", 'Set email for '.$this->name); + } - /** - * Get a snippet of HTML which will render the user's avatar, be that - * a local file, a remote file, a gravatar, a something else, etc. - */ - public function get_avatar_html(): string { - // FIXME: configurable - global $config; - if($config->get_string("avatar_host") === "gravatar") { - if(!empty($this->email)) { - $hash = md5(strtolower($this->email)); - $s = $config->get_string("avatar_gravatar_size"); - $d = urlencode($config->get_string("avatar_gravatar_default")); - $r = $config->get_string("avatar_gravatar_rating"); - $cb = date("Y-m-d"); - return ""; - } - } - return ""; - } + /** + * Get a snippet of HTML which will render the user's avatar, be that + * a local file, a remote file, a gravatar, a something else, etc. + */ + public function get_avatar_html(): string + { + // FIXME: configurable + global $config; + if ($config->get_string("avatar_host") === "gravatar") { + if (!empty($this->email)) { + $hash = md5(strtolower($this->email)); + $s = $config->get_string("avatar_gravatar_size"); + $d = urlencode($config->get_string("avatar_gravatar_default")); + $r = $config->get_string("avatar_gravatar_rating"); + $cb = date("Y-m-d"); + return ""; + } + } + return ""; + } - /** - * Get an auth token to be used in POST forms - * - * password = secret, avoid storing directly - * passhash = bcrypt(password), so someone who gets to the database can't get passwords - * sesskey = md5(passhash . IP), so if it gets sniffed it can't be used from another IP, - * and it can't be used to get the passhash to generate new sesskeys - * authtok = md5(sesskey, salt), presented to the user in web forms, to make sure that - * the form was generated within the session. Salted and re-hashed so that - * reading a web page from the user's cache doesn't give access to the session key - */ - public function get_auth_token(): string { - global $config; - $salt = DATABASE_DSN; - $addr = get_session_ip($config); - return md5(md5($this->passhash . $addr) . "salty-csrf-" . $salt); - } + /** + * Get an auth token to be used in POST forms + * + * password = secret, avoid storing directly + * passhash = bcrypt(password), so someone who gets to the database can't get passwords + * sesskey = md5(passhash . IP), so if it gets sniffed it can't be used from another IP, + * and it can't be used to get the passhash to generate new sesskeys + * authtok = md5(sesskey, salt), presented to the user in web forms, to make sure that + * the form was generated within the session. Salted and re-hashed so that + * reading a web page from the user's cache doesn't give access to the session key + */ + public function get_auth_token(): string + { + global $config; + $salt = DATABASE_DSN; + $addr = get_session_ip($config); + return md5(md5($this->passhash . $addr) . "salty-csrf-" . $salt); + } - public function get_auth_html(): string { - $at = $this->get_auth_token(); - return ''; - } + public function get_auth_html(): string + { + $at = $this->get_auth_token(); + return ''; + } - public function check_auth_token(): bool { - return (isset($_POST["auth_token"]) && $_POST["auth_token"] == $this->get_auth_token()); - } + public function check_auth_token(): bool + { + return (isset($_POST["auth_token"]) && $_POST["auth_token"] == $this->get_auth_token()); + } } diff --git a/core/userclass.php b/core/userclass.php index 86af3b79..862b4194 100644 --- a/core/userclass.php +++ b/core/userclass.php @@ -3,191 +3,191 @@ * @global UserClass[] $_shm_user_classes */ global $_shm_user_classes; -$_shm_user_classes = array(); +$_shm_user_classes = []; /** * Class UserClass */ -class UserClass { +class UserClass +{ - /** - * @var null|string - */ - public $name = null; + /** + * @var null|string + */ + public $name = null; - /** - * @var \UserClass|null - */ - public $parent = null; + /** + * @var \UserClass|null + */ + public $parent = null; - /** - * @var array - */ - public $abilities = array(); + /** + * @var array + */ + public $abilities = []; - public function __construct(string $name, string $parent=null, array $abilities=array()) { - global $_shm_user_classes; + public function __construct(string $name, string $parent=null, array $abilities=[]) + { + global $_shm_user_classes; - $this->name = $name; - $this->abilities = $abilities; + $this->name = $name; + $this->abilities = $abilities; - if(!is_null($parent)) { - $this->parent = $_shm_user_classes[$parent]; - } + if (!is_null($parent)) { + $this->parent = $_shm_user_classes[$parent]; + } - $_shm_user_classes[$name] = $this; - } + $_shm_user_classes[$name] = $this; + } - /** - * Determine if this class of user can perform an action or has ability. - * - * @throws SCoreException - */ - public function can(string $ability): bool { - if(array_key_exists($ability, $this->abilities)) { - $val = $this->abilities[$ability]; - return $val; - } - else if(!is_null($this->parent)) { - return $this->parent->can($ability); - } - else { - global $_shm_user_classes; - $min_dist = 9999; - $min_ability = null; - foreach($_shm_user_classes['base']->abilities as $a => $cando) { - $v = levenshtein($ability, $a); - if($v < $min_dist) { - $min_dist = $v; - $min_ability = $a; - } - } - throw new SCoreException("Unknown ability '".html_escape($ability)."'. Did the developer mean '".html_escape($min_ability)."'?"); - } - } + /** + * Determine if this class of user can perform an action or has ability. + * + * @throws SCoreException + */ + public function can(string $ability): bool + { + if (array_key_exists($ability, $this->abilities)) { + $val = $this->abilities[$ability]; + return $val; + } elseif (!is_null($this->parent)) { + return $this->parent->can($ability); + } else { + global $_shm_user_classes; + $min_dist = 9999; + $min_ability = null; + foreach ($_shm_user_classes['base']->abilities as $a => $cando) { + $v = levenshtein($ability, $a); + if ($v < $min_dist) { + $min_dist = $v; + $min_ability = $a; + } + } + throw new SCoreException("Unknown ability '".html_escape($ability)."'. Did the developer mean '".html_escape($min_ability)."'?"); + } + } } // action_object_attribute // action = create / view / edit / delete // object = image / user / tag / setting -new UserClass("base", null, array( - "change_setting" => False, # modify web-level settings, eg the config table - "override_config" => False, # modify sys-level settings, eg shimmie.conf.php - "big_search" => False, # search for more than 3 tags at once (speed mode only) +new UserClass("base", null, [ + "change_setting" => false, # modify web-level settings, eg the config table + "override_config" => false, # modify sys-level settings, eg shimmie.conf.php + "big_search" => false, # search for more than 3 tags at once (speed mode only) - "manage_extension_list" => False, - "manage_alias_list" => False, - "mass_tag_edit" => False, + "manage_extension_list" => false, + "manage_alias_list" => false, + "mass_tag_edit" => false, - "view_ip" => False, # view IP addresses associated with things - "ban_ip" => False, + "view_ip" => false, # view IP addresses associated with things + "ban_ip" => false, - "edit_user_name" => False, - "edit_user_password" => False, - "edit_user_info" => False, # email address, etc - "edit_user_class" => False, - "delete_user" => False, + "edit_user_name" => false, + "edit_user_password" => false, + "edit_user_info" => false, # email address, etc + "edit_user_class" => false, + "delete_user" => false, - "create_comment" => False, - "delete_comment" => False, - "bypass_comment_checks" => False, # spam etc + "create_comment" => false, + "delete_comment" => false, + "bypass_comment_checks" => false, # spam etc - "replace_image" => False, - "create_image" => False, - "edit_image_tag" => False, - "edit_image_source" => False, - "edit_image_owner" => False, - "edit_image_lock" => False, - "bulk_edit_image_tag" => False, - "bulk_edit_image_source" => False, - "delete_image" => False, + "replace_image" => false, + "create_image" => false, + "edit_image_tag" => false, + "edit_image_source" => false, + "edit_image_owner" => false, + "edit_image_lock" => false, + "bulk_edit_image_tag" => false, + "bulk_edit_image_source" => false, + "delete_image" => false, - "ban_image" => False, + "ban_image" => false, - "view_eventlog" => False, - "ignore_downtime" => False, + "view_eventlog" => false, + "ignore_downtime" => false, - "create_image_report" => False, - "view_image_report" => False, # deal with reported images + "create_image_report" => false, + "view_image_report" => false, # deal with reported images - "edit_wiki_page" => False, - "delete_wiki_page" => False, + "edit_wiki_page" => false, + "delete_wiki_page" => false, - "manage_blocks" => False, + "manage_blocks" => false, - "manage_admintools" => False, + "manage_admintools" => false, - "view_other_pms" => False, - "edit_feature" => False, - "bulk_edit_vote" => False, - "edit_other_vote" => False, - "view_sysinfo" => False, + "view_other_pms" => false, + "edit_feature" => false, + "bulk_edit_vote" => false, + "edit_other_vote" => false, + "view_sysinfo" => false, - "hellbanned" => False, - "view_hellbanned" => False, + "hellbanned" => false, + "view_hellbanned" => false, - "protected" => False, # only admins can modify protected users (stops a moderator changing an admin's password) -)); + "protected" => false, # only admins can modify protected users (stops a moderator changing an admin's password) +]); -new UserClass("anonymous", "base", array( -)); +new UserClass("anonymous", "base", [ +]); -new UserClass("user", "base", array( - "big_search" => True, - "create_image" => True, - "create_comment" => True, - "edit_image_tag" => True, - "edit_image_source" => True, - "create_image_report" => True, -)); +new UserClass("user", "base", [ + "big_search" => true, + "create_image" => true, + "create_comment" => true, + "edit_image_tag" => true, + "edit_image_source" => true, + "create_image_report" => true, +]); -new UserClass("admin", "base", array( - "change_setting" => True, - "override_config" => True, - "big_search" => True, - "edit_image_lock" => True, - "view_ip" => True, - "ban_ip" => True, - "edit_user_name" => True, - "edit_user_password" => True, - "edit_user_info" => True, - "edit_user_class" => True, - "delete_user" => True, - "create_image" => True, - "delete_image" => True, - "ban_image" => True, - "create_comment" => True, - "delete_comment" => True, - "bypass_comment_checks" => True, - "replace_image" => True, - "manage_extension_list" => True, - "manage_alias_list" => True, - "edit_image_tag" => True, - "edit_image_source" => True, - "edit_image_owner" => True, - "bulk_edit_image_tag" => True, - "bulk_edit_image_source" => True, - "mass_tag_edit" => True, - "create_image_report" => True, - "view_image_report" => True, - "edit_wiki_page" => True, - "delete_wiki_page" => True, - "view_eventlog" => True, - "manage_blocks" => True, - "manage_admintools" => True, - "ignore_downtime" => True, - "view_other_pms" => True, - "edit_feature" => True, - "bulk_edit_vote" => True, - "edit_other_vote" => True, - "view_sysinfo" => True, - "view_hellbanned" => True, - "protected" => True, -)); +new UserClass("admin", "base", [ + "change_setting" => true, + "override_config" => true, + "big_search" => true, + "edit_image_lock" => true, + "view_ip" => true, + "ban_ip" => true, + "edit_user_name" => true, + "edit_user_password" => true, + "edit_user_info" => true, + "edit_user_class" => true, + "delete_user" => true, + "create_image" => true, + "delete_image" => true, + "ban_image" => true, + "create_comment" => true, + "delete_comment" => true, + "bypass_comment_checks" => true, + "replace_image" => true, + "manage_extension_list" => true, + "manage_alias_list" => true, + "edit_image_tag" => true, + "edit_image_source" => true, + "edit_image_owner" => true, + "bulk_edit_image_tag" => true, + "bulk_edit_image_source" => true, + "mass_tag_edit" => true, + "create_image_report" => true, + "view_image_report" => true, + "edit_wiki_page" => true, + "delete_wiki_page" => true, + "view_eventlog" => true, + "manage_blocks" => true, + "manage_admintools" => true, + "ignore_downtime" => true, + "view_other_pms" => true, + "edit_feature" => true, + "bulk_edit_vote" => true, + "edit_other_vote" => true, + "view_sysinfo" => true, + "view_hellbanned" => true, + "protected" => true, +]); -new UserClass("hellbanned", "user", array( - "hellbanned" => True, -)); +new UserClass("hellbanned", "user", [ + "hellbanned" => true, +]); @include_once "data/config/user-classes.conf.php"; - diff --git a/core/util.php b/core/util.php index 9ac1477f..b5908246 100644 --- a/core/util.php +++ b/core/util.php @@ -5,117 +5,126 @@ require_once "vendor/shish/libcontext-php/context.php"; * Misc * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -function mtimefile(string $file): string { - $data_href = get_base_href(); - $mtime = filemtime($file); - return "$data_href/$file?$mtime"; +function mtimefile(string $file): string +{ + $data_href = get_base_href(); + $mtime = filemtime($file); + return "$data_href/$file?$mtime"; } -function get_theme(): string { - global $config; - $theme = $config->get_string("theme", "default"); - if(!file_exists("themes/$theme")) $theme = "default"; - return $theme; +function get_theme(): string +{ + global $config; + $theme = $config->get_string("theme", "default"); + if (!file_exists("themes/$theme")) { + $theme = "default"; + } + return $theme; } -function contact_link(): ?string { - global $config; - $text = $config->get_string('contact_link'); - if(is_null($text)) return null; +function contact_link(): ?string +{ + global $config; + $text = $config->get_string('contact_link'); + if (is_null($text)) { + return null; + } - if( - startsWith($text, "http:") || - startsWith($text, "https:") || - startsWith($text, "mailto:") - ) { - return $text; - } + if ( + startsWith($text, "http:") || + startsWith($text, "https:") || + startsWith($text, "mailto:") + ) { + return $text; + } - if(strpos($text, "@")) { - return "mailto:$text"; - } + if (strpos($text, "@")) { + return "mailto:$text"; + } - if(strpos($text, "/")) { - return "http://$text"; - } + if (strpos($text, "/")) { + return "http://$text"; + } - return $text; + return $text; } /** * Check if HTTPS is enabled for the server. */ -function is_https_enabled(): bool { - return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); +function is_https_enabled(): bool +{ + return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); } /** * Compare two Block objects, used to sort them before being displayed */ -function blockcmp(Block $a, Block $b): int { - if($a->position == $b->position) { - return 0; - } - else { - return ($a->position > $b->position); - } +function blockcmp(Block $a, Block $b): int +{ + if ($a->position == $b->position) { + return 0; + } else { + return ($a->position > $b->position); + } } /** * Figure out PHP's internal memory limit */ -function get_memory_limit(): int { - global $config; +function get_memory_limit(): int +{ + global $config; - // thumbnail generation requires lots of memory - $default_limit = 8*1024*1024; // 8 MB of memory is PHP's default. - $shimmie_limit = parse_shorthand_int($config->get_int("thumb_mem_limit")); + // thumbnail generation requires lots of memory + $default_limit = 8*1024*1024; // 8 MB of memory is PHP's default. + $shimmie_limit = parse_shorthand_int($config->get_int("thumb_mem_limit")); - if($shimmie_limit < 3*1024*1024) { - // we aren't going to fit, override - $shimmie_limit = $default_limit; - } + if ($shimmie_limit < 3*1024*1024) { + // we aren't going to fit, override + $shimmie_limit = $default_limit; + } - /* - Get PHP's configured memory limit. - Note that this is set to -1 for NO memory limit. + /* + Get PHP's configured memory limit. + Note that this is set to -1 for NO memory limit. - http://ca2.php.net/manual/en/ini.core.php#ini.memory-limit - */ - $memory = parse_shorthand_int(ini_get("memory_limit")); + http://ca2.php.net/manual/en/ini.core.php#ini.memory-limit + */ + $memory = parse_shorthand_int(ini_get("memory_limit")); - if($memory == -1) { - // No memory limit. - // Return the larger of the set limits. - return max($shimmie_limit, $default_limit); - } - else { - // PHP has a memory limit set. - if ($shimmie_limit > $memory) { - // Shimmie wants more memory than what PHP is currently set for. + if ($memory == -1) { + // No memory limit. + // Return the larger of the set limits. + return max($shimmie_limit, $default_limit); + } else { + // PHP has a memory limit set. + if ($shimmie_limit > $memory) { + // Shimmie wants more memory than what PHP is currently set for. - // Attempt to set PHP's memory limit. - if ( ini_set("memory_limit", $shimmie_limit) === false ) { - /* We can't change PHP's limit, oh well, return whatever its currently set to */ - return $memory; - } - $memory = parse_shorthand_int(ini_get("memory_limit")); - } + // Attempt to set PHP's memory limit. + if (ini_set("memory_limit", $shimmie_limit) === false) { + /* We can't change PHP's limit, oh well, return whatever its currently set to */ + return $memory; + } + $memory = parse_shorthand_int(ini_get("memory_limit")); + } - // PHP's memory limit is more than Shimmie needs. - return $memory; // return the current setting - } + // PHP's memory limit is more than Shimmie needs. + return $memory; // return the current setting + } } /** * Get the currently active IP, masked to make it not change when the last * octet or two change, for use in session cookies and such */ -function get_session_ip(Config $config): string { - $mask = $config->get_string("session_hash_mask", "255.255.0.0"); - $addr = $_SERVER['REMOTE_ADDR']; - $addr = inet_ntop(inet_pton($addr) & inet_pton($mask)); - return $addr; +function get_session_ip(Config $config): string +{ + $mask = $config->get_string("session_hash_mask", "255.255.0.0"); + $addr = $_SERVER['REMOTE_ADDR']; + $addr = inet_ntop(inet_pton($addr) & inet_pton($mask)); + return $addr; } @@ -128,146 +137,159 @@ function get_session_ip(Config $config): string { * the action actually takes place (eg onWhateverElse) - but much of the time, actions * are taken from within onPageRequest... */ -function flash_message(string $text, string $type="info") { - global $page; - $current = $page->get_cookie("flash_message"); - if($current) { - $text = $current . "\n" . $text; - } - # the message should be viewed pretty much immediately, - # so 60s timeout should be more than enough - $page->add_cookie("flash_message", $text, time()+60, "/"); +function flash_message(string $text, string $type="info") +{ + global $page; + $current = $page->get_cookie("flash_message"); + if ($current) { + $text = $current . "\n" . $text; + } + # the message should be viewed pretty much immediately, + # so 60s timeout should be more than enough + $page->add_cookie("flash_message", $text, time()+60, "/"); } /** * A shorthand way to send a TextFormattingEvent and get the results. */ -function format_text(string $string): string { - $tfe = new TextFormattingEvent($string); - send_event($tfe); - return $tfe->formatted; +function format_text(string $string): string +{ + $tfe = new TextFormattingEvent($string); + send_event($tfe); + return $tfe->formatted; } -function warehouse_path(string $base, string $hash, bool $create=true): string { - $ab = substr($hash, 0, 2); - $cd = substr($hash, 2, 2); - if(WH_SPLITS == 2) { - $pa = 'data/'.$base.'/'.$ab.'/'.$cd.'/'.$hash; - } - else { - $pa = 'data/'.$base.'/'.$ab.'/'.$hash; - } - if($create && !file_exists(dirname($pa))) mkdir(dirname($pa), 0755, true); - return $pa; +function warehouse_path(string $base, string $hash, bool $create=true): string +{ + $ab = substr($hash, 0, 2); + $cd = substr($hash, 2, 2); + if (WH_SPLITS == 2) { + $pa = 'data/'.$base.'/'.$ab.'/'.$cd.'/'.$hash; + } else { + $pa = 'data/'.$base.'/'.$ab.'/'.$hash; + } + if ($create && !file_exists(dirname($pa))) { + mkdir(dirname($pa), 0755, true); + } + return $pa; } -function data_path(string $filename): string { - $filename = "data/" . $filename; - if(!file_exists(dirname($filename))) mkdir(dirname($filename), 0755, true); - return $filename; +function data_path(string $filename): string +{ + $filename = "data/" . $filename; + if (!file_exists(dirname($filename))) { + mkdir(dirname($filename), 0755, true); + } + return $filename; } -function transload(string $url, string $mfile): ?array { - global $config; +function transload(string $url, string $mfile): ?array +{ + global $config; - if($config->get_string("transload_engine") === "curl" && function_exists("curl_init")) { - $ch = curl_init($url); - $fp = fopen($mfile, "w"); + if ($config->get_string("transload_engine") === "curl" && function_exists("curl_init")) { + $ch = curl_init($url); + $fp = fopen($mfile, "w"); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_VERBOSE, 1); - curl_setopt($ch, CURLOPT_HEADER, 1); - curl_setopt($ch, CURLOPT_REFERER, $url); - curl_setopt($ch, CURLOPT_USERAGENT, "Shimmie-".VERSION); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_VERBOSE, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_REFERER, $url); + curl_setopt($ch, CURLOPT_USERAGENT, "Shimmie-".VERSION); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - $response = curl_exec($ch); + $response = curl_exec($ch); - $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); - $headers = http_parse_headers(implode("\n", preg_split('/\R/', rtrim(substr($response, 0, $header_size))))); - $body = substr($response, $header_size); + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $headers = http_parse_headers(implode("\n", preg_split('/\R/', rtrim(substr($response, 0, $header_size))))); + $body = substr($response, $header_size); - curl_close($ch); - fwrite($fp, $body); - fclose($fp); + curl_close($ch); + fwrite($fp, $body); + fclose($fp); - return $headers; - } + return $headers; + } - if($config->get_string("transload_engine") === "wget") { - $s_url = escapeshellarg($url); - $s_mfile = escapeshellarg($mfile); - system("wget --no-check-certificate $s_url --output-document=$s_mfile"); + if ($config->get_string("transload_engine") === "wget") { + $s_url = escapeshellarg($url); + $s_mfile = escapeshellarg($mfile); + system("wget --no-check-certificate $s_url --output-document=$s_mfile"); - return file_exists($mfile); - } + return file_exists($mfile); + } - if($config->get_string("transload_engine") === "fopen") { - $fp_in = @fopen($url, "r"); - $fp_out = fopen($mfile, "w"); - if(!$fp_in || !$fp_out) { - return null; - } - $length = 0; - while(!feof($fp_in) && $length <= $config->get_int('upload_size')) { - $data = fread($fp_in, 8192); - $length += strlen($data); - fwrite($fp_out, $data); - } - fclose($fp_in); - fclose($fp_out); + if ($config->get_string("transload_engine") === "fopen") { + $fp_in = @fopen($url, "r"); + $fp_out = fopen($mfile, "w"); + if (!$fp_in || !$fp_out) { + return null; + } + $length = 0; + while (!feof($fp_in) && $length <= $config->get_int('upload_size')) { + $data = fread($fp_in, 8192); + $length += strlen($data); + fwrite($fp_out, $data); + } + fclose($fp_in); + fclose($fp_out); - $headers = http_parse_headers(implode("\n", $http_response_header)); + $headers = http_parse_headers(implode("\n", $http_response_header)); - return $headers; - } + return $headers; + } - return null; + return null; } /** * Get the active contents of a .php file */ -function manual_include(string $fname): ?string { - static $included = array(); +function manual_include(string $fname): ?string +{ + static $included = []; - if(!file_exists($fname)) return null; + if (!file_exists($fname)) { + return null; + } - if(in_array($fname, $included)) return null; + if (in_array($fname, $included)) { + return null; + } - $included[] = $fname; + $included[] = $fname; - print "$fname\n"; + print "$fname\n"; - $text = file_get_contents($fname); + $text = file_get_contents($fname); - // we want one continuous file - $text = str_replace('<'.'?php', '', $text); - $text = str_replace('?'.'>', '', $text); + // we want one continuous file + $text = str_replace('<'.'?php', '', $text); + $text = str_replace('?'.'>', '', $text); - // most requires are built-in, but we want /lib separately - $text = str_replace('require_', '// require_', $text); - $text = str_replace('// require_once "lib', 'require_once "lib', $text); + // most requires are built-in, but we want /lib separately + $text = str_replace('require_', '// require_', $text); + $text = str_replace('// require_once "lib', 'require_once "lib', $text); - // @include_once is used for user-creatable config files - $text = preg_replace('/@include_once "(.*)";/e', "manual_include('$1')", $text); + // @include_once is used for user-creatable config files + $text = preg_replace('/@include_once "(.*)";/e', "manual_include('$1')", $text); - return $text; + return $text; } -function path_to_tags(string $path): string { - $matches = array(); - if(preg_match("/\d+ - (.*)\.([a-zA-Z]+)/", basename($path), $matches)) { - $tags = $matches[1]; - } - else { - $tags = dirname($path); - $tags = str_replace("/", " ", $tags); - $tags = str_replace("__", " ", $tags); - $tags = trim($tags); - } - return $tags; +function path_to_tags(string $path): string +{ + $matches = []; + if (preg_match("/\d+ - (.*)\.([a-zA-Z]+)/", basename($path), $matches)) { + $tags = $matches[1]; + } else { + $tags = dirname($path); + $tags = str_replace("/", " ", $tags); + $tags = str_replace("__", " ", $tags); + $tags = trim($tags); + } + return $tags; } @@ -284,52 +306,54 @@ $_shm_load_start = microtime(true); * Collects some debug information (execution time, memory usage, queries, etc) * and formats it to stick in the footer of the page. */ -function get_debug_info(): string { - global $config, $_shm_event_count, $database, $_shm_load_start; +function get_debug_info(): string +{ + global $config, $_shm_event_count, $database, $_shm_load_start; - $i_mem = sprintf("%5.2f", ((memory_get_peak_usage(true)+512)/1024)/1024); + $i_mem = sprintf("%5.2f", ((memory_get_peak_usage(true)+512)/1024)/1024); - if($config->get_string("commit_hash", "unknown") == "unknown"){ - $commit = ""; - } - else { - $commit = " (".$config->get_string("commit_hash").")"; - } - $time = sprintf("%.2f", microtime(true) - $_shm_load_start); - $dbtime = sprintf("%.2f", $database->dbtime); - $i_files = count(get_included_files()); - $hits = $database->cache->get_hits(); - $miss = $database->cache->get_misses(); + if ($config->get_string("commit_hash", "unknown") == "unknown") { + $commit = ""; + } else { + $commit = " (".$config->get_string("commit_hash").")"; + } + $time = sprintf("%.2f", microtime(true) - $_shm_load_start); + $dbtime = sprintf("%.2f", $database->dbtime); + $i_files = count(get_included_files()); + $hits = $database->cache->get_hits(); + $miss = $database->cache->get_misses(); - $debug = "
Took $time seconds (db:$dbtime) and {$i_mem}MB of RAM"; - $debug .= "; Used $i_files files and {$database->query_count} queries"; - $debug .= "; Sent $_shm_event_count events"; - $debug .= "; $hits cache hits and $miss misses"; - $debug .= "; Shimmie version ". VERSION . $commit; // .", SCore Version ". SCORE_VERSION; + $debug = "
Took $time seconds (db:$dbtime) and {$i_mem}MB of RAM"; + $debug .= "; Used $i_files files and {$database->query_count} queries"; + $debug .= "; Sent $_shm_event_count events"; + $debug .= "; $hits cache hits and $miss misses"; + $debug .= "; Shimmie version ". VERSION . $commit; // .", SCore Version ". SCORE_VERSION; - return $debug; + return $debug; } -function log_slow() { - global $_shm_load_start; - if(!is_null(SLOW_PAGES)) { - $_time = microtime(true) - $_shm_load_start; - if($_time > SLOW_PAGES) { - $_query = _get_query(); - $_dbg = get_debug_info(); - file_put_contents("data/slow-pages.log", "$_time $_query $_dbg\n", FILE_APPEND | LOCK_EX); - } - } +function log_slow() +{ + global $_shm_load_start; + if (!is_null(SLOW_PAGES)) { + $_time = microtime(true) - $_shm_load_start; + if ($_time > SLOW_PAGES) { + $_query = _get_query(); + $_dbg = get_debug_info(); + file_put_contents("data/slow-pages.log", "$_time $_query $_dbg\n", FILE_APPEND | LOCK_EX); + } + } } -function score_assert_handler($file, $line, $code, $desc = null) { - $file = basename($file); - print("Assertion failed at $file:$line: $code ($desc)"); - /* - print("

");
-	debug_print_backtrace();
-	print("
"); - */ +function score_assert_handler($file, $line, $code, $desc = null) +{ + $file = basename($file); + print("Assertion failed at $file:$line: $code ($desc)"); + /* + print("
");
+    debug_print_backtrace();
+    print("
"); + */ } @@ -339,88 +363,94 @@ function score_assert_handler($file, $line, $code, $desc = null) { /** @privatesection */ -function _version_check() { - if(MIN_PHP_VERSION) { - if(version_compare(phpversion(), MIN_PHP_VERSION, ">=") === FALSE) { - print " +function _version_check() +{ + if (MIN_PHP_VERSION) { + if (version_compare(phpversion(), MIN_PHP_VERSION, ">=") === false) { + print " Shimmie (SCore Engine) does not support versions of PHP lower than ".MIN_PHP_VERSION." (PHP reports that it is version ".phpversion().") If your web host is running an older version, they are dangerously out of date and you should plan on moving elsewhere. "; - exit; - } - } + exit; + } + } } -function _sanitise_environment() { - global $_shm_ctx; +function _sanitise_environment() +{ + global $_shm_ctx; - if(TIMEZONE) { - date_default_timezone_set(TIMEZONE); - } + if (TIMEZONE) { + date_default_timezone_set(TIMEZONE); + } - # ini_set('zend.assertions', 1); // generate assertions - ini_set('assert.exception', 1); // throw exceptions when failed - if(DEBUG) { - error_reporting(E_ALL); - assert_options(ASSERT_ACTIVE, 1); - assert_options(ASSERT_BAIL, 1); - assert_options(ASSERT_WARNING, 0); - assert_options(ASSERT_QUIET_EVAL, 1); - assert_options(ASSERT_CALLBACK, 'score_assert_handler'); - } + # ini_set('zend.assertions', 1); // generate assertions + ini_set('assert.exception', 1); // throw exceptions when failed + if (DEBUG) { + error_reporting(E_ALL); + assert_options(ASSERT_ACTIVE, 1); + assert_options(ASSERT_BAIL, 1); + assert_options(ASSERT_WARNING, 0); + assert_options(ASSERT_QUIET_EVAL, 1); + assert_options(ASSERT_CALLBACK, 'score_assert_handler'); + } - $_shm_ctx = new Context(); - if(CONTEXT) { - $_shm_ctx->set_log(CONTEXT); - } + $_shm_ctx = new Context(); + if (CONTEXT) { + $_shm_ctx->set_log(CONTEXT); + } - if(COVERAGE) { - _start_coverage(); - register_shutdown_function("_end_coverage"); - } + if (COVERAGE) { + _start_coverage(); + register_shutdown_function("_end_coverage"); + } - ob_start(); + ob_start(); - if(PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { - if(isset($_SERVER['REMOTE_ADDR'])) { - die("CLI with remote addr? Confused, not taking the risk."); - } - $_SERVER['REMOTE_ADDR'] = "0.0.0.0"; - $_SERVER['HTTP_HOST'] = ""; - } + if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { + if (isset($_SERVER['REMOTE_ADDR'])) { + die("CLI with remote addr? Confused, not taking the risk."); + } + $_SERVER['REMOTE_ADDR'] = "0.0.0.0"; + $_SERVER['HTTP_HOST'] = ""; + } } -function _get_themelet_files(string $_theme): array { - $base_themelets = array(); - if(file_exists('themes/'.$_theme.'/custompage.class.php')) $base_themelets[] = 'themes/'.$_theme.'/custompage.class.php'; - $base_themelets[] = 'themes/'.$_theme.'/layout.class.php'; - $base_themelets[] = 'themes/'.$_theme.'/themelet.class.php'; +function _get_themelet_files(string $_theme): array +{ + $base_themelets = []; + if (file_exists('themes/'.$_theme.'/custompage.class.php')) { + $base_themelets[] = 'themes/'.$_theme.'/custompage.class.php'; + } + $base_themelets[] = 'themes/'.$_theme.'/layout.class.php'; + $base_themelets[] = 'themes/'.$_theme.'/themelet.class.php'; - $ext_themelets = zglob("ext/{".ENABLED_EXTS."}/theme.php"); - $custom_themelets = zglob('themes/'.$_theme.'/{'.ENABLED_EXTS.'}.theme.php'); + $ext_themelets = zglob("ext/{".ENABLED_EXTS."}/theme.php"); + $custom_themelets = zglob('themes/'.$_theme.'/{'.ENABLED_EXTS.'}.theme.php'); - return array_merge($base_themelets, $ext_themelets, $custom_themelets); + return array_merge($base_themelets, $ext_themelets, $custom_themelets); } /** * Used to display fatal errors to the web user. */ -function _fatal_error(Exception $e) { - $version = VERSION; - $message = $e->getMessage(); +function _fatal_error(Exception $e) +{ + $version = VERSION; + $message = $e->getMessage(); - //$trace = var_dump($e->getTrace()); + //$trace = var_dump($e->getTrace()); - //$hash = exec("git rev-parse HEAD"); - //$h_hash = $hash ? "

Hash: $hash" : ""; - //'.$h_hash.' + //$hash = exec("git rev-parse HEAD"); + //$h_hash = $hash ? "

Hash: $hash" : ""; + //'.$h_hash.' - header("HTTP/1.0 500 Internal Error"); - echo ' + header("HTTP/1.0 500 Internal Error"); + echo ' Internal error - SCore-'.$version.' @@ -440,42 +470,50 @@ function _fatal_error(Exception $e) { * Necessary because various servers and various clients * think that / is special... */ -function _decaret(string $str): string { - $out = ""; - $length = strlen($str); - for($i=0; $i<$length; $i++) { - if($str[$i] == "^") { - $i++; - if($str[$i] == "^") $out .= "^"; - if($str[$i] == "s") $out .= "/"; - if($str[$i] == "b") $out .= "\\"; - } - else { - $out .= $str[$i]; - } - } - return $out; +function _decaret(string $str): string +{ + $out = ""; + $length = strlen($str); + for ($i=0; $i<$length; $i++) { + if ($str[$i] == "^") { + $i++; + if ($str[$i] == "^") { + $out .= "^"; + } + if ($str[$i] == "s") { + $out .= "/"; + } + if ($str[$i] == "b") { + $out .= "\\"; + } + } else { + $out .= $str[$i]; + } + } + return $out; } -function _get_user(): User { - global $config, $page; - $user = null; - if($page->get_cookie("user") && $page->get_cookie("session")) { - $tmp_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session")); - if(!is_null($tmp_user)) { - $user = $tmp_user; - } - } - if(is_null($user)) { - $user = User::by_id($config->get_int("anon_id", 0)); - } - assert(!is_null($user)); +function _get_user(): User +{ + global $config, $page; + $user = null; + if ($page->get_cookie("user") && $page->get_cookie("session")) { + $tmp_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session")); + if (!is_null($tmp_user)) { + $user = $tmp_user; + } + } + if (is_null($user)) { + $user = User::by_id($config->get_int("anon_id", 0)); + } + assert(!is_null($user)); - return $user; + return $user; } -function _get_query(): string { - return (@$_POST["q"]?:@$_GET["q"])?:"/"; +function _get_query(): string +{ + return (@$_POST["q"]?:@$_GET["q"])?:"/"; } @@ -483,24 +521,30 @@ function _get_query(): string { * Code coverage * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -function _start_coverage(): void { - if(function_exists("xdebug_start_code_coverage")) { - #xdebug_start_code_coverage(XDEBUG_CC_UNUSED|XDEBUG_CC_DEAD_CODE); - xdebug_start_code_coverage(XDEBUG_CC_UNUSED); - } +function _start_coverage(): void +{ + if (function_exists("xdebug_start_code_coverage")) { + #xdebug_start_code_coverage(XDEBUG_CC_UNUSED|XDEBUG_CC_DEAD_CODE); + xdebug_start_code_coverage(XDEBUG_CC_UNUSED); + } } -function _end_coverage(): void { - if(function_exists("xdebug_get_code_coverage")) { - // Absolute path is necessary because working directory - // inside register_shutdown_function is unpredictable. - $absolute_path = dirname(dirname(__FILE__)) . "/data/coverage"; - if(!file_exists($absolute_path)) mkdir($absolute_path); - $n = 0; - $t = time(); - while(file_exists("$absolute_path/$t.$n.log")) $n++; - file_put_contents("$absolute_path/$t.$n.log", gzdeflate(serialize(xdebug_get_code_coverage()))); - } +function _end_coverage(): void +{ + if (function_exists("xdebug_get_code_coverage")) { + // Absolute path is necessary because working directory + // inside register_shutdown_function is unpredictable. + $absolute_path = dirname(dirname(__FILE__)) . "/data/coverage"; + if (!file_exists($absolute_path)) { + mkdir($absolute_path); + } + $n = 0; + $t = time(); + while (file_exists("$absolute_path/$t.$n.log")) { + $n++; + } + file_put_contents("$absolute_path/$t.$n.log", gzdeflate(serialize(xdebug_get_code_coverage()))); + } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ @@ -513,35 +557,36 @@ function _end_coverage(): void { * * FIXME: also check that IP ban ext is installed */ -function show_ip(string $ip, string $ban_reason): string { - global $user; - $u_reason = url_escape($ban_reason); - $u_end = url_escape("+1 week"); - $ban = $user->can("ban_ip") ? ", Ban" : ""; - $ip = $user->can("view_ip") ? $ip.$ban : ""; - return $ip; +function show_ip(string $ip, string $ban_reason): string +{ + global $user; + $u_reason = url_escape($ban_reason); + $u_end = url_escape("+1 week"); + $ban = $user->can("ban_ip") ? ", Ban" : ""; + $ip = $user->can("view_ip") ? $ip.$ban : ""; + return $ip; } /** * Make a form tag with relevant auth token and stuff */ -function make_form(string $target, string $method="POST", bool $multipart=False, string $form_id="", string $onsubmit=""): string { - global $user; - if($method == "GET") { - $link = html_escape($target); - $target = make_link($target); - $extra_inputs = ""; - } - else { - $extra_inputs = $user->get_auth_html(); - } +function make_form(string $target, string $method="POST", bool $multipart=false, string $form_id="", string $onsubmit=""): string +{ + global $user; + if ($method == "GET") { + $link = html_escape($target); + $target = make_link($target); + $extra_inputs = ""; + } else { + $extra_inputs = $user->get_auth_html(); + } - $extra = empty($form_id) ? '' : 'id="'. $form_id .'"'; - if($multipart) { - $extra .= " enctype='multipart/form-data'"; - } - if($onsubmit) { - $extra .= ' onsubmit="'.$onsubmit.'"'; - } - return '

'.$extra_inputs; + $extra = empty($form_id) ? '' : 'id="'. $form_id .'"'; + if ($multipart) { + $extra .= " enctype='multipart/form-data'"; + } + if ($onsubmit) { + $extra .= ' onsubmit="'.$onsubmit.'"'; + } + return ''.$extra_inputs; } diff --git a/ext/admin/main.php b/ext/admin/main.php index 752ae64e..05722392 100644 --- a/ext/admin/main.php +++ b/ext/admin/main.php @@ -23,254 +23,268 @@ /** * Sent when the admin page is ready to be added to */ -class AdminBuildingEvent extends Event { - /** @var \Page */ - public $page; +class AdminBuildingEvent extends Event +{ + /** @var \Page */ + public $page; - public function __construct(Page $page) { - $this->page = $page; - } + public function __construct(Page $page) + { + $this->page = $page; + } } -class AdminActionEvent extends Event { - /** @var string */ - public $action; - /** @var bool */ - public $redirect = true; +class AdminActionEvent extends Event +{ + /** @var string */ + public $action; + /** @var bool */ + public $redirect = true; - public function __construct(string $action) { - $this->action = $action; - } + public function __construct(string $action) + { + $this->action = $action; + } } -class AdminPage extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; +class AdminPage extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("admin")) { - if(!$user->can("manage_admintools")) { - $this->theme->display_permission_denied(); - } - else { - if($event->count_args() == 0) { - send_event(new AdminBuildingEvent($page)); - } - else { - $action = $event->get_arg(0); - $aae = new AdminActionEvent($action); + if ($event->page_matches("admin")) { + if (!$user->can("manage_admintools")) { + $this->theme->display_permission_denied(); + } else { + if ($event->count_args() == 0) { + send_event(new AdminBuildingEvent($page)); + } else { + $action = $event->get_arg(0); + $aae = new AdminActionEvent($action); - if($user->check_auth_token()) { - log_info("admin", "Util: $action"); - set_time_limit(0); - send_event($aae); - } + if ($user->check_auth_token()) { + log_info("admin", "Util: $action"); + set_time_limit(0); + send_event($aae); + } - if($aae->redirect) { - $page->set_mode("redirect"); - $page->set_redirect(make_link("admin")); - } - } - } - } - } + if ($aae->redirect) { + $page->set_mode("redirect"); + $page->set_redirect(make_link("admin")); + } + } + } + } + } - public function onCommand(CommandEvent $event) { - if($event->cmd == "help") { - print "\tget-page [query string]\n"; - print "\t\teg 'get-page post/list'\n\n"; - print "\tregen-thumb [hash]\n"; - print "\t\tregenerate a thumbnail\n\n"; - } - if($event->cmd == "get-page") { - global $page; - send_event(new PageRequestEvent($event->args[0])); - $page->display(); - } - if($event->cmd == "regen-thumb") { - $image = Image::by_hash($event->args[0]); - if($image) { - print("Regenerating thumb for image {$image->id} ({$image->hash})\n"); - send_event(new ThumbnailGenerationEvent($image->hash, $image->ext, true)); - } - else { - print("Can't find image with hash {$event->args[0]}\n"); - } - } - } + public function onCommand(CommandEvent $event) + { + if ($event->cmd == "help") { + print "\tget-page [query string]\n"; + print "\t\teg 'get-page post/list'\n\n"; + print "\tregen-thumb [hash]\n"; + print "\t\tregenerate a thumbnail\n\n"; + } + if ($event->cmd == "get-page") { + global $page; + send_event(new PageRequestEvent($event->args[0])); + $page->display(); + } + if ($event->cmd == "regen-thumb") { + $image = Image::by_hash($event->args[0]); + if ($image) { + print("Regenerating thumb for image {$image->id} ({$image->hash})\n"); + send_event(new ThumbnailGenerationEvent($image->hash, $image->ext, true)); + } else { + print("Can't find image with hash {$event->args[0]}\n"); + } + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_page(); - $this->theme->display_form(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_page(); + $this->theme->display_form(); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("manage_admintools")) { - $event->add_link("Board Admin", make_link("admin")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("manage_admintools")) { + $event->add_link("Board Admin", make_link("admin")); + } + } - public function onAdminAction(AdminActionEvent $event) { - $action = $event->action; - if(method_exists($this, $action)) { - $event->redirect = $this->$action(); - } - } + public function onAdminAction(AdminActionEvent $event) + { + $action = $event->action; + if (method_exists($this, $action)) { + $event->redirect = $this->$action(); + } + } - public function onPostListBuilding(PostListBuildingEvent $event) { - global $user; - if($user->can("manage_admintools") && !empty($event->search_terms)) { - $event->add_control($this->theme->dbq_html(Tag::implode($event->search_terms))); - } - } + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $user; + if ($user->can("manage_admintools") && !empty($event->search_terms)) { + $event->add_control($this->theme->dbq_html(Tag::implode($event->search_terms))); + } + } - private function delete_by_query() { - global $page; - $query = $_POST['query']; - $reason = @$_POST['reason']; - assert(strlen($query) > 1); + private function delete_by_query() + { + global $page; + $query = $_POST['query']; + $reason = @$_POST['reason']; + assert(strlen($query) > 1); - $images = Image::find_images(0, 1000000, Tag::explode($query)); - $count = count($images); - log_warning("admin", "Mass-deleting $count images from $query", "Mass deleted $count images"); - foreach($images as $image) { - if($reason && class_exists("ImageBan")) { - send_event(new AddImageHashBanEvent($image->hash, $reason)); - } - send_event(new ImageDeletionEvent($image)); - } + $images = Image::find_images(0, 1000000, Tag::explode($query)); + $count = count($images); + log_warning("admin", "Mass-deleting $count images from $query", "Mass deleted $count images"); + foreach ($images as $image) { + if ($reason && class_exists("ImageBan")) { + send_event(new AddImageHashBanEvent($image->hash, $reason)); + } + send_event(new ImageDeletionEvent($image)); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/list")); - return false; - } + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/list")); + return false; + } - private function set_tag_case() { - global $database; - $database->execute($database->scoreql_to_sql( - "UPDATE tags SET tag=:tag1 WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag2)" - ), array("tag1" => $_POST['tag'], "tag2" => $_POST['tag'])); - log_info("admin", "Fixed the case of ".html_escape($_POST['tag']), "Fixed case"); - return true; - } + private function set_tag_case() + { + global $database; + $database->execute($database->scoreql_to_sql( + "UPDATE tags SET tag=:tag1 WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag2)" + ), ["tag1" => $_POST['tag'], "tag2" => $_POST['tag']]); + log_info("admin", "Fixed the case of ".html_escape($_POST['tag']), "Fixed case"); + return true; + } - private function lowercase_all_tags() { - global $database; - $database->execute("UPDATE tags SET tag=lower(tag)"); - log_warning("admin", "Set all tags to lowercase", "Set all tags to lowercase"); - return true; - } + private function lowercase_all_tags() + { + global $database; + $database->execute("UPDATE tags SET tag=lower(tag)"); + log_warning("admin", "Set all tags to lowercase", "Set all tags to lowercase"); + return true; + } - private function recount_tag_use() { - global $database; - $database->Execute(" + private function recount_tag_use() + { + global $database; + $database->Execute(" UPDATE tags SET count = COALESCE( (SELECT COUNT(image_id) FROM image_tags WHERE tag_id=tags.id GROUP BY tag_id), 0 ) "); - $database->Execute("DELETE FROM tags WHERE count=0"); - log_warning("admin", "Re-counted tags", "Re-counted tags"); - return true; - } + $database->Execute("DELETE FROM tags WHERE count=0"); + log_warning("admin", "Re-counted tags", "Re-counted tags"); + return true; + } - private function database_dump() { - global $page; + private function database_dump() + { + global $page; - $matches = array(); - preg_match("#^(?P\w+)\:(?:user=(?P\w+)(?:;|$)|password=(?P\w*)(?:;|$)|host=(?P[\w\.\-]+)(?:;|$)|dbname=(?P[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches); - $software = $matches['proto']; - $username = $matches['user']; - $password = $matches['password']; - $hostname = $matches['host']; - $database = $matches['dbname']; + $matches = []; + preg_match("#^(?P\w+)\:(?:user=(?P\w+)(?:;|$)|password=(?P\w*)(?:;|$)|host=(?P[\w\.\-]+)(?:;|$)|dbname=(?P[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches); + $software = $matches['proto']; + $username = $matches['user']; + $password = $matches['password']; + $hostname = $matches['host']; + $database = $matches['dbname']; - switch($software) { - case 'mysql': - $cmd = "mysqldump -h$hostname -u$username -p$password $database"; - break; - case 'pgsql': - putenv("PGPASSWORD=$password"); - $cmd = "pg_dump -h $hostname -U $username $database"; - break; - case 'sqlite': - $cmd = "sqlite3 $database .dump"; - break; - default: - $cmd = false; - } + switch ($software) { + case 'mysql': + $cmd = "mysqldump -h$hostname -u$username -p$password $database"; + break; + case 'pgsql': + putenv("PGPASSWORD=$password"); + $cmd = "pg_dump -h $hostname -U $username $database"; + break; + case 'sqlite': + $cmd = "sqlite3 $database .dump"; + break; + default: + $cmd = false; + } - //FIXME: .SQL dump is empty if cmd doesn't exist + //FIXME: .SQL dump is empty if cmd doesn't exist - if($cmd) { - $page->set_mode("data"); - $page->set_type("application/x-unknown"); - $page->set_filename('shimmie-'.date('Ymd').'.sql'); - $page->set_data(shell_exec($cmd)); - } + if ($cmd) { + $page->set_mode("data"); + $page->set_type("application/x-unknown"); + $page->set_filename('shimmie-'.date('Ymd').'.sql'); + $page->set_data(shell_exec($cmd)); + } - return false; - } + return false; + } - private function download_all_images() { - global $database, $page; + private function download_all_images() + { + global $database, $page; - $images = $database->get_all("SELECT hash, ext FROM images"); - $filename = data_path('imgdump-'.date('Ymd').'.zip'); + $images = $database->get_all("SELECT hash, ext FROM images"); + $filename = data_path('imgdump-'.date('Ymd').'.zip'); - $zip = new ZipArchive; - if($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === TRUE){ - foreach($images as $img){ - $img_loc = warehouse_path("images", $img["hash"], FALSE); - $zip->addFile($img_loc, $img["hash"].".".$img["ext"]); - } - $zip->close(); - } + $zip = new ZipArchive; + if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === true) { + foreach ($images as $img) { + $img_loc = warehouse_path("images", $img["hash"], false); + $zip->addFile($img_loc, $img["hash"].".".$img["ext"]); + } + $zip->close(); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link($filename)); //TODO: Delete file after downloaded? + $page->set_mode("redirect"); + $page->set_redirect(make_link($filename)); //TODO: Delete file after downloaded? - return false; // we do want a redirect, but a manual one - } + return false; // we do want a redirect, but a manual one + } - private function reset_image_ids() { + private function reset_image_ids() + { global $database; - //TODO: Make work with PostgreSQL + SQLite - //TODO: Update score_log (Having an optional ID column for score_log would be nice..) - preg_match("#^(?P\w+)\:(?:user=(?P\w+)(?:;|$)|password=(?P\w*)(?:;|$)|host=(?P[\w\.\-]+)(?:;|$)|dbname=(?P[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches); + //TODO: Make work with PostgreSQL + SQLite + //TODO: Update score_log (Having an optional ID column for score_log would be nice..) + preg_match("#^(?P\w+)\:(?:user=(?P\w+)(?:;|$)|password=(?P\w*)(?:;|$)|host=(?P[\w\.\-]+)(?:;|$)|dbname=(?P[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches); - if($matches['proto'] == "mysql"){ - $tables = $database->get_col("SELECT TABLE_NAME + if ($matches['proto'] == "mysql") { + $tables = $database->get_col("SELECT TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = :db AND REFERENCED_COLUMN_NAME = 'id' - AND REFERENCED_TABLE_NAME = 'images'", array("db" => $matches['dbname'])); + AND REFERENCED_TABLE_NAME = 'images'", ["db" => $matches['dbname']]); - $i = 1; - $ids = $database->get_col("SELECT id FROM images ORDER BY images.id ASC"); - foreach($ids as $id){ - $sql = "SET FOREIGN_KEY_CHECKS=0; + $i = 1; + $ids = $database->get_col("SELECT id FROM images ORDER BY images.id ASC"); + foreach ($ids as $id) { + $sql = "SET FOREIGN_KEY_CHECKS=0; UPDATE images SET id={$i} WHERE image_id={$id};"; - foreach($tables as $table){ - $sql .= "UPDATE {$table} SET image_id={$i} WHERE image_id={$id};"; - } + foreach ($tables as $table) { + $sql .= "UPDATE {$table} SET image_id={$i} WHERE image_id={$id};"; + } - $sql .= " SET FOREIGN_KEY_CHECKS=1;"; - $database->execute($sql); + $sql .= " SET FOREIGN_KEY_CHECKS=1;"; + $database->execute($sql); - $i++; - } - $database->execute("ALTER TABLE images AUTO_INCREMENT=".(count($ids) + 1)); - }elseif($matches['proto'] == "pgsql"){ - //TODO: Make this work with PostgreSQL - }elseif($matches['proto'] == "sqlite"){ - //TODO: Make this work with SQLite - } + $i++; + } + $database->execute("ALTER TABLE images AUTO_INCREMENT=".(count($ids) + 1)); + } elseif ($matches['proto'] == "pgsql") { + //TODO: Make this work with PostgreSQL + } elseif ($matches['proto'] == "sqlite") { + //TODO: Make this work with SQLite + } return true; } } - diff --git a/ext/admin/test.php b/ext/admin/test.php index 3f893899..39dc5508 100644 --- a/ext/admin/test.php +++ b/ext/admin/test.php @@ -1,84 +1,89 @@ get_page('admin'); - $this->assert_response(403); - $this->assert_title("Permission Denied"); +class AdminPageTest extends ShimmiePHPUnitTestCase +{ + public function testAuth() + { + $this->get_page('admin'); + $this->assert_response(403); + $this->assert_title("Permission Denied"); - $this->log_in_as_user(); - $this->get_page('admin'); - $this->assert_response(403); - $this->assert_title("Permission Denied"); + $this->log_in_as_user(); + $this->get_page('admin'); + $this->assert_response(403); + $this->assert_title("Permission Denied"); - $this->log_in_as_admin(); - $this->get_page('admin'); - $this->assert_response(200); - $this->assert_title("Admin Tools"); - } + $this->log_in_as_admin(); + $this->get_page('admin'); + $this->assert_response(200); + $this->assert_title("Admin Tools"); + } - public function testLowercase() { - $ts = time(); // we need a tag that hasn't been used before + public function testLowercase() + { + $ts = time(); // we need a tag that hasn't been used before - $this->log_in_as_admin(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "TeStCase$ts"); + $this->log_in_as_admin(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "TeStCase$ts"); - $this->get_page("post/view/$image_id_1"); - $this->assert_title("Image $image_id_1: TeStCase$ts"); + $this->get_page("post/view/$image_id_1"); + $this->assert_title("Image $image_id_1: TeStCase$ts"); - $this->get_page('admin'); - $this->assert_title("Admin Tools"); - //$this->click("All tags to lowercase"); - send_event(new AdminActionEvent('lowercase_all_tags')); + $this->get_page('admin'); + $this->assert_title("Admin Tools"); + //$this->click("All tags to lowercase"); + send_event(new AdminActionEvent('lowercase_all_tags')); - $this->get_page("post/view/$image_id_1"); - $this->assert_title("Image $image_id_1: testcase$ts"); + $this->get_page("post/view/$image_id_1"); + $this->assert_title("Image $image_id_1: testcase$ts"); - $this->delete_image($image_id_1); - } + $this->delete_image($image_id_1); + } - # FIXME: make sure the admin tools actually work - public function testRecount() { - $this->log_in_as_admin(); - $this->get_page('admin'); - $this->assert_title("Admin Tools"); + # FIXME: make sure the admin tools actually work + public function testRecount() + { + $this->log_in_as_admin(); + $this->get_page('admin'); + $this->assert_title("Admin Tools"); - //$this->click("Recount tag use"); - send_event(new AdminActionEvent('recount_tag_use')); - } + //$this->click("Recount tag use"); + send_event(new AdminActionEvent('recount_tag_use')); + } - public function testDump() { - $this->log_in_as_admin(); - $this->get_page('admin'); - $this->assert_title("Admin Tools"); + public function testDump() + { + $this->log_in_as_admin(); + $this->get_page('admin'); + $this->assert_title("Admin Tools"); - // this calls mysqldump which jams up travis prompting for a password - //$this->click("Download database contents"); - //send_event(new AdminActionEvent('database_dump')); - //$this->assert_response(200); - } + // this calls mysqldump which jams up travis prompting for a password + //$this->click("Download database contents"); + //send_event(new AdminActionEvent('database_dump')); + //$this->assert_response(200); + } - public function testDBQ() { - $this->log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); - $image_id_3 = $this->post_image("tests/favicon.png", "test"); + public function testDBQ() + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); + $image_id_3 = $this->post_image("tests/favicon.png", "test"); - $this->get_page("post/list/test/1"); - //$this->click("Delete All These Images"); - $_POST['query'] = 'test'; - //$_POST['reason'] = 'reason'; // non-null-reason = add a hash ban - send_event(new AdminActionEvent('delete_by_query')); + $this->get_page("post/list/test/1"); + //$this->click("Delete All These Images"); + $_POST['query'] = 'test'; + //$_POST['reason'] = 'reason'; // non-null-reason = add a hash ban + send_event(new AdminActionEvent('delete_by_query')); - $this->get_page("post/view/$image_id_1"); - $this->assert_response(404); - $this->get_page("post/view/$image_id_2"); - $this->assert_response(200); - $this->get_page("post/view/$image_id_3"); - $this->assert_response(404); + $this->get_page("post/view/$image_id_1"); + $this->assert_response(404); + $this->get_page("post/view/$image_id_2"); + $this->assert_response(200); + $this->get_page("post/view/$image_id_3"); + $this->assert_response(404); - $this->delete_image($image_id_1); - $this->delete_image($image_id_2); - $this->delete_image($image_id_3); - } + $this->delete_image($image_id_1); + $this->delete_image($image_id_2); + $this->delete_image($image_id_3); + } } - diff --git a/ext/admin/theme.php b/ext/admin/theme.php index 6cd83736..3e60d224 100644 --- a/ext/admin/theme.php +++ b/ext/admin/theme.php @@ -1,71 +1,76 @@ set_title("Admin Tools"); - $page->set_heading("Admin Tools"); - $page->add_block(new NavBlock()); - } + $page->set_title("Admin Tools"); + $page->set_heading("Admin Tools"); + $page->add_block(new NavBlock()); + } - protected function button(string $name, string $action, bool $protected=false): string { - $c_protected = $protected ? " protected" : ""; - $html = make_form(make_link("admin/$action"), "POST", false, "admin$c_protected"); - if($protected) { - $html .= ""; - $html .= ""; - } - else { - $html .= ""; - } - $html .= "\n"; - return $html; - } + protected function button(string $name, string $action, bool $protected=false): string + { + $c_protected = $protected ? " protected" : ""; + $html = make_form(make_link("admin/$action"), "POST", false, "admin$c_protected"); + if ($protected) { + $html .= ""; + $html .= ""; + } else { + $html .= ""; + } + $html .= "\n"; + return $html; + } - /* - * Show a form which links to admin_utils with POST[action] set to one of: - * 'lowercase all tags' - * 'recount tag use' - * etc - */ - public function display_form() { - global $page, $database; + /* + * Show a form which links to admin_utils with POST[action] set to one of: + * 'lowercase all tags' + * 'recount tag use' + * etc + */ + public function display_form() + { + global $page, $database; - $html = ""; - $html .= $this->button("All tags to lowercase", "lowercase_all_tags", true); - $html .= $this->button("Recount tag use", "recount_tag_use", false); - if(class_exists('ZipArchive')) - $html .= $this->button("Download all images", "download_all_images", false); + $html = ""; + $html .= $this->button("All tags to lowercase", "lowercase_all_tags", true); + $html .= $this->button("Recount tag use", "recount_tag_use", false); + if (class_exists('ZipArchive')) { + $html .= $this->button("Download all images", "download_all_images", false); + } $html .= $this->button("Download database contents", "database_dump", false); - if($database->get_driver_name() == "mysql") - $html .= $this->button("Reset image IDs", "reset_image_ids", true); - $page->add_block(new Block("Misc Admin Tools", $html)); + if ($database->get_driver_name() == "mysql") { + $html .= $this->button("Reset image IDs", "reset_image_ids", true); + } + $page->add_block(new Block("Misc Admin Tools", $html)); - $html = make_form(make_link("admin/set_tag_case"), "POST"); - $html .= ""; - $html .= ""; - $html .= "\n"; - $page->add_block(new Block("Set Tag Case", $html)); - } + $html = make_form(make_link("admin/set_tag_case"), "POST"); + $html .= ""; + $html .= ""; + $html .= "\n"; + $page->add_block(new Block("Set Tag Case", $html)); + } - public function dbq_html($terms) { - $h_terms = html_escape($terms); - $h_reason = ""; - if(class_exists("ImageBan")) { - $h_reason = ""; - } - $html = make_form(make_link("admin/delete_by_query"), "POST") . " + public function dbq_html($terms) + { + $h_terms = html_escape($terms); + $h_reason = ""; + if (class_exists("ImageBan")) { + $h_reason = ""; + } + $html = make_form(make_link("admin/delete_by_query"), "POST") . " $h_reason "; - return $html; - } + return $html; + } } - diff --git a/ext/alias_editor/main.php b/ext/alias_editor/main.php index 40c0117a..9e7139cf 100644 --- a/ext/alias_editor/main.php +++ b/ext/alias_editor/main.php @@ -10,155 +10,156 @@ * site admins can edit it, other people can view and download it */ -class AddAliasEvent extends Event { - /** @var string */ - public $oldtag; - /** @var string */ - public $newtag; +class AddAliasEvent extends Event +{ + /** @var string */ + public $oldtag; + /** @var string */ + public $newtag; - public function __construct(string $oldtag, string $newtag) { - $this->oldtag = trim($oldtag); - $this->newtag = trim($newtag); - } + public function __construct(string $oldtag, string $newtag) + { + $this->oldtag = trim($oldtag); + $this->newtag = trim($newtag); + } } -class AddAliasException extends SCoreException {} - -class AliasEditor extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $config, $database, $page, $user; - - if($event->page_matches("alias")) { - if($event->get_arg(0) == "add") { - if($user->can("manage_alias_list")) { - if(isset($_POST['oldtag']) && isset($_POST['newtag'])) { - try { - $aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']); - send_event($aae); - $page->set_mode("redirect"); - $page->set_redirect(make_link("alias/list")); - } - catch(AddAliasException $ex) { - $this->theme->display_error(500, "Error adding alias", $ex->getMessage()); - } - } - } - } - else if($event->get_arg(0) == "remove") { - if($user->can("manage_alias_list")) { - if(isset($_POST['oldtag'])) { - $database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", array("oldtag" => $_POST['oldtag'])); - log_info("alias_editor", "Deleted alias for ".$_POST['oldtag'], "Deleted alias"); - - $page->set_mode("redirect"); - $page->set_redirect(make_link("alias/list")); - } - } - } - else if($event->get_arg(0) == "list") { - $page_number = $event->get_arg(1); - if(is_null($page_number) || !is_numeric($page_number)) { - $page_number = 0; - } - else if ($page_number <= 0) { - $page_number = 0; - } - else { - $page_number--; - } - - $alias_per_page = $config->get_int('alias_items_per_page', 30); - - $query = "SELECT oldtag, newtag FROM aliases ORDER BY newtag ASC LIMIT :limit OFFSET :offset"; - $alias = $database->get_pairs($query, - array("limit"=>$alias_per_page, "offset"=>$page_number * $alias_per_page) - ); - - $total_pages = ceil($database->get_one("SELECT COUNT(*) FROM aliases") / $alias_per_page); - - $this->theme->display_aliases($alias, $page_number + 1, $total_pages); - } - else if($event->get_arg(0) == "export") { - $page->set_mode("data"); - $page->set_type("text/csv"); - $page->set_filename("aliases.csv"); - $page->set_data($this->get_alias_csv($database)); - } - else if($event->get_arg(0) == "import") { - if($user->can("manage_alias_list")) { - if(count($_FILES) > 0) { - $tmp = $_FILES['alias_file']['tmp_name']; - $contents = file_get_contents($tmp); - $this->add_alias_csv($database, $contents); - log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many? - $page->set_mode("redirect"); - $page->set_redirect(make_link("alias/list")); - } - else { - $this->theme->display_error(400, "No File Specified", "You have to upload a file"); - } - } - else { - $this->theme->display_error(401, "Admins Only", "Only admins can edit the alias list"); - } - } - } - } - - public function onAddAlias(AddAliasEvent $event) { - global $database; - $pair = array("oldtag" => $event->oldtag, "newtag" => $event->newtag); - if($database->get_row("SELECT * FROM aliases WHERE oldtag=:oldtag AND lower(newtag)=lower(:newtag)", $pair)) { - throw new AddAliasException("That alias already exists"); - } - else if($database->get_row("SELECT * FROM aliases WHERE oldtag=:newtag", array("newtag" => $event->newtag))) { - throw new AddAliasException("{$event->newtag} is itself an alias"); - } - else { - $database->execute("INSERT INTO aliases(oldtag, newtag) VALUES(:oldtag, :newtag)", $pair); - log_info("alias_editor", "Added alias for {$event->oldtag} -> {$event->newtag}", "Added alias"); - } - } - - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("manage_alias_list")) { - $event->add_link("Alias Editor", make_link("alias/list")); - } - } - - private function get_alias_csv(Database $database): string { - $csv = ""; - $aliases = $database->get_pairs("SELECT oldtag, newtag FROM aliases ORDER BY newtag"); - foreach($aliases as $old => $new) { - $csv .= "\"$old\",\"$new\"\n"; - } - return $csv; - } - - private function add_alias_csv(Database $database, string $csv) { - $csv = str_replace("\r", "\n", $csv); - foreach(explode("\n", $csv) as $line) { - $parts = str_getcsv($line); - if(count($parts) == 2) { - try { - $aae = new AddAliasEvent($parts[0], $parts[1]); - send_event($aae); - } - catch(AddAliasException $ex) { - $this->theme->display_error(500, "Error adding alias", $ex->getMessage()); - } - } - } - } - - /** - * Get the priority for this extension. - * - * Add alias *after* mass tag editing, else the MTE will - * search for the images and be redirected to the alias, - * missing out the images tagged with the old tag. - */ - public function get_priority(): int {return 60;} +class AddAliasException extends SCoreException +{ } +class AliasEditor extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $config, $database, $page, $user; + + if ($event->page_matches("alias")) { + if ($event->get_arg(0) == "add") { + if ($user->can("manage_alias_list")) { + if (isset($_POST['oldtag']) && isset($_POST['newtag'])) { + try { + $aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']); + send_event($aae); + $page->set_mode("redirect"); + $page->set_redirect(make_link("alias/list")); + } catch (AddAliasException $ex) { + $this->theme->display_error(500, "Error adding alias", $ex->getMessage()); + } + } + } + } elseif ($event->get_arg(0) == "remove") { + if ($user->can("manage_alias_list")) { + if (isset($_POST['oldtag'])) { + $database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", ["oldtag" => $_POST['oldtag']]); + log_info("alias_editor", "Deleted alias for ".$_POST['oldtag'], "Deleted alias"); + + $page->set_mode("redirect"); + $page->set_redirect(make_link("alias/list")); + } + } + } elseif ($event->get_arg(0) == "list") { + $page_number = $event->get_arg(1); + if (is_null($page_number) || !is_numeric($page_number)) { + $page_number = 0; + } elseif ($page_number <= 0) { + $page_number = 0; + } else { + $page_number--; + } + + $alias_per_page = $config->get_int('alias_items_per_page', 30); + + $query = "SELECT oldtag, newtag FROM aliases ORDER BY newtag ASC LIMIT :limit OFFSET :offset"; + $alias = $database->get_pairs( + $query, + ["limit"=>$alias_per_page, "offset"=>$page_number * $alias_per_page] + ); + + $total_pages = ceil($database->get_one("SELECT COUNT(*) FROM aliases") / $alias_per_page); + + $this->theme->display_aliases($alias, $page_number + 1, $total_pages); + } elseif ($event->get_arg(0) == "export") { + $page->set_mode("data"); + $page->set_type("text/csv"); + $page->set_filename("aliases.csv"); + $page->set_data($this->get_alias_csv($database)); + } elseif ($event->get_arg(0) == "import") { + if ($user->can("manage_alias_list")) { + if (count($_FILES) > 0) { + $tmp = $_FILES['alias_file']['tmp_name']; + $contents = file_get_contents($tmp); + $this->add_alias_csv($database, $contents); + log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many? + $page->set_mode("redirect"); + $page->set_redirect(make_link("alias/list")); + } else { + $this->theme->display_error(400, "No File Specified", "You have to upload a file"); + } + } else { + $this->theme->display_error(401, "Admins Only", "Only admins can edit the alias list"); + } + } + } + } + + public function onAddAlias(AddAliasEvent $event) + { + global $database; + $pair = ["oldtag" => $event->oldtag, "newtag" => $event->newtag]; + if ($database->get_row("SELECT * FROM aliases WHERE oldtag=:oldtag AND lower(newtag)=lower(:newtag)", $pair)) { + throw new AddAliasException("That alias already exists"); + } elseif ($database->get_row("SELECT * FROM aliases WHERE oldtag=:newtag", ["newtag" => $event->newtag])) { + throw new AddAliasException("{$event->newtag} is itself an alias"); + } else { + $database->execute("INSERT INTO aliases(oldtag, newtag) VALUES(:oldtag, :newtag)", $pair); + log_info("alias_editor", "Added alias for {$event->oldtag} -> {$event->newtag}", "Added alias"); + } + } + + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("manage_alias_list")) { + $event->add_link("Alias Editor", make_link("alias/list")); + } + } + + private function get_alias_csv(Database $database): string + { + $csv = ""; + $aliases = $database->get_pairs("SELECT oldtag, newtag FROM aliases ORDER BY newtag"); + foreach ($aliases as $old => $new) { + $csv .= "\"$old\",\"$new\"\n"; + } + return $csv; + } + + private function add_alias_csv(Database $database, string $csv) + { + $csv = str_replace("\r", "\n", $csv); + foreach (explode("\n", $csv) as $line) { + $parts = str_getcsv($line); + if (count($parts) == 2) { + try { + $aae = new AddAliasEvent($parts[0], $parts[1]); + send_event($aae); + } catch (AddAliasException $ex) { + $this->theme->display_error(500, "Error adding alias", $ex->getMessage()); + } + } + } + } + + /** + * Get the priority for this extension. + * + * Add alias *after* mass tag editing, else the MTE will + * search for the images and be redirected to the alias, + * missing out the images tagged with the old tag. + */ + public function get_priority(): int + { + return 60; + } +} diff --git a/ext/alias_editor/test.php b/ext/alias_editor/test.php index 0b8e4512..b2bbe00c 100644 --- a/ext/alias_editor/test.php +++ b/ext/alias_editor/test.php @@ -1,104 +1,107 @@ get_page('alias/list'); - $this->assert_response(200); - $this->assert_title("Alias List"); - } +class AliasEditorTest extends ShimmiePHPUnitTestCase +{ + public function testAliasList() + { + $this->get_page('alias/list'); + $this->assert_response(200); + $this->assert_title("Alias List"); + } - public function testAliasListReadOnly() { - // Check that normal users can't add aliases. - $this->log_in_as_user(); - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->assert_no_text("Add"); - } + public function testAliasListReadOnly() + { + // Check that normal users can't add aliases. + $this->log_in_as_user(); + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->assert_no_text("Add"); + } - public function testAliasEditor() { - /* - ********************************************************************** - * FIXME: TODO: - * For some reason the alias tests always fail when they are running - * inside the TravisCI VM environment. I have tried to determine - * the exact cause of this, but have been unable to pin it down. - * - * For now, I am commenting them out until I have more time to - * dig into this and determine exactly what is happening. - * - ********************************************************************* - */ - $this->markTestIncomplete(); + public function testAliasEditor() + { + /* + ********************************************************************** + * FIXME: TODO: + * For some reason the alias tests always fail when they are running + * inside the TravisCI VM environment. I have tried to determine + * the exact cause of this, but have been unable to pin it down. + * + * For now, I am commenting them out until I have more time to + * dig into this and determine exactly what is happening. + * + ********************************************************************* + */ + $this->markTestIncomplete(); - $this->log_in_as_admin(); + $this->log_in_as_admin(); - # test one to one - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->set_field('oldtag', "test1"); - $this->set_field('newtag', "test2"); - $this->clickSubmit('Add'); - $this->assert_no_text("Error adding alias"); + # test one to one + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->set_field('oldtag', "test1"); + $this->set_field('newtag', "test2"); + $this->clickSubmit('Add'); + $this->assert_no_text("Error adding alias"); - $this->get_page('alias/list'); - $this->assert_text("test1"); + $this->get_page('alias/list'); + $this->assert_text("test1"); - $this->get_page("alias/export/aliases.csv"); - $this->assert_text("test1,test2"); + $this->get_page("alias/export/aliases.csv"); + $this->assert_text("test1,test2"); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test1"); - $this->get_page("post/view/$image_id"); # check that the tag has been replaced - $this->assert_title("Image $image_id: test2"); - $this->get_page("post/list/test1/1"); # searching for an alias should find the master tag - $this->assert_title("Image $image_id: test2"); - $this->get_page("post/list/test2/1"); # check that searching for the main tag still works - $this->assert_title("Image $image_id: test2"); - $this->delete_image($image_id); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test1"); + $this->get_page("post/view/$image_id"); # check that the tag has been replaced + $this->assert_title("Image $image_id: test2"); + $this->get_page("post/list/test1/1"); # searching for an alias should find the master tag + $this->assert_title("Image $image_id: test2"); + $this->get_page("post/list/test2/1"); # check that searching for the main tag still works + $this->assert_title("Image $image_id: test2"); + $this->delete_image($image_id); - $this->get_page('alias/list'); - $this->click("Remove"); - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->assert_no_text("test1"); + $this->get_page('alias/list'); + $this->click("Remove"); + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->assert_no_text("test1"); - # test one to many - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->set_field('oldtag', "onetag"); - $this->set_field('newtag', "multi tag"); - $this->click("Add"); - $this->get_page('alias/list'); - $this->assert_text("multi"); - $this->assert_text("tag"); + # test one to many + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->set_field('oldtag', "onetag"); + $this->set_field('newtag', "multi tag"); + $this->click("Add"); + $this->get_page('alias/list'); + $this->assert_text("multi"); + $this->assert_text("tag"); - $this->get_page("alias/export/aliases.csv"); - $this->assert_text("onetag,multi tag"); + $this->get_page("alias/export/aliases.csv"); + $this->assert_text("onetag,multi tag"); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "onetag"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "onetag"); - // FIXME: known broken - //$this->get_page("post/list/onetag/1"); # searching for an aliased tag should find its aliases - //$this->assert_title("onetag"); - //$this->assert_no_text("No Images Found"); - $this->get_page("post/list/multi/1"); - $this->assert_title("multi"); - $this->assert_no_text("No Images Found"); - $this->get_page("post/list/multi%20tag/1"); - $this->assert_title("multi tag"); - $this->assert_no_text("No Images Found"); - $this->delete_image($image_id_1); - $this->delete_image($image_id_2); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "onetag"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "onetag"); + // FIXME: known broken + //$this->get_page("post/list/onetag/1"); # searching for an aliased tag should find its aliases + //$this->assert_title("onetag"); + //$this->assert_no_text("No Images Found"); + $this->get_page("post/list/multi/1"); + $this->assert_title("multi"); + $this->assert_no_text("No Images Found"); + $this->get_page("post/list/multi%20tag/1"); + $this->assert_title("multi tag"); + $this->assert_no_text("No Images Found"); + $this->delete_image($image_id_1); + $this->delete_image($image_id_2); - $this->get_page('alias/list'); - $this->click("Remove"); - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->assert_no_text("test1"); + $this->get_page('alias/list'); + $this->click("Remove"); + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->assert_no_text("test1"); - $this->log_out(); + $this->log_out(); - $this->get_page('alias/list'); - $this->assert_title("Alias List"); - $this->assert_no_text("Add"); - } + $this->get_page('alias/list'); + $this->assert_title("Alias List"); + $this->assert_no_text("Add"); + } } - diff --git a/ext/alias_editor/theme.php b/ext/alias_editor/theme.php index 51e65f2b..ec12348e 100644 --- a/ext/alias_editor/theme.php +++ b/ext/alias_editor/theme.php @@ -1,18 +1,20 @@ can("manage_alias_list"); - if($can_manage) { - $h_action = "Action"; - $h_add = " + $can_manage = $user->can("manage_alias_list"); + if ($can_manage) { + $h_action = "Action"; + $h_add = " ".make_form(make_link("alias/add"))." @@ -21,20 +23,19 @@ class AliasEditorTheme extends Themelet { "; - } - else { - $h_action = ""; - $h_add = ""; - } + } else { + $h_action = ""; + $h_add = ""; + } - $h_aliases = ""; - foreach($aliases as $old => $new) { - $h_old = html_escape($old); - $h_new = "".html_escape($new).""; + $h_aliases = ""; + foreach ($aliases as $old => $new) { + $h_old = html_escape($old); + $h_new = "".html_escape($new).""; - $h_aliases .= "$h_old$h_new"; - if($can_manage) { - $h_aliases .= " + $h_aliases .= "$h_old$h_new"; + if ($can_manage) { + $h_aliases .= " ".make_form(make_link("alias/remove"))." @@ -42,10 +43,10 @@ class AliasEditorTheme extends Themelet { "; - } - $h_aliases .= ""; - } - $html = " + } + $h_aliases .= ""; + } + $html = " $h_action$h_aliases @@ -54,22 +55,21 @@ class AliasEditorTheme extends Themelet {

Download as CSV

"; - $bulk_html = " + $bulk_html = " ".make_form(make_link("alias/import"), 'post', true)." "; - $page->set_title("Alias List"); - $page->set_heading("Alias List"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Aliases", $html)); - if($can_manage) { - $page->add_block(new Block("Bulk Upload", $bulk_html, "main", 51)); - } + $page->set_title("Alias List"); + $page->set_heading("Alias List"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Aliases", $html)); + if ($can_manage) { + $page->add_block(new Block("Bulk Upload", $bulk_html, "main", 51)); + } - $this->display_paginator($page, "alias/list", null, $pageNumber, $totalPages); - } + $this->display_paginator($page, "alias/list", null, $pageNumber, $totalPages); + } } - diff --git a/ext/amazon_s3/main.php b/ext/amazon_s3/main.php index a0fda3a4..c2f4514f 100644 --- a/ext/amazon_s3/main.php +++ b/ext/amazon_s3/main.php @@ -9,67 +9,71 @@ require_once "ext/amazon_s3/lib/S3.php"; -class UploadS3 extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string("amazon_s3_access", ""); - $config->set_default_string("amazon_s3_secret", ""); - $config->set_default_string("amazon_s3_bucket", ""); - } +class UploadS3 extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string("amazon_s3_access", ""); + $config->set_default_string("amazon_s3_secret", ""); + $config->set_default_string("amazon_s3_bucket", ""); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Amazon S3"); - $sb->add_text_option("amazon_s3_access", "Access key: "); - $sb->add_text_option("amazon_s3_secret", "
Secret key: "); - $sb->add_text_option("amazon_s3_bucket", "
Bucket: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Amazon S3"); + $sb->add_text_option("amazon_s3_access", "Access key: "); + $sb->add_text_option("amazon_s3_secret", "
Secret key: "); + $sb->add_text_option("amazon_s3_bucket", "
Bucket: "); + $event->panel->add_block($sb); + } - public function onImageAddition(ImageAdditionEvent $event) { - global $config; - $access = $config->get_string("amazon_s3_access"); - $secret = $config->get_string("amazon_s3_secret"); - $bucket = $config->get_string("amazon_s3_bucket"); - if(!empty($bucket)) { - log_debug("amazon_s3", "Mirroring Image #".$event->image->id." to S3 #$bucket"); - $s3 = new S3($access, $secret); - $s3->putBucket($bucket, S3::ACL_PUBLIC_READ); - $s3->putObjectFile( - warehouse_path("thumbs", $event->image->hash), - $bucket, - 'thumbs/'.$event->image->hash, - S3::ACL_PUBLIC_READ, - array(), - array( - "Content-Type" => "image/jpeg", - "Content-Disposition" => "inline; filename=image-" . $event->image->id . ".jpg", - ) - ); - $s3->putObjectFile( - warehouse_path("images", $event->image->hash), - $bucket, - 'images/'.$event->image->hash, - S3::ACL_PUBLIC_READ, - array(), - array( - "Content-Type" => $event->image->get_mime_type(), - "Content-Disposition" => "inline; filename=image-" . $event->image->id . "." . $event->image->ext, - ) - ); - } - } + public function onImageAddition(ImageAdditionEvent $event) + { + global $config; + $access = $config->get_string("amazon_s3_access"); + $secret = $config->get_string("amazon_s3_secret"); + $bucket = $config->get_string("amazon_s3_bucket"); + if (!empty($bucket)) { + log_debug("amazon_s3", "Mirroring Image #".$event->image->id." to S3 #$bucket"); + $s3 = new S3($access, $secret); + $s3->putBucket($bucket, S3::ACL_PUBLIC_READ); + $s3->putObjectFile( + warehouse_path("thumbs", $event->image->hash), + $bucket, + 'thumbs/'.$event->image->hash, + S3::ACL_PUBLIC_READ, + [], + [ + "Content-Type" => "image/jpeg", + "Content-Disposition" => "inline; filename=image-" . $event->image->id . ".jpg", + ] + ); + $s3->putObjectFile( + warehouse_path("images", $event->image->hash), + $bucket, + 'images/'.$event->image->hash, + S3::ACL_PUBLIC_READ, + [], + [ + "Content-Type" => $event->image->get_mime_type(), + "Content-Disposition" => "inline; filename=image-" . $event->image->id . "." . $event->image->ext, + ] + ); + } + } - public function onImageDeletion(ImageDeletionEvent $event) { - global $config; - $access = $config->get_string("amazon_s3_access"); - $secret = $config->get_string("amazon_s3_secret"); - $bucket = $config->get_string("amazon_s3_bucket"); - if(!empty($bucket)) { - log_debug("amazon_s3", "Deleting Image #".$event->image->id." from S3"); - $s3 = new S3($access, $secret); - $s3->deleteObject($bucket, "images/" . $event->image->hash); - $s3->deleteObject($bucket, "thumbs/" . $event->image->hash); - } - } + public function onImageDeletion(ImageDeletionEvent $event) + { + global $config; + $access = $config->get_string("amazon_s3_access"); + $secret = $config->get_string("amazon_s3_secret"); + $bucket = $config->get_string("amazon_s3_bucket"); + if (!empty($bucket)) { + log_debug("amazon_s3", "Deleting Image #".$event->image->id." from S3"); + $s3 = new S3($access, $secret); + $s3->deleteObject($bucket, "images/" . $event->image->hash); + $s3->deleteObject($bucket, "thumbs/" . $event->image->hash); + } + } } - diff --git a/ext/arrowkey_navigation/main.php b/ext/arrowkey_navigation/main.php index 01a504f7..209fbf04 100644 --- a/ext/arrowkey_navigation/main.php +++ b/ext/arrowkey_navigation/main.php @@ -8,35 +8,39 @@ * Documentation: * Simply enable this extention in the extention manager to enable arrow key navigation. */ -class ArrowkeyNavigation extends Extension { - /** - * Adds functionality for post/view on images. - */ - public function onDisplayingImage(DisplayingImageEvent $event) { - $prev_url = make_http(make_link("post/prev/".$event->image->id)); - $next_url = make_http(make_link("post/next/".$event->image->id)); - $this->add_arrowkeys_code($prev_url, $next_url); - } +class ArrowkeyNavigation extends Extension +{ + /** + * Adds functionality for post/view on images. + */ + public function onDisplayingImage(DisplayingImageEvent $event) + { + $prev_url = make_http(make_link("post/prev/".$event->image->id)); + $next_url = make_http(make_link("post/next/".$event->image->id)); + $this->add_arrowkeys_code($prev_url, $next_url); + } - /** - * Adds functionality for post/list. - */ - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("post/list")) { - $pageinfo = $this->get_list_pageinfo($event); - $prev_url = make_http(make_link("post/list/".$pageinfo["prev"])); - $next_url = make_http(make_link("post/list/".$pageinfo["next"])); - $this->add_arrowkeys_code($prev_url, $next_url); - } - } + /** + * Adds functionality for post/list. + */ + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("post/list")) { + $pageinfo = $this->get_list_pageinfo($event); + $prev_url = make_http(make_link("post/list/".$pageinfo["prev"])); + $next_url = make_http(make_link("post/list/".$pageinfo["next"])); + $this->add_arrowkeys_code($prev_url, $next_url); + } + } - /** - * Adds the javascript to the page with the given urls. - */ - private function add_arrowkeys_code(string $prev_url, string $next_url) { - global $page; + /** + * Adds the javascript to the page with the given urls. + */ + private function add_arrowkeys_code(string $prev_url, string $next_url) + { + global $page; - $page->add_html_header("", 60); - } + } - /** - * Returns info about the current page number. - */ - private function get_list_pageinfo(PageRequestEvent $event): array { - global $config, $database; + /** + * Returns info about the current page number. + */ + private function get_list_pageinfo(PageRequestEvent $event): array + { + global $config, $database; - // get the amount of images per page - $images_per_page = $config->get_int('index_images'); + // get the amount of images per page + $images_per_page = $config->get_int('index_images'); - // if there are no tags, use default - if (is_null($event->get_arg(1))){ - $prefix = ""; - $page_number = int_escape($event->get_arg(0)); - $total_pages = ceil($database->get_one( - "SELECT COUNT(*) FROM images") / $images_per_page); - } - else { // if there are tags, use pages with tags - $prefix = url_escape($event->get_arg(0)) . "/"; - $page_number = int_escape($event->get_arg(1)); - $total_pages = ceil($database->get_one( - "SELECT count FROM tags WHERE tag=:tag", - array("tag"=>$event->get_arg(0))) / $images_per_page); - } + // if there are no tags, use default + if (is_null($event->get_arg(1))) { + $prefix = ""; + $page_number = int_escape($event->get_arg(0)); + $total_pages = ceil($database->get_one( + "SELECT COUNT(*) FROM images" + ) / $images_per_page); + } else { // if there are tags, use pages with tags + $prefix = url_escape($event->get_arg(0)) . "/"; + $page_number = int_escape($event->get_arg(1)); + $total_pages = ceil($database->get_one( + "SELECT count FROM tags WHERE tag=:tag", + ["tag"=>$event->get_arg(0)] + ) / $images_per_page); + } - // creates previous & next values - // When previous first page, go to last page - if ($page_number <= 1) $prev = $total_pages; - else $prev = $page_number-1; - if ($page_number >= $total_pages) $next = 1; - else $next = $page_number+1; + // creates previous & next values + // When previous first page, go to last page + if ($page_number <= 1) { + $prev = $total_pages; + } else { + $prev = $page_number-1; + } + if ($page_number >= $total_pages) { + $next = 1; + } else { + $next = $page_number+1; + } - // Create return array - $pageinfo = array( - "prev" => $prefix.$prev, - "next" => $prefix.$next, - ); + // Create return array + $pageinfo = [ + "prev" => $prefix.$prev, + "next" => $prefix.$next, + ]; - return $pageinfo; - } + return $pageinfo; + } } - diff --git a/ext/artists/main.php b/ext/artists/main.php index c2f0da73..bb1343d3 100644 --- a/ext/artists/main.php +++ b/ext/artists/main.php @@ -8,49 +8,56 @@ * Documentation: * */ -class AuthorSetEvent extends Event { - /** @var \Image */ - public $image; - /** @var \User */ - public $user; - /** @var string */ - public $author; +class AuthorSetEvent extends Event +{ + /** @var \Image */ + public $image; + /** @var \User */ + public $user; + /** @var string */ + public $author; - public function __construct(Image $image, User $user, string $author) { + public function __construct(Image $image, User $user, string $author) + { $this->image = $image; $this->user = $user; $this->author = $author; } } -class Artists extends Extension { - public function onImageInfoSet(ImageInfoSetEvent $event) { +class Artists extends Extension +{ + public function onImageInfoSet(ImageInfoSetEvent $event) + { global $user; - if (isset($_POST["tag_edit__author"])) { - send_event(new AuthorSetEvent($event->image, $user, $_POST["tag_edit__author"])); - } - } + if (isset($_POST["tag_edit__author"])) { + send_event(new AuthorSetEvent($event->image, $user, $_POST["tag_edit__author"])); + } + } - public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { + public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) + { global $user; $artistName = $this->get_artistName_by_imageID($event->image->id); - if(!$user->is_anonymous()) { + if (!$user->is_anonymous()) { $event->add_part($this->theme->get_author_editor_html($artistName), 42); } - } + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - if(preg_match("/^author[=|:](.*)$/i", $event->term, $matches)) { - $char = $matches[1]; - $event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char))); - } - } + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + if (preg_match("/^author[=|:](.*)$/i", $event->term, $matches)) { + $char = $matches[1]; + $event->add_querylet(new Querylet("Author = :author_char", ["author_char"=>$char])); + } + } - public function onInitExt(InitExtEvent $event) { - global $config, $database; + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - if ($config->get_int("ext_artists_version") < 1) { + if ($config->get_int("ext_artists_version") < 1) { $database->create_table("artists", " id SCORE_AIPK, user_id INTEGER NOT NULL, @@ -60,7 +67,7 @@ class Artists extends Extension { notes TEXT, FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE "); - + $database->create_table("artist_members", " id SCORE_AIPK, artist_id INTEGER NOT NULL, @@ -100,47 +107,53 @@ class Artists extends Extension { } } - public function onAuthorSet(AuthorSetEvent $event) { + public function onAuthorSet(AuthorSetEvent $event) + { global $database; $author = strtolower($event->author); - if (strlen($author) === 0 || strpos($author, " ")) - return; + if (strlen($author) === 0 || strpos($author, " ")) { + return; + } $paddedAuthor = str_replace(" ", "_", $author); - $artistID = NULL; - if ($this->artist_exists($author)) + $artistID = null; + if ($this->artist_exists($author)) { $artistID = $this->get_artist_id($author); + } - if (is_null($artistID) && $this->alias_exists_by_name($paddedAuthor)) + if (is_null($artistID) && $this->alias_exists_by_name($paddedAuthor)) { $artistID = $this->get_artistID_by_aliasName($paddedAuthor); + } - if (is_null($artistID) && $this->member_exists_by_name($paddedAuthor)) + if (is_null($artistID) && $this->member_exists_by_name($paddedAuthor)) { $artistID = $this->get_artistID_by_memberName($paddedAuthor); + } - if (is_null($artistID) && $this->url_exists_by_url($author)) + if (is_null($artistID) && $this->url_exists_by_url($author)) { $artistID = $this->get_artistID_by_url($author); + } if (!is_null($artistID)) { $artistName = $this->get_artistName_by_artistID($artistID); - } - else { + } else { $this->save_new_artist($author, ""); $artistName = $author; } $database->execute( "UPDATE images SET author = ? WHERE id = ?", - array($artistName, $event->image->id) + [$artistName, $event->image->id] ); } - public function onPageRequest(PageRequestEvent $event) { + public function onPageRequest(PageRequestEvent $event) + { global $page, $user; - if($event->page_matches("artist")) { - switch($event->get_arg(0)) { + if ($event->page_matches("artist")) { + switch ($event->get_arg(0)) { //*************ARTIST SECTION************** case "list": { @@ -150,10 +163,9 @@ class Artists extends Extension { } case "new": { - if(!$user->is_anonymous()) { - $this->theme->new_artist_composer(); - } - else { + if (!$user->is_anonymous()) { + $this->theme->new_artist_composer(); + } else { $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist."); } break; @@ -166,17 +178,15 @@ class Artists extends Extension { } case "create": { - if(!$user->is_anonymous()) { + if (!$user->is_anonymous()) { $newArtistID = $this->add_artist(); if ($newArtistID == -1) { $this->theme->display_error(400, "Error", "Error when entering artist data."); - } - else { + } else { $page->set_mode("redirect"); $page->set_redirect(make_link("artist/view/".$newArtistID)); } - } - else { + } else { $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist."); } break; @@ -192,7 +202,7 @@ class Artists extends Extension { $userIsLogged = !$user->is_anonymous(); $userIsAdmin = $user->is_admin(); - + $images = Image::find_images(0, 4, Tag::explode($artist['name'])); $this->theme->show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin); @@ -201,9 +211,9 @@ class Artists extends Extension { //$this->theme->show_new_member_composer($artistID); //$this->theme->show_new_url_composer($artistID); } - + $this->theme->sidebar_options("editor", $artistID, $userIsAdmin); - + break; } @@ -214,14 +224,13 @@ class Artists extends Extension { $aliases = $this->get_alias($artistID); $members = $this->get_members($artistID); $urls = $this->get_urls($artistID); - - if(!$user->is_anonymous()) { - $this->theme->show_artist_editor($artist, $aliases, $members, $urls); - + + if (!$user->is_anonymous()) { + $this->theme->show_artist_editor($artist, $aliases, $members, $urls); + $userIsAdmin = $user->is_admin(); $this->theme->sidebar_options("editor", $artistID, $userIsAdmin); - } - else { + } else { $this->theme->display_error(401, "Error", "You must be registered and logged in to edit an artist."); } break; @@ -277,8 +286,7 @@ class Artists extends Extension { //***********ALIAS SECTION *********************** case "alias": { - switch ($event->get_arg(1)) - { + switch ($event->get_arg(1)) { case "add": { $artistID = $_POST['artistID']; @@ -319,8 +327,7 @@ class Artists extends Extension { //**************** URLS SECTION ********************** case "url": { - switch ($event->get_arg(1)) - { + switch ($event->get_arg(1)) { case "add": { $artistID = $_POST['artistID']; @@ -360,8 +367,7 @@ class Artists extends Extension { //******************* MEMBERS SECTION ********************* case "member": { - switch ($event->get_arg(1)) - { + switch ($event->get_arg(1)) { case "add": { $artistID = $_POST['artistID']; @@ -402,116 +408,134 @@ class Artists extends Extension { } } - private function get_artistName_by_imageID(int $imageID): string { + private function get_artistName_by_imageID(int $imageID): string + { global $database; - $result = $database->get_row("SELECT author FROM images WHERE id = ?", array($imageID)); + $result = $database->get_row("SELECT author FROM images WHERE id = ?", [$imageID]); return stripslashes($result['author']); } - private function url_exists_by_url(string $url): bool { + private function url_exists_by_url(string $url): bool + { global $database; - $result = $database->get_one("SELECT COUNT(1) FROM artist_urls WHERE url = ?", array($url)); + $result = $database->get_one("SELECT COUNT(1) FROM artist_urls WHERE url = ?", [$url]); return ($result != 0); } - private function member_exists_by_name(string $member): bool { + private function member_exists_by_name(string $member): bool + { global $database; - $result = $database->get_one("SELECT COUNT(1) FROM artist_members WHERE name = ?", array($member)); + $result = $database->get_one("SELECT COUNT(1) FROM artist_members WHERE name = ?", [$member]); return ($result != 0); } - private function alias_exists_by_name(string $alias): bool { + private function alias_exists_by_name(string $alias): bool + { global $database; - $result = $database->get_one("SELECT COUNT(1) FROM artist_alias WHERE alias = ?", array($alias)); + $result = $database->get_one("SELECT COUNT(1) FROM artist_alias WHERE alias = ?", [$alias]); return ($result != 0); } - private function alias_exists(int $artistID, string $alias): bool { + private function alias_exists(int $artistID, string $alias): bool + { global $database; $result = $database->get_one( "SELECT COUNT(1) FROM artist_alias WHERE artist_id = ? AND alias = ?", - array($artistID, $alias) + [$artistID, $alias] ); return ($result != 0); } - private function get_artistID_by_url(string $url): int { + private function get_artistID_by_url(string $url): int + { global $database; - return $database->get_one("SELECT artist_id FROM artist_urls WHERE url = ?", array($url)); + return $database->get_one("SELECT artist_id FROM artist_urls WHERE url = ?", [$url]); } - private function get_artistID_by_memberName(string $member): int { + private function get_artistID_by_memberName(string $member): int + { global $database; - return $database->get_one("SELECT artist_id FROM artist_members WHERE name = ?", array($member)); + return $database->get_one("SELECT artist_id FROM artist_members WHERE name = ?", [$member]); } - private function get_artistName_by_artistID(int $artistID): string { + private function get_artistName_by_artistID(int $artistID): string + { global $database; - return $database->get_one("SELECT name FROM artists WHERE id = ?", array($artistID)); + return $database->get_one("SELECT name FROM artists WHERE id = ?", [$artistID]); } - private function get_artistID_by_aliasID(int $aliasID): int { + private function get_artistID_by_aliasID(int $aliasID): int + { global $database; - return $database->get_one("SELECT artist_id FROM artist_alias WHERE id = ?", array($aliasID)); + return $database->get_one("SELECT artist_id FROM artist_alias WHERE id = ?", [$aliasID]); } - private function get_artistID_by_memberID(int $memberID): int { + private function get_artistID_by_memberID(int $memberID): int + { global $database; - return $database->get_one("SELECT artist_id FROM artist_members WHERE id = ?", array($memberID)); + return $database->get_one("SELECT artist_id FROM artist_members WHERE id = ?", [$memberID]); } - private function get_artistID_by_urlID(int $urlID): int { + private function get_artistID_by_urlID(int $urlID): int + { global $database; - return $database->get_one("SELECT artist_id FROM artist_urls WHERE id = ?", array($urlID)); + return $database->get_one("SELECT artist_id FROM artist_urls WHERE id = ?", [$urlID]); } - private function delete_alias(int $aliasID) { + private function delete_alias(int $aliasID) + { global $database; - $database->execute("DELETE FROM artist_alias WHERE id = ?", array($aliasID)); + $database->execute("DELETE FROM artist_alias WHERE id = ?", [$aliasID]); } - private function delete_url(int $urlID) { + private function delete_url(int $urlID) + { global $database; - $database->execute("DELETE FROM artist_urls WHERE id = ?", array($urlID)); + $database->execute("DELETE FROM artist_urls WHERE id = ?", [$urlID]); } - private function delete_member(int $memberID) { + private function delete_member(int $memberID) + { global $database; - $database->execute("DELETE FROM artist_members WHERE id = ?", array($memberID)); + $database->execute("DELETE FROM artist_members WHERE id = ?", [$memberID]); } - private function get_alias_by_id(int $aliasID): array { + private function get_alias_by_id(int $aliasID): array + { global $database; - $result = $database->get_row("SELECT * FROM artist_alias WHERE id = ?", array($aliasID)); + $result = $database->get_row("SELECT * FROM artist_alias WHERE id = ?", [$aliasID]); $result["alias"] = stripslashes($result["alias"]); return $result; } - private function get_url_by_id(int $urlID): array { + private function get_url_by_id(int $urlID): array + { global $database; - $result = $database->get_row("SELECT * FROM artist_urls WHERE id = ?", array($urlID)); + $result = $database->get_row("SELECT * FROM artist_urls WHERE id = ?", [$urlID]); $result["url"] = stripslashes($result["url"]); return $result; } - private function get_member_by_id(int $memberID): array { + private function get_member_by_id(int $memberID): array + { global $database; - $result = $database->get_row("SELECT * FROM artist_members WHERE id = ?", array($memberID)); + $result = $database->get_row("SELECT * FROM artist_members WHERE id = ?", [$memberID]); $result["name"] = stripslashes($result["name"]); return $result; } - private function update_artist() { + private function update_artist() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ 'id' => 'int', 'name' => 'string,lower', 'notes' => 'string,trim,nullify', 'aliases' => 'string,trim,nullify', 'aliasesIDs' => 'string,trim,nullify', 'members' => 'string,trim,nullify', - )); + ]); $artistID = $inputs['id']; $name = $inputs['name']; $notes = $inputs['notes']; @@ -526,66 +550,67 @@ class Artists extends Extension { $urlsAsString = $inputs["urls"]; $urlsIDsAsString = $inputs["urlsIDs"]; - if(strpos($name, " ")) + if (strpos($name, " ")) { return; + } global $database; $database->execute( "UPDATE artists SET name = ?, notes = ?, updated = now(), user_id = ? WHERE id = ? ", - array($name, $notes, $userID, $artistID) + [$name, $notes, $userID, $artistID] ); // ALIAS MATCHING SECTION $i = 0; - $aliasesAsArray = is_null($aliasesAsString) ? array() : explode(" ", $aliasesAsString); - $aliasesIDsAsArray = is_null($aliasesIDsAsString) ? array() : explode(" ", $aliasesIDsAsString); - while ($i < count($aliasesAsArray)) - { + $aliasesAsArray = is_null($aliasesAsString) ? [] : explode(" ", $aliasesAsString); + $aliasesIDsAsArray = is_null($aliasesIDsAsString) ? [] : explode(" ", $aliasesIDsAsString); + while ($i < count($aliasesAsArray)) { // if an alias was updated - if ($i < count($aliasesIDsAsArray)) + if ($i < count($aliasesIDsAsArray)) { $this->save_existing_alias($aliasesIDsAsArray[$i], $aliasesAsArray[$i], $userID); - else + } else { // if we already updated all, save new ones $this->save_new_alias($artistID, $aliasesAsArray[$i], $userID); + } $i++; } // if we have more ids than alias, then some alias have been deleted -- delete them from db - while ($i < count($aliasesIDsAsArray)) + while ($i < count($aliasesIDsAsArray)) { $this->delete_alias($aliasesIDsAsArray[$i++]); + } // MEMBERS MATCHING SECTION $i = 0; - $membersAsArray = is_null($membersAsString) ? array() : explode(" ", $membersAsString); - $membersIDsAsArray = is_null($membersIDsAsString) ? array() : explode(" ", $membersIDsAsString); - while ($i < count($membersAsArray)) - { + $membersAsArray = is_null($membersAsString) ? [] : explode(" ", $membersAsString); + $membersIDsAsArray = is_null($membersIDsAsString) ? [] : explode(" ", $membersIDsAsString); + while ($i < count($membersAsArray)) { // if a member was updated - if ($i < count($membersIDsAsArray)) + if ($i < count($membersIDsAsArray)) { $this->save_existing_member($membersIDsAsArray[$i], $membersAsArray[$i], $userID); - else + } else { // if we already updated all, save new ones $this->save_new_member($artistID, $membersAsArray[$i], $userID); + } $i++; } // if we have more ids than members, then some members have been deleted -- delete them from db - while ($i < count($membersIDsAsArray)) + while ($i < count($membersIDsAsArray)) { $this->delete_member($membersIDsAsArray[$i++]); + } // URLS MATCHING SECTION $i = 0; $urlsAsString = str_replace("\r\n", "\n", $urlsAsString); $urlsAsString = str_replace("\n\r", "\n", $urlsAsString); - $urlsAsArray = is_null($urlsAsString) ? array() : explode("\n", $urlsAsString); - $urlsIDsAsArray = is_null($urlsIDsAsString) ? array() : explode(" ", $urlsIDsAsString); - while ($i < count($urlsAsArray)) - { + $urlsAsArray = is_null($urlsAsString) ? [] : explode("\n", $urlsAsString); + $urlsIDsAsArray = is_null($urlsIDsAsString) ? [] : explode(" ", $urlsIDsAsString); + while ($i < count($urlsAsArray)) { // if an URL was updated if ($i < count($urlsIDsAsArray)) { $this->save_existing_url($urlsIDsAsArray[$i], $urlsAsArray[$i], $userID); - } - else { + } else { $this->save_new_url($artistID, $urlsAsArray[$i], $userID); } @@ -593,74 +618,83 @@ class Artists extends Extension { } // if we have more ids than urls, then some urls have been deleted -- delete them from db - while ($i < count($urlsIDsAsArray)) + while ($i < count($urlsIDsAsArray)) { $this->delete_url($urlsIDsAsArray[$i++]); + } } - private function update_alias() { + private function update_alias() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "aliasID" => "int", "alias" => "string,lower", - )); + ]); $this->save_existing_alias($inputs['aliasID'], $inputs['alias'], $user->id); } - private function save_existing_alias(int $aliasID, string $alias, int $userID) { + private function save_existing_alias(int $aliasID, string $alias, int $userID) + { global $database; $database->execute( "UPDATE artist_alias SET alias = ?, updated = now(), user_id = ? WHERE id = ? ", - array($alias, $userID, $aliasID) + [$alias, $userID, $aliasID] ); } - private function update_url() { + private function update_url() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "urlID" => "int", "url" => "string", - )); + ]); $this->save_existing_url($inputs['urlID'], $inputs['url'], $user->id); } - private function save_existing_url(int $urlID, string $url, int $userID) { + private function save_existing_url(int $urlID, string $url, int $userID) + { global $database; $database->execute( "UPDATE artist_urls SET url = ?, updated = now(), user_id = ? WHERE id = ?", - array($url, $userID, $urlID) + [$url, $userID, $urlID] ); } - private function update_member() { + private function update_member() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "memberID" => "int", "name" => "string,lower", - )); + ]); $this->save_existing_member($inputs['memberID'], $inputs['name'], $user->id); } - private function save_existing_member(int $memberID, string $memberName, int $userID) { + private function save_existing_member(int $memberID, string $memberName, int $userID) + { global $database; $database->execute( "UPDATE artist_members SET name = ?, updated = now(), user_id = ? WHERE id = ?", - array($memberName, $userID, $memberID) + [$memberName, $userID, $memberID] ); } - private function add_artist(){ + private function add_artist() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "name" => "string,lower", "notes" => "string,optional", "aliases" => "string,lower,optional", "members" => "string,lower,optional", "urls" => "string,optional" - )); + ]); $name = $inputs["name"]; - if(strpos($name, " ")) + if (strpos($name, " ")) { return -1; + } $notes = $inputs["notes"]; @@ -672,26 +706,29 @@ class Artists extends Extension { //$artistID = ""; //// WE CHECK IF THE ARTIST ALREADY EXISTS ON DATABASE; IF NOT WE CREATE - if(!$this->artist_exists($name)) { + if (!$this->artist_exists($name)) { $artistID = $this->save_new_artist($name, $notes); log_info("artists", "Artist {$artistID} created by {$user->name}"); - } - else { + } else { $artistID = $this->get_artist_id($name); } if (!is_null($aliases)) { $aliasArray = explode(" ", $aliases); - foreach($aliasArray as $alias) - if (!$this->alias_exists($artistID, $alias)) + foreach ($aliasArray as $alias) { + if (!$this->alias_exists($artistID, $alias)) { $this->save_new_alias($artistID, $alias, $userID); + } + } } if (!is_null($members)) { $membersArray = explode(" ", $members); - foreach ($membersArray as $member) - if (!$this->member_exists($artistID, $member)) + foreach ($membersArray as $member) { + if (!$this->member_exists($artistID, $member)) { $this->save_new_member($artistID, $member, $userID); + } + } } if (!is_null($urls)) { @@ -700,36 +737,41 @@ class Artists extends Extension { $urls = str_replace("\n\r", "\n", $urls); $urlsArray = explode("\n", $urls); - foreach ($urlsArray as $url) - if (!$this->url_exists($artistID, $url)) + foreach ($urlsArray as $url) { + if (!$this->url_exists($artistID, $url)) { $this->save_new_url($artistID, $url, $userID); + } + } } return $artistID; } - private function save_new_artist(string $name, string $notes): int { + private function save_new_artist(string $name, string $notes): int + { global $database, $user; $database->execute(" INSERT INTO artists (user_id, name, notes, created, updated) VALUES (?, ?, ?, now(), now()) - ", array($user->id, $name, $notes)); + ", [$user->id, $name, $notes]); return $database->get_last_insert_id('artists_id_seq'); } - private function artist_exists(string $name): bool { + private function artist_exists(string $name): bool + { global $database; $result = $database->get_one( "SELECT COUNT(1) FROM artists WHERE name = ?", - array($name) + [$name] ); return ($result != 0); } - private function get_artist(int $artistID): array { + private function get_artist(int $artistID): array + { global $database; $result = $database->get_row( "SELECT * FROM artists WHERE id = ?", - array($artistID) + [$artistID] ); $result["name"] = stripslashes($result["name"]); @@ -738,14 +780,15 @@ class Artists extends Extension { return $result; } - private function get_members(int $artistID): array { + private function get_members(int $artistID): array + { global $database; $result = $database->get_all( "SELECT * FROM artist_members WHERE artist_id = ?", - array($artistID) + [$artistID] ); - - $num = count($result); + + $num = count($result); for ($i = 0 ; $i < $num ; $i++) { $result[$i]["name"] = stripslashes($result[$i]["name"]); } @@ -753,14 +796,15 @@ class Artists extends Extension { return $result; } - private function get_urls(int $artistID): array { + private function get_urls(int $artistID): array + { global $database; $result = $database->get_all( "SELECT id, url FROM artist_urls WHERE artist_id = ?", - array($artistID) + [$artistID] ); - - $num = count($result); + + $num = count($result); for ($i = 0 ; $i < $num ; $i++) { $result[$i]["url"] = stripslashes($result[$i]["url"]); } @@ -768,43 +812,46 @@ class Artists extends Extension { return $result; } - private function get_artist_id(string $name): int { - global $database; - return (int)$database->get_one( + private function get_artist_id(string $name): int + { + global $database; + return (int)$database->get_one( "SELECT id FROM artists WHERE name = ?", - array($name) + [$name] ); - } + } - private function get_artistID_by_aliasName(string $alias): int { + private function get_artistID_by_aliasName(string $alias): int + { global $database; return (int)$database->get_one( "SELECT artist_id FROM artist_alias WHERE alias = ?", - array($alias) + [$alias] ); } - private function delete_artist(int $artistID) { + private function delete_artist(int $artistID) + { global $database; $database->execute( "DELETE FROM artists WHERE id = ? ", - array($artistID) + [$artistID] ); - } - - /* - * HERE WE GET THE LIST OF ALL ARTIST WITH PAGINATION - */ - private function get_listing(Page $page, PageRequestEvent $event) - { - global $config, $database; + } + + /* + * HERE WE GET THE LIST OF ALL ARTIST WITH PAGINATION + */ + private function get_listing(Page $page, PageRequestEvent $event) + { + global $config, $database; - $pageNumber = clamp($event->get_arg(1), 1, null) - 1; - $artistsPerPage = $config->get_int("artistsPerPage"); + $pageNumber = clamp($event->get_arg(1), 1, null) - 1; + $artistsPerPage = $config->get_int("artistsPerPage"); - $listing = $database->get_all( - " + $listing = $database->get_all( + " ( SELECT a.id, a.user_id, a.name, u.name AS user_name, COALESCE(t.count, 0) AS posts , 'artist' as type, a.id AS artist_id, a.name AS artist_name, a.updated @@ -850,21 +897,22 @@ class Artists extends Extension { ) ORDER BY updated DESC LIMIT ?, ? - ", array( + ", + [ $pageNumber * $artistsPerPage , $artistsPerPage - )); - - $number_of_listings = count($listing); + ] + ); + + $number_of_listings = count($listing); - for ($i = 0 ; $i < $number_of_listings ; $i++) - { - $listing[$i]["name"] = stripslashes($listing[$i]["name"]); - $listing[$i]["user_name"] = stripslashes($listing[$i]["user_name"]); - $listing[$i]["artist_name"] = stripslashes($listing[$i]["artist_name"]); - } + for ($i = 0 ; $i < $number_of_listings ; $i++) { + $listing[$i]["name"] = stripslashes($listing[$i]["name"]); + $listing[$i]["user_name"] = stripslashes($listing[$i]["user_name"]); + $listing[$i]["artist_name"] = stripslashes($listing[$i]["artist_name"]); + } - $count = $database->get_one(" + $count = $database->get_one(" SELECT COUNT(1) FROM artists AS a LEFT OUTER JOIN artist_members AS am @@ -873,107 +921,122 @@ class Artists extends Extension { ON a.id = aa.artist_id "); - $totalPages = ceil ($count / $artistsPerPage); + $totalPages = ceil($count / $artistsPerPage); - $this->theme->list_artists($listing, $pageNumber + 1, $totalPages); - } - - /* - * HERE WE ADD AN ALIAS - */ - private function add_urls() { + $this->theme->list_artists($listing, $pageNumber + 1, $totalPages); + } + + /* + * HERE WE ADD AN ALIAS + */ + private function add_urls() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "artistID" => "int", "urls" => "string", - )); + ]); $artistID = $inputs["artistID"]; $urls = explode("\n", $inputs["urls"]); - foreach ($urls as $url) - if (!$this->url_exists($artistID, $url)) + foreach ($urls as $url) { + if (!$this->url_exists($artistID, $url)) { $this->save_new_url($artistID, $url, $user->id); + } + } } - private function save_new_url(int $artistID, string $url, int $userID) { + private function save_new_url(int $artistID, string $url, int $userID) + { global $database; $database->execute( "INSERT INTO artist_urls (artist_id, created, updated, url, user_id) VALUES (?, now(), now(), ?, ?)", - array($artistID, $url, $userID) + [$artistID, $url, $userID] ); } - private function add_alias() { + private function add_alias() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "artistID" => "int", "aliases" => "string,lower", - )); + ]); $artistID = $inputs["artistID"]; $aliases = explode(" ", $inputs["aliases"]); - foreach ($aliases as $alias) - if (!$this->alias_exists($artistID, $alias)) + foreach ($aliases as $alias) { + if (!$this->alias_exists($artistID, $alias)) { $this->save_new_alias($artistID, $alias, $user->id); + } + } } - private function save_new_alias(int $artistID, string $alias, int $userID) { + private function save_new_alias(int $artistID, string $alias, int $userID) + { global $database; $database->execute( "INSERT INTO artist_alias (artist_id, created, updated, alias, user_id) VALUES (?, now(), now(), ?, ?)", - array($artistID, $alias, $userID) + [$artistID, $alias, $userID] ); } - private function add_members() { + private function add_members() + { global $user; - $inputs = validate_input(array( + $inputs = validate_input([ "artistID" => "int", "members" => "string,lower", - )); + ]); $artistID = $inputs["artistID"]; $members = explode(" ", $inputs["members"]); - foreach ($members as $member) - if (!$this->member_exists($artistID, $member)) + foreach ($members as $member) { + if (!$this->member_exists($artistID, $member)) { $this->save_new_member($artistID, $member, $user->id); + } + } } - private function save_new_member(int $artistID, string $member, int $userID) { + private function save_new_member(int $artistID, string $member, int $userID) + { global $database; $database->execute( "INSERT INTO artist_members (artist_id, name, created, updated, user_id) VALUES (?, ?, now(), now(), ?)", - array($artistID, $member, $userID) + [$artistID, $member, $userID] ); } - private function member_exists(int $artistID, string $member): bool { + private function member_exists(int $artistID, string $member): bool + { global $database; $result = $database->get_one( "SELECT COUNT(1) FROM artist_members WHERE artist_id = ? AND name = ?", - array($artistID, $member) + [$artistID, $member] ); return ($result != 0); } - private function url_exists(int $artistID, string $url): bool { + private function url_exists(int $artistID, string $url): bool + { global $database; $result = $database->get_one( "SELECT COUNT(1) FROM artist_urls WHERE artist_id = ? AND url = ?", - array($artistID, $url) + [$artistID, $url] ); return ($result != 0); } - /** - * HERE WE GET THE INFO OF THE ALIAS - */ - private function get_alias(int $artistID): array { + /** + * HERE WE GET THE INFO OF THE ALIAS + */ + private function get_alias(int $artistID): array + { global $database; $result = $database->get_all(" @@ -981,11 +1044,11 @@ class Artists extends Extension { FROM artist_alias WHERE artist_id = ? ORDER BY alias ASC - ", array($artistID)); + ", [$artistID]); for ($i = 0 ; $i < count($result) ; $i++) { $result[$i]["alias_name"] = stripslashes($result[$i]["alias_name"]); } return $result; - } + } } diff --git a/ext/artists/test.php b/ext/artists/test.php index 9cbfdf5e..23ee4cfb 100644 --- a/ext/artists/test.php +++ b/ext/artists/test.php @@ -1,9 +1,10 @@ get_page("post/list/author=bob/1"); - #$this->assert_response(200); - } +class ArtistTest extends ShimmiePHPUnitTestCase +{ + public function testSearch() + { + # FIXME: check that the results are there + $this->get_page("post/list/author=bob/1"); + #$this->assert_response(200); + } } - diff --git a/ext/artists/theme.php b/ext/artists/theme.php index 750209f4..f9ebb745 100644 --- a/ext/artists/theme.php +++ b/ext/artists/theme.php @@ -1,8 +1,10 @@ "; - } + } - public function sidebar_options(string $mode, ?int $artistID=NULL, $is_admin=FALSE): bool { - global $page, $user; + public function sidebar_options(string $mode, ?int $artistID=null, $is_admin=false): bool + { + global $page, $user; - $html = ""; + $html = ""; - if($mode == "neutral"){ - $html = " + if ($mode == "neutral") { + $html = " ".$user->get_auth_html()." "; - } - - if($mode == "editor"){ - $html = " + } + + if ($mode == "editor") { + $html = " ".$user->get_auth_html()." @@ -36,16 +39,16 @@ class ArtistsTheme extends Themelet { "; - - if($is_admin){ - $html .= " + + if ($is_admin) { + $html .= " ".$user->get_auth_html()." "; - } - - $html .= " + } + + $html .= " ".$user->get_auth_html()." @@ -62,49 +65,52 @@ class ArtistsTheme extends Themelet { "; - } + } - if($html) $page->add_block(new Block("Manage Artists", $html, "left", 10)); - } + if ($html) { + $page->add_block(new Block("Manage Artists", $html, "left", 10)); + } + } - public function show_artist_editor($artist, $aliases, $members, $urls) { - global $user; + public function show_artist_editor($artist, $aliases, $members, $urls) + { + global $user; - $artistName = $artist['name']; - $artistNotes = $artist['notes']; - $artistID = $artist['id']; + $artistName = $artist['name']; + $artistNotes = $artist['notes']; + $artistID = $artist['id']; - // aliases - $aliasesString = ""; - $aliasesIDsString = ""; - foreach ($aliases as $alias) { - $aliasesString .= $alias["alias_name"]." "; - $aliasesIDsString .= $alias["alias_id"]." "; - } - $aliasesString = rtrim($aliasesString); - $aliasesIDsString = rtrim($aliasesIDsString); + // aliases + $aliasesString = ""; + $aliasesIDsString = ""; + foreach ($aliases as $alias) { + $aliasesString .= $alias["alias_name"]." "; + $aliasesIDsString .= $alias["alias_id"]." "; + } + $aliasesString = rtrim($aliasesString); + $aliasesIDsString = rtrim($aliasesIDsString); - // members - $membersString = ""; - $membersIDsString = ""; - foreach ($members as $member) { - $membersString .= $member["name"]." "; - $membersIDsString .= $member["id"]." "; - } - $membersString = rtrim($membersString); - $membersIDsString = rtrim($membersIDsString); + // members + $membersString = ""; + $membersIDsString = ""; + foreach ($members as $member) { + $membersString .= $member["name"]." "; + $membersIDsString .= $member["id"]." "; + } + $membersString = rtrim($membersString); + $membersIDsString = rtrim($membersIDsString); - // urls - $urlsString = ""; - $urlsIDsString = ""; - foreach ($urls as $url) { - $urlsString .= $url["url"]."\n"; - $urlsIDsString .= $url["id"]." "; - } - $urlsString = substr($urlsString, 0, strlen($urlsString) -1); - $urlsIDsString = rtrim($urlsIDsString); + // urls + $urlsString = ""; + $urlsIDsString = ""; + foreach ($urls as $url) { + $urlsString .= $url["url"]."\n"; + $urlsIDsString .= $url["id"]." "; + } + $urlsString = substr($urlsString, 0, strlen($urlsString) -1); + $urlsIDsString = rtrim($urlsIDsString); - $html = ' + $html = ' '.$user->get_auth_html().'
FromTo
Author @@ -11,22 +13,23 @@ class ArtistsTheme extends Themelet {
@@ -122,14 +128,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Edit artist", $html, "main", 10)); - } - - public function new_artist_composer() { - global $page, $user; + global $page; + $page->add_block(new Block("Edit artist", $html, "main", 10)); + } + + public function new_artist_composer() + { + global $page, $user; - $html = " + $html = " ".$user->get_auth_html()."
@@ -141,86 +148,95 @@ class ArtistsTheme extends Themelet {
Name:
"; - $page->set_title("Artists"); - $page->set_heading("Artists"); - $page->add_block(new Block("Artists", $html, "main", 10)); - } - - public function list_artists($artists, $pageNumber, $totalPages) { - global $user, $page; + $page->set_title("Artists"); + $page->set_heading("Artists"); + $page->add_block(new Block("Artists", $html, "main", 10)); + } + + public function list_artists($artists, $pageNumber, $totalPages) + { + global $user, $page; - $html = "". - "". - "". - "". - "". - ""; + $html = "
NameTypeLast updaterPosts
". + "". + "". + "". + "". + ""; - if(!$user->is_anonymous()) $html .= ""; // space for edit link - - $html .= ""; + if (!$user->is_anonymous()) { + $html .= ""; + } // space for edit link + + $html .= ""; - $deletionLinkActionArray = array( - 'artist' => 'artist/nuke/', - 'alias' => 'artist/alias/delete/', - 'member' => 'artist/member/delete/', - ); + $deletionLinkActionArray = [ + 'artist' => 'artist/nuke/', + 'alias' => 'artist/alias/delete/', + 'member' => 'artist/member/delete/', + ]; - $editionLinkActionArray = array( - 'artist' => 'artist/edit/', - 'alias' => 'artist/alias/edit/', - 'member' => 'artist/member/edit/', - ); + $editionLinkActionArray = [ + 'artist' => 'artist/edit/', + 'alias' => 'artist/alias/edit/', + 'member' => 'artist/member/edit/', + ]; - $typeTextArray = array( - 'artist' => 'Artist', - 'alias' => 'Alias', - 'member' => 'Member', - ); + $typeTextArray = [ + 'artist' => 'Artist', + 'alias' => 'Alias', + 'member' => 'Member', + ]; - foreach ($artists as $artist) { - if ($artist['type'] != 'artist') - $artist['name'] = str_replace("_", " ", $artist['name']); + foreach ($artists as $artist) { + if ($artist['type'] != 'artist') { + $artist['name'] = str_replace("_", " ", $artist['name']); + } - $elementLink = "".str_replace("_", " ", $artist['name']).""; - //$artist_link = "".str_replace("_", " ", $artist['artist_name']).""; - $user_link = "".$artist['user_name'].""; - $edit_link = "Edit"; - $del_link = "Delete"; + $elementLink = "".str_replace("_", " ", $artist['name']).""; + //$artist_link = "".str_replace("_", " ", $artist['artist_name']).""; + $user_link = "".$artist['user_name'].""; + $edit_link = "Edit"; + $del_link = "Delete"; - $html .= "". - "". + "". - "". - "". - ""; + $html .= "". + "". + "". + ""; - if(!$user->is_anonymous()) $html .= ""; - if($user->is_admin()) $html .= ""; + if (!$user->is_anonymous()) { + $html .= ""; + } + if ($user->is_admin()) { + $html .= ""; + } - $html .= ""; - } + $html .= ""; + } - $html .= "
NameTypeLast updaterPostsAction
Action
".$elementLink; + $html .= "
".$elementLink; - //if ($artist['type'] == 'member') - // $html .= " (member of ".$artist_link.")"; + //if ($artist['type'] == 'member') + // $html .= " (member of ".$artist_link.")"; - //if ($artist['type'] == 'alias') - // $html .= " (alias for ".$artist_link.")"; + //if ($artist['type'] == 'alias') + // $html .= " (alias for ".$artist_link.")"; - $html .= "".$typeTextArray[$artist['type']]."".$user_link."".$artist['posts']."".$typeTextArray[$artist['type']]."".$user_link."".$artist['posts']."".$edit_link."".$del_link."".$edit_link."".$del_link."
"; + $html .= ""; - $page->set_title("Artists"); - $page->set_heading("Artists"); - $page->add_block(new Block("Artists", $html, "main", 10)); + $page->set_title("Artists"); + $page->set_heading("Artists"); + $page->add_block(new Block("Artists", $html, "main", 10)); - $this->display_paginator($page, "artist/list", null, $pageNumber, $totalPages); - } + $this->display_paginator($page, "artist/list", null, $pageNumber, $totalPages); + } - public function show_new_alias_composer($artistID) { - global $user; + public function show_new_alias_composer($artistID) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().' @@ -231,14 +247,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Artist Aliases", $html, "main", 20)); - } + global $page; + $page->add_block(new Block("Artist Aliases", $html, "main", 20)); + } - public function show_new_member_composer($artistID) { - global $user; + public function show_new_member_composer($artistID) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().'
@@ -249,14 +266,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Artist members", $html, "main", 30)); - } + global $page; + $page->add_block(new Block("Artist members", $html, "main", 30)); + } - public function show_new_url_composer($artistID) { - global $user; + public function show_new_url_composer($artistID) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().'
@@ -267,14 +285,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Artist URLs", $html, "main", 40)); - } + global $page; + $page->add_block(new Block("Artist URLs", $html, "main", 40)); + } - public function show_alias_editor($alias) { - global $user; + public function show_alias_editor($alias) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().' @@ -284,14 +303,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Edit Alias", $html, "main", 10)); - } + global $page; + $page->add_block(new Block("Edit Alias", $html, "main", 10)); + } - public function show_url_editor($url) { - global $user; + public function show_url_editor($url) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().' @@ -301,14 +321,15 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Edit URL", $html, "main", 10)); - } + global $page; + $page->add_block(new Block("Edit URL", $html, "main", 10)); + } - public function show_member_editor($member) { - global $user; + public function show_member_editor($member) + { + global $user; - $html = ' + $html = ' '.$user->get_auth_html().' @@ -318,184 +339,210 @@ class ArtistsTheme extends Themelet { '; - global $page; - $page->add_block(new Block("Edit Member", $html, "main", 10)); - } + global $page; + $page->add_block(new Block("Edit Member", $html, "main", 10)); + } - public function show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin) { - global $page; + public function show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin) + { + global $page; - $artist_link = "".str_replace("_", " ", $artist['name']).""; + $artist_link = "".str_replace("_", " ", $artist['name']).""; - $html = "
+ $html = "
"; - - if ($userIsLogged) $html .= ""; - if ($userIsAdmin) $html .= ""; + + if ($userIsLogged) { + $html .= ""; + } + if ($userIsAdmin) { + $html .= ""; + } - $html .= " + $html .= " "; - if ($userIsLogged) $html .= ""; - if ($userIsAdmin) $html .= ""; - $html .= ""; + if ($userIsLogged) { + $html .= ""; + } + if ($userIsAdmin) { + $html .= ""; + } + $html .= ""; - $html .= $this->render_aliases($aliases, $userIsLogged, $userIsAdmin); - $html .= $this->render_members($members, $userIsLogged, $userIsAdmin); - $html .= $this->render_urls($urls, $userIsLogged, $userIsAdmin); + $html .= $this->render_aliases($aliases, $userIsLogged, $userIsAdmin); + $html .= $this->render_members($members, $userIsLogged, $userIsAdmin); + $html .= $this->render_urls($urls, $userIsLogged, $userIsAdmin); - $html .= " + $html .= ""; - if ($userIsLogged) $html .= ""; - if ($userIsAdmin) $html .= ""; - //TODO how will notes be edited? On edit artist? (should there be an editartist?) or on a editnotes? - //same question for deletion - $html .= " + if ($userIsLogged) { + $html .= ""; + } + if ($userIsAdmin) { + $html .= ""; + } + //TODO how will notes be edited? On edit artist? (should there be an editartist?) or on a editnotes? + //same question for deletion + $html .= "
Name: ".$artist_link."
Notes: ".$artist["notes"]."
"; - $page->set_title("Artist"); - $page->set_heading("Artist"); - $page->add_block(new Block("Artist", $html, "main", 10)); + $page->set_title("Artist"); + $page->set_heading("Artist"); + $page->add_block(new Block("Artist", $html, "main", 10)); - //we show the images for the artist - $artist_images = ""; - foreach($images as $image) { - $thumb_html = $this->build_thumb_html($image); - - $artist_images .= ''. - ''.$thumb_html.''. - ''; - } - - $page->add_block(new Block("Artist Images", $artist_images, "main", 20)); - } + //we show the images for the artist + $artist_images = ""; + foreach ($images as $image) { + $thumb_html = $this->build_thumb_html($image); + + $artist_images .= ''. + ''.$thumb_html.''. + ''; + } + + $page->add_block(new Block("Artist Images", $artist_images, "main", 20)); + } - private function render_aliases(array $aliases, bool $userIsLogged, bool $userIsAdmin): string { - $html = ""; - if(count($aliases) > 0) { - $aliasViewLink = str_replace("_", " ", $aliases[0]['alias_name']); // no link anymore - $aliasEditLink = "Edit"; - $aliasDeleteLink = "Delete"; + private function render_aliases(array $aliases, bool $userIsLogged, bool $userIsAdmin): string + { + $html = ""; + if (count($aliases) > 0) { + $aliasViewLink = str_replace("_", " ", $aliases[0]['alias_name']); // no link anymore + $aliasEditLink = "Edit"; + $aliasDeleteLink = "Delete"; - $html .= " + $html .= " Aliases: " . $aliasViewLink . ""; - if ($userIsLogged) - $html .= "" . $aliasEditLink . ""; + if ($userIsLogged) { + $html .= "" . $aliasEditLink . ""; + } - if ($userIsAdmin) - $html .= "" . $aliasDeleteLink . ""; + if ($userIsAdmin) { + $html .= "" . $aliasDeleteLink . ""; + } - $html .= ""; + $html .= ""; - if (count($aliases) > 1) { - for ($i = 1; $i < count($aliases); $i++) { - $aliasViewLink = str_replace("_", " ", $aliases[$i]['alias_name']); // no link anymore - $aliasEditLink = "Edit"; - $aliasDeleteLink = "Delete"; + if (count($aliases) > 1) { + for ($i = 1; $i < count($aliases); $i++) { + $aliasViewLink = str_replace("_", " ", $aliases[$i]['alias_name']); // no link anymore + $aliasEditLink = "Edit"; + $aliasDeleteLink = "Delete"; - $html .= " + $html .= "   " . $aliasViewLink . ""; - if ($userIsLogged) - $html .= "" . $aliasEditLink . ""; - if ($userIsAdmin) - $html .= "" . $aliasDeleteLink . ""; + if ($userIsLogged) { + $html .= "" . $aliasEditLink . ""; + } + if ($userIsAdmin) { + $html .= "" . $aliasDeleteLink . ""; + } - $html .= ""; - } - } - } - return $html; - } + $html .= ""; + } + } + } + return $html; + } - private function render_members(array $members, bool $userIsLogged, bool $userIsAdmin): string { - $html = ""; - if(count($members) > 0) { - $memberViewLink = str_replace("_", " ", $members[0]['name']); // no link anymore - $memberEditLink = "Edit"; - $memberDeleteLink = "Delete"; + private function render_members(array $members, bool $userIsLogged, bool $userIsAdmin): string + { + $html = ""; + if (count($members) > 0) { + $memberViewLink = str_replace("_", " ", $members[0]['name']); // no link anymore + $memberEditLink = "Edit"; + $memberDeleteLink = "Delete"; - $html .= " + $html .= " Members: " . $memberViewLink . ""; - if ($userIsLogged) - $html .= "" . $memberEditLink . ""; - if ($userIsAdmin) - $html .= "" . $memberDeleteLink . ""; + if ($userIsLogged) { + $html .= "" . $memberEditLink . ""; + } + if ($userIsAdmin) { + $html .= "" . $memberDeleteLink . ""; + } - $html .= ""; + $html .= ""; - if (count($members) > 1) { - for ($i = 1; $i < count($members); $i++) { - $memberViewLink = str_replace("_", " ", $members[$i]['name']); // no link anymore - $memberEditLink = "Edit"; - $memberDeleteLink = "Delete"; + if (count($members) > 1) { + for ($i = 1; $i < count($members); $i++) { + $memberViewLink = str_replace("_", " ", $members[$i]['name']); // no link anymore + $memberEditLink = "Edit"; + $memberDeleteLink = "Delete"; - $html .= " + $html .= "   " . $memberViewLink . ""; - if ($userIsLogged) - $html .= "" . $memberEditLink . ""; - if ($userIsAdmin) - $html .= "" . $memberDeleteLink . ""; + if ($userIsLogged) { + $html .= "" . $memberEditLink . ""; + } + if ($userIsAdmin) { + $html .= "" . $memberDeleteLink . ""; + } - $html .= ""; - } - } - } - return $html; - } + $html .= ""; + } + } + } + return $html; + } - private function render_urls(array $urls, bool $userIsLogged, bool $userIsAdmin): string { - $html = ""; - if(count($urls) > 0) { - $urlViewLink = "" . str_replace("_", " ", $urls[0]['url']) . ""; - $urlEditLink = "Edit"; - $urlDeleteLink = "Delete"; + private function render_urls(array $urls, bool $userIsLogged, bool $userIsAdmin): string + { + $html = ""; + if (count($urls) > 0) { + $urlViewLink = "" . str_replace("_", " ", $urls[0]['url']) . ""; + $urlEditLink = "Edit"; + $urlDeleteLink = "Delete"; - $html .= " + $html .= " URLs: " . $urlViewLink . ""; - if ($userIsLogged) - $html .= "" . $urlEditLink . ""; + if ($userIsLogged) { + $html .= "" . $urlEditLink . ""; + } - if ($userIsAdmin) - $html .= "" . $urlDeleteLink . ""; + if ($userIsAdmin) { + $html .= "" . $urlDeleteLink . ""; + } - $html .= ""; + $html .= ""; - if (count($urls) > 1) { - for ($i = 1; $i < count($urls); $i++) { - $urlViewLink = "" . str_replace("_", " ", $urls[$i]['url']) . ""; - $urlEditLink = "Edit"; - $urlDeleteLink = "Delete"; + if (count($urls) > 1) { + for ($i = 1; $i < count($urls); $i++) { + $urlViewLink = "" . str_replace("_", " ", $urls[$i]['url']) . ""; + $urlEditLink = "Edit"; + $urlDeleteLink = "Delete"; - $html .= " + $html .= "   " . $urlViewLink . ""; - if ($userIsLogged) - $html .= "" . $urlEditLink . ""; + if ($userIsLogged) { + $html .= "" . $urlEditLink . ""; + } - if ($userIsAdmin) - $html .= "" . $urlDeleteLink . ""; - - $html .= ""; - } - return $html; - } - } - return $html; - } + if ($userIsAdmin) { + $html .= "" . $urlDeleteLink . ""; + } + $html .= ""; + } + return $html; + } + } + return $html; + } } - diff --git a/ext/autocomplete/main.php b/ext/autocomplete/main.php index d3ed6900..eb71227b 100644 --- a/ext/autocomplete/main.php +++ b/ext/autocomplete/main.php @@ -5,55 +5,64 @@ * Description: Adds autocomplete to search & tagging. */ -class AutoComplete extends Extension { - public function get_priority(): int {return 30;} // before Home +class AutoComplete extends Extension +{ + public function get_priority(): int + { + return 30; + } // before Home - public function onPageRequest(PageRequestEvent $event) { - global $page, $database; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $database; - if($event->page_matches("api/internal/autocomplete")) { - if(!isset($_GET["s"])) return; + if ($event->page_matches("api/internal/autocomplete")) { + if (!isset($_GET["s"])) { + return; + } - $page->set_mode("data"); - $page->set_type("application/json"); + $page->set_mode("data"); + $page->set_type("application/json"); - $s = strtolower($_GET["s"]); - if( - $s == '' || - $s[0] == '_' || - $s[0] == '%' || - strlen($s) > 32 - ) { - $page->set_data("{}"); - return; - } + $s = strtolower($_GET["s"]); + if ( + $s == '' || + $s[0] == '_' || + $s[0] == '%' || + strlen($s) > 32 + ) { + $page->set_data("{}"); + return; + } - //$limit = 0; - $cache_key = "autocomplete-$s"; - $limitSQL = ""; - $SQLarr = array("search"=>"$s%"); - if(isset($_GET["limit"]) && $_GET["limit"] !== 0){ - $limitSQL = "LIMIT :limit"; - $SQLarr['limit'] = $_GET["limit"]; - $cache_key .= "-" . $_GET["limit"]; - } + //$limit = 0; + $cache_key = "autocomplete-$s"; + $limitSQL = ""; + $SQLarr = ["search"=>"$s%"]; + if (isset($_GET["limit"]) && $_GET["limit"] !== 0) { + $limitSQL = "LIMIT :limit"; + $SQLarr['limit'] = $_GET["limit"]; + $cache_key .= "-" . $_GET["limit"]; + } - $res = $database->cache->get($cache_key); - if(!$res) { - $res = $database->get_pairs($database->scoreql_to_sql(" + $res = $database->cache->get($cache_key); + if (!$res) { + $res = $database->get_pairs( + $database->scoreql_to_sql(" SELECT tag, count FROM tags WHERE SCORE_STRNORM(tag) LIKE SCORE_STRNORM(:search) AND count > 0 ORDER BY count DESC - $limitSQL"), $SQLarr - ); - $database->cache->set($cache_key, $res, 600); - } + $limitSQL"), + $SQLarr + ); + $database->cache->set($cache_key, $res, 600); + } - $page->set_data(json_encode($res)); - } + $page->set_data(json_encode($res)); + } - $this->theme->build_autocomplete($page); - } + $this->theme->build_autocomplete($page); + } } diff --git a/ext/autocomplete/theme.php b/ext/autocomplete/theme.php index 462d2bfd..334a7807 100644 --- a/ext/autocomplete/theme.php +++ b/ext/autocomplete/theme.php @@ -1,13 +1,15 @@ add_html_header(""); - $page->add_html_header(""); - $page->add_html_header(''); - $page->add_html_header(""); - } + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header(''); + $page->add_html_header(""); + } } diff --git a/ext/ban_words/main.php b/ext/ban_words/main.php index 23123c20..c668e514 100644 --- a/ext/ban_words/main.php +++ b/ext/ban_words/main.php @@ -20,10 +20,12 @@ * from Essex" */ -class BanWords extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string('banned_words', " +class BanWords extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string('banned_words', " a href= anal blowjob @@ -51,80 +53,87 @@ very nice site viagra xanax "); - } + } - public function onCommentPosting(CommentPostingEvent $event) { - global $user; - if(!$user->can("bypass_comment_checks")) { - $this->test_text($event->comment, new CommentPostingException("Comment contains banned terms")); - } - } + public function onCommentPosting(CommentPostingEvent $event) + { + global $user; + if (!$user->can("bypass_comment_checks")) { + $this->test_text($event->comment, new CommentPostingException("Comment contains banned terms")); + } + } - public function onSourceSet(SourceSetEvent $event) { - $this->test_text($event->source, new SCoreException("Source contains banned terms")); - } + public function onSourceSet(SourceSetEvent $event) + { + $this->test_text($event->source, new SCoreException("Source contains banned terms")); + } - public function onTagSet(TagSetEvent $event) { - $this->test_text(Tag::implode($event->tags), new SCoreException("Tags contain banned terms")); - } + public function onTagSet(TagSetEvent $event) + { + $this->test_text(Tag::implode($event->tags), new SCoreException("Tags contain banned terms")); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Banned Phrases"); - $sb->add_label("One per line, lines that start with slashes are treated as regex
"); - $sb->add_longtext_option("banned_words"); - $failed = array(); - foreach($this->get_words() as $word) { - if($word[0] == '/') { - if(preg_match($word, "") === false) { - $failed[] = $word; - } - } - } - if($failed) { - $sb->add_label("Failed regexes: ".join(", ", $failed)); - } - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Banned Phrases"); + $sb->add_label("One per line, lines that start with slashes are treated as regex
"); + $sb->add_longtext_option("banned_words"); + $failed = []; + foreach ($this->get_words() as $word) { + if ($word[0] == '/') { + if (preg_match($word, "") === false) { + $failed[] = $word; + } + } + } + if ($failed) { + $sb->add_label("Failed regexes: ".join(", ", $failed)); + } + $event->panel->add_block($sb); + } - /** - * Throws if the comment contains banned words. - */ - private function test_text(string $comment, Exception $ex): void { - $comment = strtolower($comment); + /** + * Throws if the comment contains banned words. + */ + private function test_text(string $comment, Exception $ex): void + { + $comment = strtolower($comment); - foreach($this->get_words() as $word) { - if($word[0] == '/') { - // lines that start with slash are regex - if(preg_match($word, $comment) === 1) { - throw $ex; - } - } - else { - // other words are literal - if(strpos($comment, $word) !== false) { - throw $ex; - } - } - } - } + foreach ($this->get_words() as $word) { + if ($word[0] == '/') { + // lines that start with slash are regex + if (preg_match($word, $comment) === 1) { + throw $ex; + } + } else { + // other words are literal + if (strpos($comment, $word) !== false) { + throw $ex; + } + } + } + } - private function get_words(): array { - global $config; - $words = array(); + private function get_words(): array + { + global $config; + $words = []; - $banned = $config->get_string("banned_words"); - foreach(explode("\n", $banned) as $word) { - $word = trim(strtolower($word)); - if(strlen($word) == 0) { - // line is blank - continue; - } - $words[] = $word; - } + $banned = $config->get_string("banned_words"); + foreach (explode("\n", $banned) as $word) { + $word = trim(strtolower($word)); + if (strlen($word) == 0) { + // line is blank + continue; + } + $words[] = $word; + } - return $words; - } + return $words; + } - public function get_priority(): int {return 30;} + public function get_priority(): int + { + return 30; + } } - diff --git a/ext/ban_words/test.php b/ext/ban_words/test.php index 886aee18..35ba6aa6 100644 --- a/ext/ban_words/test.php +++ b/ext/ban_words/test.php @@ -1,33 +1,34 @@ fail("Exception not thrown"); - } - catch(CommentPostingException $e) { - $this->assertEquals($e->getMessage(), "Comment contains banned terms"); - } - } +class BanWordsTest extends ShimmiePHPUnitTestCase +{ + public function check_blocked($image_id, $words) + { + global $user; + try { + send_event(new CommentPostingEvent($image_id, $user, $words)); + $this->fail("Exception not thrown"); + } catch (CommentPostingException $e) { + $this->assertEquals($e->getMessage(), "Comment contains banned terms"); + } + } - public function testWordBan() { - global $config; - $config->set_string("banned_words", "viagra\nporn\n\n/http:.*\.cn\//"); + public function testWordBan() + { + global $config; + $config->set_string("banned_words", "viagra\nporn\n\n/http:.*\.cn\//"); - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - $this->check_blocked($image_id, "kittens and viagra"); - $this->check_blocked($image_id, "kittens and ViagrA"); - $this->check_blocked($image_id, "kittens and viagra!"); - $this->check_blocked($image_id, "some link to http://something.cn/"); + $this->check_blocked($image_id, "kittens and viagra"); + $this->check_blocked($image_id, "kittens and ViagrA"); + $this->check_blocked($image_id, "kittens and viagra!"); + $this->check_blocked($image_id, "some link to http://something.cn/"); - $this->get_page('comment/list'); - $this->assert_title('Comments'); - $this->assert_no_text('viagra'); - $this->assert_no_text('ViagrA'); - $this->assert_no_text('http://something.cn/'); - } + $this->get_page('comment/list'); + $this->assert_title('Comments'); + $this->assert_no_text('viagra'); + $this->assert_no_text('ViagrA'); + $this->assert_no_text('http://something.cn/'); + } } - diff --git a/ext/bbcode/main.php b/ext/bbcode/main.php index e1c284d1..f7c834f3 100644 --- a/ext/bbcode/main.php +++ b/ext/bbcode/main.php @@ -25,135 +25,162 @@ * */ -class BBCode extends FormatterExtension { - public function format(string $text): string { - $text = $this->extract_code($text); - foreach(array( - "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", - ) as $el) { - $text = preg_replace("!\[$el\](.*?)\[/$el\]!s", "<$el>$1", $text); - } - $text = preg_replace('!^>>([^\d].+)!', '
$1
', $text); - $text = preg_replace('!>>(\d+)(#c?\d+)?!s', '>>$1$2', $text); - $text = preg_replace('!\[anchor=(.*?)\](.*?)\[/anchor\]!s', '$2 ', $text); // add "bb-" to avoid clashing with eg #top - $text = preg_replace('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '$3', $text); - $text = preg_replace('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '$1$2', $text); - $text = preg_replace('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '$2', $text); - $text = preg_replace('!\[url\]((?:https?|ftp|irc|mailto)://.*?)\[/url\]!s', '$1', $text); - $text = preg_replace('!\[email\](.*?)\[/email\]!s', '$1', $text); - $text = preg_replace('!\[img\](https?:\/\/.*?)\[/img\]!s', '', $text); - $text = preg_replace('!\[\[([^\|\]]+)\|([^\]]+)\]\]!s', '$2', $text); - $text = preg_replace('!\[\[([^\]]+)\]\]!s', '$1', $text); - $text = preg_replace("!\n\s*\n!", "\n\n", $text); - $text = str_replace("\n", "\n
", $text); - $text = preg_replace("/\[quote\](.*?)\[\/quote\]/s", "
\\1
", $text); - $text = preg_replace("/\[quote=(.*?)\](.*?)\[\/quote\]/s", "
\\1 said:
\\2
", $text); - while(preg_match("/\[list\](.*?)\[\/list\]/s", $text)) - $text = preg_replace("/\[list\](.*?)\[\/list\]/s", "
    \\1
", $text); - while(preg_match("/\[ul\](.*?)\[\/ul\]/s", $text)) - $text = preg_replace("/\[ul\](.*?)\[\/ul\]/s", "
    \\1
", $text); - while(preg_match("/\[ol\](.*?)\[\/ol\]/s", $text)) - $text = preg_replace("/\[ol\](.*?)\[\/ol\]/s", "
    \\1
", $text); - $text = preg_replace("/\[li\](.*?)\[\/li\]/s", "
  • \\1
  • ", $text); - $text = preg_replace("#\[\*\]#s", "
  • ", $text); - $text = preg_replace("#
    <(li|ul|ol|/ul|/ol)>#s", "<\\1>", $text); - $text = preg_replace("#\[align=(left|center|right)\](.*?)\[\/align\]#s", "
    \\2
    ", $text); - $text = $this->filter_spoiler($text); - $text = $this->insert_code($text); - return $text; - } +class BBCode extends FormatterExtension +{ + public function format(string $text): string + { + $text = $this->extract_code($text); + foreach ([ + "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", + ] as $el) { + $text = preg_replace("!\[$el\](.*?)\[/$el\]!s", "<$el>$1", $text); + } + $text = preg_replace('!^>>([^\d].+)!', '
    $1
    ', $text); + $text = preg_replace('!>>(\d+)(#c?\d+)?!s', '>>$1$2', $text); + $text = preg_replace('!\[anchor=(.*?)\](.*?)\[/anchor\]!s', '$2 ', $text); // add "bb-" to avoid clashing with eg #top + $text = preg_replace('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '$3', $text); + $text = preg_replace('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '$1$2', $text); + $text = preg_replace('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '$2', $text); + $text = preg_replace('!\[url\]((?:https?|ftp|irc|mailto)://.*?)\[/url\]!s', '$1', $text); + $text = preg_replace('!\[email\](.*?)\[/email\]!s', '$1', $text); + $text = preg_replace('!\[img\](https?:\/\/.*?)\[/img\]!s', '', $text); + $text = preg_replace('!\[\[([^\|\]]+)\|([^\]]+)\]\]!s', '$2', $text); + $text = preg_replace('!\[\[([^\]]+)\]\]!s', '$1', $text); + $text = preg_replace("!\n\s*\n!", "\n\n", $text); + $text = str_replace("\n", "\n
    ", $text); + $text = preg_replace("/\[quote\](.*?)\[\/quote\]/s", "
    \\1
    ", $text); + $text = preg_replace("/\[quote=(.*?)\](.*?)\[\/quote\]/s", "
    \\1 said:
    \\2
    ", $text); + while (preg_match("/\[list\](.*?)\[\/list\]/s", $text)) { + $text = preg_replace("/\[list\](.*?)\[\/list\]/s", "
      \\1
    ", $text); + } + while (preg_match("/\[ul\](.*?)\[\/ul\]/s", $text)) { + $text = preg_replace("/\[ul\](.*?)\[\/ul\]/s", "
      \\1
    ", $text); + } + while (preg_match("/\[ol\](.*?)\[\/ol\]/s", $text)) { + $text = preg_replace("/\[ol\](.*?)\[\/ol\]/s", "
      \\1
    ", $text); + } + $text = preg_replace("/\[li\](.*?)\[\/li\]/s", "
  • \\1
  • ", $text); + $text = preg_replace("#\[\*\]#s", "
  • ", $text); + $text = preg_replace("#
    <(li|ul|ol|/ul|/ol)>#s", "<\\1>", $text); + $text = preg_replace("#\[align=(left|center|right)\](.*?)\[\/align\]#s", "
    \\2
    ", $text); + $text = $this->filter_spoiler($text); + $text = $this->insert_code($text); + return $text; + } - public function strip(string $text): string { - foreach(array( - "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", - "code", "url", "email", "li", - ) as $el) { - $text = preg_replace("!\[$el\](.*?)\[/$el\]!s", '$1', $text); - } - $text = preg_replace("!\[anchor=(.*?)\](.*?)\[/anchor\]!s", '$2', $text); - $text = preg_replace("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text); - $text = preg_replace("!\[img\](.*?)\[/img\]!s", "", $text); - $text = preg_replace("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text); - $text = preg_replace("!\[\[([^\]]+)\]\]!s", '$1', $text); - $text = preg_replace("!\[quote\](.*?)\[/quote\]!s", "", $text); - $text = preg_replace("!\[quote=(.*?)\](.*?)\[/quote\]!s", "", $text); - $text = preg_replace("!\[/?(list|ul|ol)\]!", "", $text); - $text = preg_replace("!\[\*\](.*?)!s", '$1', $text); - $text = $this->strip_spoiler($text); - return $text; - } + public function strip(string $text): string + { + foreach ([ + "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", + "code", "url", "email", "li", + ] as $el) { + $text = preg_replace("!\[$el\](.*?)\[/$el\]!s", '$1', $text); + } + $text = preg_replace("!\[anchor=(.*?)\](.*?)\[/anchor\]!s", '$2', $text); + $text = preg_replace("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text); + $text = preg_replace("!\[img\](.*?)\[/img\]!s", "", $text); + $text = preg_replace("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text); + $text = preg_replace("!\[\[([^\]]+)\]\]!s", '$1', $text); + $text = preg_replace("!\[quote\](.*?)\[/quote\]!s", "", $text); + $text = preg_replace("!\[quote=(.*?)\](.*?)\[/quote\]!s", "", $text); + $text = preg_replace("!\[/?(list|ul|ol)\]!", "", $text); + $text = preg_replace("!\[\*\](.*?)!s", '$1', $text); + $text = $this->strip_spoiler($text); + return $text; + } - private function filter_spoiler(string $text): string { - return str_replace( - array("[spoiler]","[/spoiler]"), - array("",""), - $text); - } + private function filter_spoiler(string $text): string + { + return str_replace( + ["[spoiler]","[/spoiler]"], + ["",""], + $text + ); + } - private function strip_spoiler(string $text): string { - $l1 = strlen("[spoiler]"); - $l2 = strlen("[/spoiler]"); - while(true) { - $start = strpos($text, "[spoiler]"); - if($start === false) break; + private function strip_spoiler(string $text): string + { + $l1 = strlen("[spoiler]"); + $l2 = strlen("[/spoiler]"); + while (true) { + $start = strpos($text, "[spoiler]"); + if ($start === false) { + break; + } - $end = strpos($text, "[/spoiler]"); - if($end === false) break; + $end = strpos($text, "[/spoiler]"); + if ($end === false) { + break; + } - if($end < $start) break; + if ($end < $start) { + break; + } - $beginning = substr($text, 0, $start); - $middle = str_rot13(substr($text, $start+$l1, ($end-$start-$l1))); - $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); + $beginning = substr($text, 0, $start); + $middle = str_rot13(substr($text, $start+$l1, ($end-$start-$l1))); + $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); - $text = $beginning . $middle . $ending; - } - return $text; - } + $text = $beginning . $middle . $ending; + } + return $text; + } - private function extract_code(string $text): string { - # at the end of this function, the only code! blocks should be - # the ones we've added -- others may contain malicious content, - # which would only appear after decoding - $text = str_replace("[code!]", "[code]", $text); - $text = str_replace("[/code!]", "[/code]", $text); + private function extract_code(string $text): string + { + # at the end of this function, the only code! blocks should be + # the ones we've added -- others may contain malicious content, + # which would only appear after decoding + $text = str_replace("[code!]", "[code]", $text); + $text = str_replace("[/code!]", "[/code]", $text); - $l1 = strlen("[code]"); - $l2 = strlen("[/code]"); - while(true) { - $start = strpos($text, "[code]"); - if($start === false) break; + $l1 = strlen("[code]"); + $l2 = strlen("[/code]"); + while (true) { + $start = strpos($text, "[code]"); + if ($start === false) { + break; + } - $end = strpos($text, "[/code]", $start); - if($end === false) break; + $end = strpos($text, "[/code]", $start); + if ($end === false) { + break; + } - if($end < $start) break; + if ($end < $start) { + break; + } - $beginning = substr($text, 0, $start); - $middle = base64_encode(substr($text, $start+$l1, ($end-$start-$l1))); - $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); + $beginning = substr($text, 0, $start); + $middle = base64_encode(substr($text, $start+$l1, ($end-$start-$l1))); + $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); - $text = $beginning . "[code!]" . $middle . "[/code!]" . $ending; - } - return $text; - } + $text = $beginning . "[code!]" . $middle . "[/code!]" . $ending; + } + return $text; + } - private function insert_code(string $text): string { - $l1 = strlen("[code!]"); - $l2 = strlen("[/code!]"); - while(true) { - $start = strpos($text, "[code!]"); - if($start === false) break; + private function insert_code(string $text): string + { + $l1 = strlen("[code!]"); + $l2 = strlen("[/code!]"); + while (true) { + $start = strpos($text, "[code!]"); + if ($start === false) { + break; + } - $end = strpos($text, "[/code!]"); - if($end === false) break; + $end = strpos($text, "[/code!]"); + if ($end === false) { + break; + } - $beginning = substr($text, 0, $start); - $middle = base64_decode(substr($text, $start+$l1, ($end-$start-$l1))); - $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); + $beginning = substr($text, 0, $start); + $middle = base64_decode(substr($text, $start+$l1, ($end-$start-$l1))); + $ending = substr($text, $end + $l2, (strlen($text)-$end+$l2)); - $text = $beginning . "
    " . $middle . "
    " . $ending; - } - return $text; - } + $text = $beginning . "
    " . $middle . "
    " . $ending; + } + return $text; + } } diff --git a/ext/bbcode/test.php b/ext/bbcode/test.php index 9df81c0f..2f8dcbc5 100644 --- a/ext/bbcode/test.php +++ b/ext/bbcode/test.php @@ -1,85 +1,110 @@ assertEquals( - $this->filter("[b]bold[/b][i]italic[/i]"), - "bolditalic"); - } +class BBCodeTest extends ShimmiePHPUnitTestCase +{ + public function testBasics() + { + $this->assertEquals( + $this->filter("[b]bold[/b][i]italic[/i]"), + "bolditalic" + ); + } - public function testStacking() { - $this->assertEquals( - $this->filter("[b]B[/b][i]I[/i][b]B[/b]"), - "BIB"); - $this->assertEquals( - $this->filter("[b]bold[i]bolditalic[/i]bold[/b]"), - "boldbolditalicbold"); - } + public function testStacking() + { + $this->assertEquals( + $this->filter("[b]B[/b][i]I[/i][b]B[/b]"), + "BIB" + ); + $this->assertEquals( + $this->filter("[b]bold[i]bolditalic[/i]bold[/b]"), + "boldbolditalicbold" + ); + } - public function testFailure() { - $this->assertEquals( - $this->filter("[b]bold[i]italic"), - "[b]bold[i]italic"); - } + public function testFailure() + { + $this->assertEquals( + $this->filter("[b]bold[i]italic"), + "[b]bold[i]italic" + ); + } - public function testCode() { - $this->assertEquals( - $this->filter("[code][b]bold[/b][/code]"), - "
    [b]bold[/b]
    "); - } + public function testCode() + { + $this->assertEquals( + $this->filter("[code][b]bold[/b][/code]"), + "
    [b]bold[/b]
    " + ); + } - public function testNestedList() { - $this->assertEquals( - $this->filter("[list][*]a[list][*]a[*]b[/list][*]b[/list]"), - "
    • a
      • a
      • b
    • b
    "); - $this->assertEquals( - $this->filter("[ul][*]a[ol][*]a[*]b[/ol][*]b[/ul]"), - "
    • a
      1. a
      2. b
    • b
    "); - } + public function testNestedList() + { + $this->assertEquals( + $this->filter("[list][*]a[list][*]a[*]b[/list][*]b[/list]"), + "
    • a
      • a
      • b
    • b
    " + ); + $this->assertEquals( + $this->filter("[ul][*]a[ol][*]a[*]b[/ol][*]b[/ul]"), + "
    • a
      1. a
      2. b
    • b
    " + ); + } - public function testSpoiler() { - $this->assertEquals( - $this->filter("[spoiler]ShishNet[/spoiler]"), - "ShishNet"); - $this->assertEquals( - $this->strip("[spoiler]ShishNet[/spoiler]"), - "FuvfuArg"); - #$this->assertEquals( - # $this->filter("[spoiler]ShishNet"), - # "[spoiler]ShishNet"); - } + public function testSpoiler() + { + $this->assertEquals( + $this->filter("[spoiler]ShishNet[/spoiler]"), + "ShishNet" + ); + $this->assertEquals( + $this->strip("[spoiler]ShishNet[/spoiler]"), + "FuvfuArg" + ); + #$this->assertEquals( + # $this->filter("[spoiler]ShishNet"), + # "[spoiler]ShishNet"); + } - public function testURL() { - $this->assertEquals( - $this->filter("[url]http://shishnet.org[/url]"), - "http://shishnet.org"); - $this->assertEquals( - $this->filter("[url=http://shishnet.org]ShishNet[/url]"), - "ShishNet"); - $this->assertEquals( - $this->filter("[url=javascript:alert(\"owned\")]click to fail[/url]"), - "[url=javascript:alert(\"owned\")]click to fail[/url]"); - } + public function testURL() + { + $this->assertEquals( + $this->filter("[url]http://shishnet.org[/url]"), + "http://shishnet.org" + ); + $this->assertEquals( + $this->filter("[url=http://shishnet.org]ShishNet[/url]"), + "ShishNet" + ); + $this->assertEquals( + $this->filter("[url=javascript:alert(\"owned\")]click to fail[/url]"), + "[url=javascript:alert(\"owned\")]click to fail[/url]" + ); + } - public function testEmailURL() { - $this->assertEquals( - $this->filter("[email]spam@shishnet.org[/email]"), - "spam@shishnet.org"); - } + public function testEmailURL() + { + $this->assertEquals( + $this->filter("[email]spam@shishnet.org[/email]"), + "spam@shishnet.org" + ); + } - public function testAnchor() { - $this->assertEquals( - $this->filter("[anchor=rules]Rules[/anchor]"), - 'Rules '); - } + public function testAnchor() + { + $this->assertEquals( + $this->filter("[anchor=rules]Rules[/anchor]"), + 'Rules ' + ); + } - private function filter($in) { - $bb = new BBCode(); - return $bb->format($in); - } + private function filter($in) + { + $bb = new BBCode(); + return $bb->format($in); + } - private function strip($in) { - $bb = new BBCode(); - return $bb->strip($in); - } + private function strip($in) + { + $bb = new BBCode(); + return $bb->strip($in); + } } - diff --git a/ext/blocks/main.php b/ext/blocks/main.php index d1f0f6cf..86e0a1c5 100644 --- a/ext/blocks/main.php +++ b/ext/blocks/main.php @@ -7,11 +7,13 @@ * Description: Add HTML to some space (News, Ads, etc) */ -class Blocks extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; - if($config->get_int("ext_blocks_version") < 1) { - $database->create_table("blocks", " +class Blocks extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; + if ($config->get_int("ext_blocks_version") < 1) { + $database->create_table("blocks", " id SCORE_AIPK, pages VARCHAR(128) NOT NULL, title VARCHAR(128) NOT NULL, @@ -19,73 +21,72 @@ class Blocks extends Extension { priority INTEGER NOT NULL, content TEXT NOT NULL "); - $database->execute("CREATE INDEX blocks_pages_idx ON blocks(pages)", array()); - $config->set_int("ext_blocks_version", 1); - } - } + $database->execute("CREATE INDEX blocks_pages_idx ON blocks(pages)", []); + $config->set_int("ext_blocks_version", 1); + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("manage_blocks")) { - $event->add_link("Blocks Editor", make_link("blocks/list")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("manage_blocks")) { + $event->add_link("Blocks Editor", make_link("blocks/list")); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page, $user; - $blocks = $database->cache->get("blocks"); - if($blocks === false) { - $blocks = $database->get_all("SELECT * FROM blocks"); - $database->cache->set("blocks", $blocks, 600); - } - foreach($blocks as $block) { - $path = implode("/", $event->args); - if(strlen($path) < 4000 && fnmatch($block['pages'], $path)) { - $b = new Block($block['title'], $block['content'], $block['area'], $block['priority']); - $b->is_content = false; - $page->add_block($b); - } - } + $blocks = $database->cache->get("blocks"); + if ($blocks === false) { + $blocks = $database->get_all("SELECT * FROM blocks"); + $database->cache->set("blocks", $blocks, 600); + } + foreach ($blocks as $block) { + $path = implode("/", $event->args); + if (strlen($path) < 4000 && fnmatch($block['pages'], $path)) { + $b = new Block($block['title'], $block['content'], $block['area'], $block['priority']); + $b->is_content = false; + $page->add_block($b); + } + } - if($event->page_matches("blocks") && $user->can("manage_blocks")) { - if($event->get_arg(0) == "add") { - if($user->check_auth_token()) { - $database->execute(" + if ($event->page_matches("blocks") && $user->can("manage_blocks")) { + if ($event->get_arg(0) == "add") { + if ($user->check_auth_token()) { + $database->execute(" INSERT INTO blocks (pages, title, area, priority, content) VALUES (?, ?, ?, ?, ?) - ", array($_POST['pages'], $_POST['title'], $_POST['area'], (int)$_POST['priority'], $_POST['content'])); - log_info("blocks", "Added Block #".($database->get_last_insert_id('blocks_id_seq'))." (".$_POST['title'].")"); - $database->cache->delete("blocks"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("blocks/list")); - } - } - if($event->get_arg(0) == "update") { - if($user->check_auth_token()) { - if(!empty($_POST['delete'])) { - $database->execute(" + ", [$_POST['pages'], $_POST['title'], $_POST['area'], (int)$_POST['priority'], $_POST['content']]); + log_info("blocks", "Added Block #".($database->get_last_insert_id('blocks_id_seq'))." (".$_POST['title'].")"); + $database->cache->delete("blocks"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("blocks/list")); + } + } + if ($event->get_arg(0) == "update") { + if ($user->check_auth_token()) { + if (!empty($_POST['delete'])) { + $database->execute(" DELETE FROM blocks WHERE id=? - ", array($_POST['id'])); - log_info("blocks", "Deleted Block #".$_POST['id']); - } - else { - $database->execute(" + ", [$_POST['id']]); + log_info("blocks", "Deleted Block #".$_POST['id']); + } else { + $database->execute(" UPDATE blocks SET pages=?, title=?, area=?, priority=?, content=? WHERE id=? - ", array($_POST['pages'], $_POST['title'], $_POST['area'], (int)$_POST['priority'], $_POST['content'], $_POST['id'])); - log_info("blocks", "Updated Block #".$_POST['id']." (".$_POST['title'].")"); - } - $database->cache->delete("blocks"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("blocks/list")); - } - } - else if($event->get_arg(0) == "list") { - $this->theme->display_blocks($database->get_all("SELECT * FROM blocks ORDER BY area, priority")); - } - } - } + ", [$_POST['pages'], $_POST['title'], $_POST['area'], (int)$_POST['priority'], $_POST['content'], $_POST['id']]); + log_info("blocks", "Updated Block #".$_POST['id']." (".$_POST['title'].")"); + } + $database->cache->delete("blocks"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("blocks/list")); + } + } elseif ($event->get_arg(0) == "list") { + $this->theme->display_blocks($database->get_all("SELECT * FROM blocks ORDER BY area, priority")); + } + } + } } - diff --git a/ext/blocks/test.php b/ext/blocks/test.php index e5681c4e..fc92f69a 100644 --- a/ext/blocks/test.php +++ b/ext/blocks/test.php @@ -1,10 +1,11 @@ log_in_as_admin(); - $this->get_page("blocks/list"); - $this->assert_response(200); - $this->assert_title("Blocks"); - } +class BlocksTest extends ShimmiePHPUnitTestCase +{ + public function testBlocks() + { + $this->log_in_as_admin(); + $this->get_page("blocks/list"); + $this->assert_response(200); + $this->assert_title("Blocks"); + } } - diff --git a/ext/blocks/theme.php b/ext/blocks/theme.php index 8a490977..32f7d870 100644 --- a/ext/blocks/theme.php +++ b/ext/blocks/theme.php @@ -1,46 +1,47 @@ "; - foreach($blocks as $block) { - $html .= make_form(make_link("blocks/update")); - $html .= ""; - $html .= ""; - $html .= "Title"; - $html .= "Area"; - $html .= "Priority"; - $html .= "Pages"; - $html .= "Delete"; - $html .= ""; - $html .= ""; - $html .= ""; - $html .= ""; - $html .= "\n"; - $html .= ""; - $html .= " "; - $html .= "\n"; - $html .= "\n"; - } - $html .= make_form(make_link("blocks/add")); - $html .= ""; - $html .= "Title"; - $html .= "Area"; - $html .= "Priority"; - $html .= "Pages"; - $html .= ""; - $html .= ""; - $html .= ""; - $html .= ""; - $html .= "\n"; - $html .= ""; - $html .= ""; + $html = ""; + foreach ($blocks as $block) { + $html .= make_form(make_link("blocks/update")); + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + $html .= ""; + $html .= ""; + $html .= "\n"; + $html .= "\n"; + } + $html .= make_form(make_link("blocks/add")); + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + $html .= ""; + $html .= "
    TitleAreaPriorityPagesDelete
     
    TitleAreaPriorityPages
    "; - $page->set_title("Blocks"); - $page->set_heading("Blocks"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Block Editor", $html)); - } + $page->set_title("Blocks"); + $page->set_heading("Blocks"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Block Editor", $html)); + } } - diff --git a/ext/blotter/main.php b/ext/blotter/main.php index 645154ec..8f54576e 100644 --- a/ext/blotter/main.php +++ b/ext/blotter/main.php @@ -8,125 +8,142 @@ * * Development TODO at http://github.com/zshall/shimmie2/issues */ -class Blotter extends Extension { - public function onInitExt(InitExtEvent $event) { - /** - * I love re-using this installer don't I... - */ - global $config; - $version = $config->get_int("blotter_version", 0); - /** - * If this version is less than "1", it's time to install. - * - * REMINDER: If I change the database tables, I must change up version by 1. - */ - if($version < 1) { - /** - * Installer - */ - global $database, $config; - $database->create_table("blotter", " +class Blotter extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + /** + * I love re-using this installer don't I... + */ + global $config; + $version = $config->get_int("blotter_version", 0); + /** + * If this version is less than "1", it's time to install. + * + * REMINDER: If I change the database tables, I must change up version by 1. + */ + if ($version < 1) { + /** + * Installer + */ + global $database, $config; + $database->create_table("blotter", " id SCORE_AIPK, entry_date SCORE_DATETIME DEFAULT SCORE_NOW, entry_text TEXT NOT NULL, important SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N "); - // Insert sample data: - $database->execute("INSERT INTO blotter (entry_date, entry_text, important) VALUES (now(), ?, ?)", - array("Installed the blotter extension!", "Y")); - log_info("blotter", "Installed tables for blotter extension."); - $config->set_int("blotter_version", 1); - } - // Set default config: - $config->set_default_int("blotter_recent", 5); - $config->set_default_string("blotter_color", "FF0000"); - $config->set_default_string("blotter_position", "subheading"); - } + // Insert sample data: + $database->execute( + "INSERT INTO blotter (entry_date, entry_text, important) VALUES (now(), ?, ?)", + ["Installed the blotter extension!", "Y"] + ); + log_info("blotter", "Installed tables for blotter extension."); + $config->set_int("blotter_version", 1); + } + // Set default config: + $config->set_default_int("blotter_recent", 5); + $config->set_default_string("blotter_color", "FF0000"); + $config->set_default_string("blotter_position", "subheading"); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Blotter"); - $sb->add_int_option("blotter_recent", "
    Number of recent entries to display: "); - $sb->add_text_option("blotter_color", "
    Color of important updates: (ABCDEF format) "); - $sb->add_choice_option("blotter_position", array("Top of page" => "subheading", "In navigation bar" => "left"), "
    Position: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Blotter"); + $sb->add_int_option("blotter_recent", "
    Number of recent entries to display: "); + $sb->add_text_option("blotter_color", "
    Color of important updates: (ABCDEF format) "); + $sb->add_choice_option("blotter_position", ["Top of page" => "subheading", "In navigation bar" => "left"], "
    Position: "); + $event->panel->add_block($sb); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->is_admin()) { - $event->add_link("Blotter Editor", make_link("blotter/editor")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->is_admin()) { + $event->add_link("Blotter Editor", make_link("blotter/editor")); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $database, $user; - if($event->page_matches("blotter")) { - switch($event->get_arg(0)) { - case "editor": - /** - * Displays the blotter editor. - */ - if(!$user->is_admin()) { - $this->theme->display_permission_denied(); - } else { - $entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC"); - $this->theme->display_editor($entries); - } - break; - case "add": - /** - * Adds an entry - */ - if(!$user->is_admin() || !$user->check_auth_token()) { - $this->theme->display_permission_denied(); - } else { - $entry_text = $_POST['entry_text']; - if($entry_text == "") { die("No entry message!"); } - if(isset($_POST['important'])) { $important = 'Y'; } else { $important = 'N'; } - // Now insert into db: - $database->execute("INSERT INTO blotter (entry_date, entry_text, important) VALUES (now(), ?, ?)", - array($entry_text, $important)); - log_info("blotter", "Added Message: $entry_text"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("blotter/editor")); - } - break; - case "remove": - /** - * Removes an entry - */ - if(!$user->is_admin() || !$user->check_auth_token()) { - $this->theme->display_permission_denied(); - } else { - $id = int_escape($_POST['id']); - if(!isset($id)) { die("No ID!"); } - $database->Execute("DELETE FROM blotter WHERE id=:id", array("id"=>$id)); - log_info("blotter", "Removed Entry #$id"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("blotter/editor")); - } - break; - case "list": - /** - * Displays all blotter entries - */ - $entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC"); - $this->theme->display_blotter_page($entries); - break; - } - } - /** - * Finally, display the blotter on whatever page we're viewing. - */ - $this->display_blotter(); - } + public function onPageRequest(PageRequestEvent $event) + { + global $page, $database, $user; + if ($event->page_matches("blotter")) { + switch ($event->get_arg(0)) { + case "editor": + /** + * Displays the blotter editor. + */ + if (!$user->is_admin()) { + $this->theme->display_permission_denied(); + } else { + $entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC"); + $this->theme->display_editor($entries); + } + break; + case "add": + /** + * Adds an entry + */ + if (!$user->is_admin() || !$user->check_auth_token()) { + $this->theme->display_permission_denied(); + } else { + $entry_text = $_POST['entry_text']; + if ($entry_text == "") { + die("No entry message!"); + } + if (isset($_POST['important'])) { + $important = 'Y'; + } else { + $important = 'N'; + } + // Now insert into db: + $database->execute( + "INSERT INTO blotter (entry_date, entry_text, important) VALUES (now(), ?, ?)", + [$entry_text, $important] + ); + log_info("blotter", "Added Message: $entry_text"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("blotter/editor")); + } + break; + case "remove": + /** + * Removes an entry + */ + if (!$user->is_admin() || !$user->check_auth_token()) { + $this->theme->display_permission_denied(); + } else { + $id = int_escape($_POST['id']); + if (!isset($id)) { + die("No ID!"); + } + $database->Execute("DELETE FROM blotter WHERE id=:id", ["id"=>$id]); + log_info("blotter", "Removed Entry #$id"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("blotter/editor")); + } + break; + case "list": + /** + * Displays all blotter entries + */ + $entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC"); + $this->theme->display_blotter_page($entries); + break; + } + } + /** + * Finally, display the blotter on whatever page we're viewing. + */ + $this->display_blotter(); + } - private function display_blotter() { - global $database, $config; - $limit = $config->get_int("blotter_recent", 5); - $sql = 'SELECT * FROM blotter ORDER BY id DESC LIMIT '.intval($limit); - $entries = $database->get_all($sql); - $this->theme->display_blotter($entries); - } + private function display_blotter() + { + global $database, $config; + $limit = $config->get_int("blotter_recent", 5); + $sql = 'SELECT * FROM blotter ORDER BY id DESC LIMIT '.intval($limit); + $entries = $database->get_all($sql); + $this->theme->display_blotter($entries); + } } - diff --git a/ext/blotter/test.php b/ext/blotter/test.php index eafec499..53b7b34e 100644 --- a/ext/blotter/test.php +++ b/ext/blotter/test.php @@ -1,34 +1,38 @@ log_in_as_admin(); - //$this->assert_text("Blotter Editor"); - //$this->click("Blotter Editor"); - //$this->log_out(); - } +class BlotterTest extends ShimmiePHPUnitTestCase +{ + public function testLogin() + { + $this->log_in_as_admin(); + //$this->assert_text("Blotter Editor"); + //$this->click("Blotter Editor"); + //$this->log_out(); + } - public function testDenial() { - $this->get_page("blotter/editor"); - $this->assert_response(403); - $this->get_page("blotter/add"); - $this->assert_response(403); - $this->get_page("blotter/remove"); - $this->assert_response(403); - } + public function testDenial() + { + $this->get_page("blotter/editor"); + $this->assert_response(403); + $this->get_page("blotter/add"); + $this->assert_response(403); + $this->get_page("blotter/remove"); + $this->assert_response(403); + } - public function testAddViewRemove() { - $this->log_in_as_admin(); + public function testAddViewRemove() + { + $this->log_in_as_admin(); - $this->get_page("blotter/editor"); - //$this->set_field("entry_text", "blotter testing"); - //$this->click("Add"); - //$this->assert_text("blotter testing"); + $this->get_page("blotter/editor"); + //$this->set_field("entry_text", "blotter testing"); + //$this->click("Add"); + //$this->assert_text("blotter testing"); - $this->get_page("blotter"); - //$this->assert_text("blotter testing"); + $this->get_page("blotter"); + //$this->assert_text("blotter testing"); - $this->get_page("blotter/editor"); - //$this->click("Remove"); - //$this->assert_no_text("blotter testing"); - } + $this->get_page("blotter/editor"); + //$this->click("Remove"); + //$this->assert_no_text("blotter testing"); + } } diff --git a/ext/blotter/theme.php b/ext/blotter/theme.php index ba274cf8..9a965467 100644 --- a/ext/blotter/theme.php +++ b/ext/blotter/theme.php @@ -1,45 +1,50 @@ get_html_for_blotter_editor($entries); - $page->set_title("Blotter Editor"); - $page->set_heading("Blotter Editor"); - $page->add_block(new Block("Welcome to the Blotter Editor!", $html, "main", 10)); - $page->add_block(new Block("Navigation", "Index", "left", 0)); - } +class BlotterTheme extends Themelet +{ + public function display_editor($entries) + { + global $page; + $html = $this->get_html_for_blotter_editor($entries); + $page->set_title("Blotter Editor"); + $page->set_heading("Blotter Editor"); + $page->add_block(new Block("Welcome to the Blotter Editor!", $html, "main", 10)); + $page->add_block(new Block("Navigation", "Index", "left", 0)); + } - public function display_blotter_page($entries) { - global $page; - $html = $this->get_html_for_blotter_page($entries); - $page->set_title("Blotter"); - $page->set_heading("Blotter"); - $page->add_block(new Block("Blotter Entries", $html, "main", 10)); - } + public function display_blotter_page($entries) + { + global $page; + $html = $this->get_html_for_blotter_page($entries); + $page->set_title("Blotter"); + $page->set_heading("Blotter"); + $page->add_block(new Block("Blotter Entries", $html, "main", 10)); + } - public function display_blotter($entries) { - global $page, $config; - $html = $this->get_html_for_blotter($entries); - $position = $config->get_string("blotter_position", "subheading"); - $page->add_block(new Block(null, $html, $position, 20)); - } + public function display_blotter($entries) + { + global $page, $config; + $html = $this->get_html_for_blotter($entries); + $position = $config->get_string("blotter_position", "subheading"); + $page->add_block(new Block(null, $html, $position, 20)); + } - private function get_html_for_blotter_editor($entries) { - global $user; + private function get_html_for_blotter_editor($entries) + { + global $user; - /** - * Long function name, but at least I won't confuse it with something else ^_^ - */ + /** + * Long function name, but at least I won't confuse it with something else ^_^ + */ - // Add_new stuff goes here. - $table_header = " + // Add_new stuff goes here. + $table_header = " Date Message Important? Action "; - $add_new = " + $add_new = " ".make_form(make_link("blotter/add"))." @@ -49,21 +54,25 @@ class BlotterTheme extends Themelet { "; - // Now, time for entries list. - $table_rows = ""; - $num_entries = count($entries); - for ($i = 0 ; $i < $num_entries ; $i++) { - /** - * Add table rows - */ - $id = $entries[$i]['id']; - $entry_date = $entries[$i]['entry_date']; - $entry_text = $entries[$i]['entry_text']; - if($entries[$i]['important'] == 'Y') { $important = 'Y'; } else { $important = 'N'; } + // Now, time for entries list. + $table_rows = ""; + $num_entries = count($entries); + for ($i = 0 ; $i < $num_entries ; $i++) { + /** + * Add table rows + */ + $id = $entries[$i]['id']; + $entry_date = $entries[$i]['entry_date']; + $entry_text = $entries[$i]['entry_text']; + if ($entries[$i]['important'] == 'Y') { + $important = 'Y'; + } else { + $important = 'N'; + } - // Add the new table row(s) - $table_rows .= - " + // Add the new table row(s) + $table_rows .= + " $entry_date $entry_text $important @@ -74,9 +83,9 @@ class BlotterTheme extends Themelet { "; - } + } - $html = " + $html = " $table_header$add_new @@ -87,82 +96,83 @@ class BlotterTheme extends Themelet { Help:
    Add entries to the blotter, and they will be displayed.
    "; - return $html; - } + return $html; + } - private function get_html_for_blotter_page($entries) { - /** - * This one displays a list of all blotter entries. - */ - global $config; - $i_color = $config->get_string("blotter_color", "#FF0000"); - $html = "
    ";
    +    private function get_html_for_blotter_page($entries)
    +    {
    +        /**
    +         * This one displays a list of all blotter entries.
    +         */
    +        global $config;
    +        $i_color = $config->get_string("blotter_color", "#FF0000");
    +        $html = "
    ";
     
    -		$num_entries = count($entries);
    -		for ($i = 0 ; $i < $num_entries ; $i++) {
    -			/**
    -			 * Blotter entries
    -			 */
    -			// Reset variables:
    -			$i_open = "";
    -			$i_close = "";
    -			//$id = $entries[$i]['id'];
    -			$messy_date = $entries[$i]['entry_date'];
    -			$clean_date = date("y/m/d", strtotime($messy_date));
    -			$entry_text = $entries[$i]['entry_text'];
    -			if($entries[$i]['important'] == 'Y') {
    -				$i_open = "";
    -				$i_close="";
    -			}
    -			$html .= "{$i_open}{$clean_date} - {$entry_text}{$i_close}

    "; - } - $html .= "
    "; - return $html; - } + $num_entries = count($entries); + for ($i = 0 ; $i < $num_entries ; $i++) { + /** + * Blotter entries + */ + // Reset variables: + $i_open = ""; + $i_close = ""; + //$id = $entries[$i]['id']; + $messy_date = $entries[$i]['entry_date']; + $clean_date = date("y/m/d", strtotime($messy_date)); + $entry_text = $entries[$i]['entry_text']; + if ($entries[$i]['important'] == 'Y') { + $i_open = ""; + $i_close=""; + } + $html .= "{$i_open}{$clean_date} - {$entry_text}{$i_close}

    "; + } + $html .= "
    "; + return $html; + } - private function get_html_for_blotter($entries) { - global $config; - $i_color = $config->get_string("blotter_color", "#FF0000"); - $position = $config->get_string("blotter_position", "subheading"); - $entries_list = ""; - $num_entries = count($entries); - for ($i = 0 ; $i < $num_entries ; $i++) { - /** - * Blotter entries - */ - // Reset variables: - $i_open = ""; - $i_close = ""; - //$id = $entries[$i]['id']; - $messy_date = $entries[$i]['entry_date']; - $clean_date = date("m/d/y", strtotime($messy_date)); - $entry_text = $entries[$i]['entry_text']; - if($entries[$i]['important'] == 'Y') { - $i_open = ""; - $i_close=""; - } - $entries_list .= "
  • {$i_open}{$clean_date} - {$entry_text}{$i_close}
  • "; - } + private function get_html_for_blotter($entries) + { + global $config; + $i_color = $config->get_string("blotter_color", "#FF0000"); + $position = $config->get_string("blotter_position", "subheading"); + $entries_list = ""; + $num_entries = count($entries); + for ($i = 0 ; $i < $num_entries ; $i++) { + /** + * Blotter entries + */ + // Reset variables: + $i_open = ""; + $i_close = ""; + //$id = $entries[$i]['id']; + $messy_date = $entries[$i]['entry_date']; + $clean_date = date("m/d/y", strtotime($messy_date)); + $entry_text = $entries[$i]['entry_text']; + if ($entries[$i]['important'] == 'Y') { + $i_open = ""; + $i_close=""; + } + $entries_list .= "
  • {$i_open}{$clean_date} - {$entry_text}{$i_close}
  • "; + } - $pos_break = ""; - $pos_align = "text-align: right; position: absolute; right: 0px;"; + $pos_break = ""; + $pos_align = "text-align: right; position: absolute; right: 0px;"; - if($position === "left") { - $pos_break = "
    "; - $pos_align = ""; - } + if ($position === "left") { + $pos_break = "
    "; + $pos_align = ""; + } - if(count($entries) === 0) { - $out_text = "No blotter entries yet."; - $in_text = "Empty."; - } - else { - $clean_date = date("m/d/y", strtotime($entries[0]['entry_date'])); - $out_text = "Blotter updated: {$clean_date}"; - $in_text = "
      $entries_list
    "; - } + if (count($entries) === 0) { + $out_text = "No blotter entries yet."; + $in_text = "Empty."; + } else { + $clean_date = date("m/d/y", strtotime($entries[0]['entry_date'])); + $out_text = "Blotter updated: {$clean_date}"; + $in_text = "
      $entries_list
    "; + } - $html = " + $html = "
    $out_text {$pos_break} @@ -173,6 +183,6 @@ class BlotterTheme extends Themelet {
    $in_text
    "; - return $html; - } + return $html; + } } diff --git a/ext/browser_search/main.php b/ext/browser_search/main.php index 653d4d2b..10950000 100644 --- a/ext/browser_search/main.php +++ b/ext/browser_search/main.php @@ -13,31 +13,34 @@ * engine" notification they have */ -class BrowserSearch extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string("search_suggestions_results_order", 'a'); - } +class BrowserSearch extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string("search_suggestions_results_order", 'a'); + } - public function onPageRequest(PageRequestEvent $event) { - global $config, $database, $page; + public function onPageRequest(PageRequestEvent $event) + { + global $config, $database, $page; - // Add in header code to let the browser know that the search plugin exists - // We need to build the data for the header - $search_title = $config->get_string('title'); - $search_file_url = make_link('browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml'); - $page->add_html_header(""); + // Add in header code to let the browser know that the search plugin exists + // We need to build the data for the header + $search_title = $config->get_string('title'); + $search_file_url = make_link('browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml'); + $page->add_html_header(""); - // The search.xml file that is generated on the fly - if($event->page_matches("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml")) { - // First, we need to build all the variables we'll need - $search_title = $config->get_string('title'); - $search_form_url = make_link('post/list/{searchTerms}'); - $suggenton_url = make_link('browser_search/')."{searchTerms}"; - $icon_b64 = base64_encode(file_get_contents("ext/handle_static/static/favicon.ico")); + // The search.xml file that is generated on the fly + if ($event->page_matches("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml")) { + // First, we need to build all the variables we'll need + $search_title = $config->get_string('title'); + $search_form_url = make_link('post/list/{searchTerms}'); + $suggenton_url = make_link('browser_search/')."{searchTerms}"; + $icon_b64 = base64_encode(file_get_contents("ext/handle_static/static/favicon.ico")); - // Now for the XML - $xml = " + // Now for the XML + $xml = " $search_title UTF-8 @@ -50,55 +53,53 @@ class BrowserSearch extends Extension { "; - // And now to send it to the browser - $page->set_mode("data"); - $page->set_type("text/xml"); - $page->set_data($xml); - } + // And now to send it to the browser + $page->set_mode("data"); + $page->set_type("text/xml"); + $page->set_data($xml); + } elseif ( + $event->page_matches("browser_search") && + !$config->get_bool("disable_search_suggestions") + ) { + // We have to build some json stuff + $tag_search = $event->get_arg(0); - else if( - $event->page_matches("browser_search") && - !$config->get_bool("disable_search_suggestions") - ) { - // We have to build some json stuff - $tag_search = $event->get_arg(0); - - // Now to get DB results - if($config->get_string("search_suggestions_results_order") == "a") { - $tags = $database->execute("SELECT tag FROM tags WHERE tag LIKE ? AND count > 0 ORDER BY tag ASC LIMIT 30",array($tag_search."%")); - } else { - $tags = $database->execute("SELECT tag FROM tags WHERE tag LIKE ? AND count > 0 ORDER BY count DESC LIMIT 30",array($tag_search."%")); - } + // Now to get DB results + if ($config->get_string("search_suggestions_results_order") == "a") { + $tags = $database->execute("SELECT tag FROM tags WHERE tag LIKE ? AND count > 0 ORDER BY tag ASC LIMIT 30", [$tag_search."%"]); + } else { + $tags = $database->execute("SELECT tag FROM tags WHERE tag LIKE ? AND count > 0 ORDER BY count DESC LIMIT 30", [$tag_search."%"]); + } - // And to do stuff with it. We want our output to look like: - // ["shimmie",["shimmies","shimmy","shimmie","21 shimmies","hip shimmies","skea shimmies"],[],[]] - $json_tag_list = ""; + // And to do stuff with it. We want our output to look like: + // ["shimmie",["shimmies","shimmy","shimmie","21 shimmies","hip shimmies","skea shimmies"],[],[]] + $json_tag_list = ""; - $tags_array = array(); - foreach($tags as $tag) { - array_push($tags_array,$tag['tag']); - } + $tags_array = []; + foreach ($tags as $tag) { + array_push($tags_array, $tag['tag']); + } - $json_tag_list .= implode("\",\"", $tags_array); + $json_tag_list .= implode("\",\"", $tags_array); - // And now for the final output - $json_string = "[\"$tag_search\",[\"$json_tag_list\"],[],[]]"; - $page->set_mode("data"); - $page->set_data($json_string); - } - } + // And now for the final output + $json_string = "[\"$tag_search\",[\"$json_tag_list\"],[],[]]"; + $page->set_mode("data"); + $page->set_data($json_string); + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sort_by = array(); - $sort_by['Alphabetical'] = 'a'; - $sort_by['Tag Count'] = 't'; + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sort_by = []; + $sort_by['Alphabetical'] = 'a'; + $sort_by['Tag Count'] = 't'; - $sb = new SetupBlock("Browser Search"); - $sb->add_bool_option("disable_search_suggestions", "Disable search suggestions: "); - $sb->add_label("
    "); - $sb->add_choice_option("search_suggestions_results_order", $sort_by, "Sort the suggestions by:"); - $event->panel->add_block($sb); - } + $sb = new SetupBlock("Browser Search"); + $sb->add_bool_option("disable_search_suggestions", "Disable search suggestions: "); + $sb->add_label("
    "); + $sb->add_choice_option("search_suggestions_results_order", $sort_by, "Sort the suggestions by:"); + $event->panel->add_block($sb); + } } - diff --git a/ext/browser_search/test.php b/ext/browser_search/test.php index 3d77f423..8e289af1 100644 --- a/ext/browser_search/test.php +++ b/ext/browser_search/test.php @@ -1,8 +1,9 @@ get_page("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml"); - $this->get_page("browser_search/test"); - } +class BrowserSearchTest extends ShimmiePHPUnitTestCase +{ + public function testBasic() + { + $this->get_page("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml"); + $this->get_page("browser_search/test"); + } } - diff --git a/ext/bulk_add/main.php b/ext/bulk_add/main.php index b86f5ef8..9634d50e 100644 --- a/ext/bulk_add/main.php +++ b/ext/bulk_add/main.php @@ -15,60 +15,67 @@ *

    Note: requires the "admin" extension to be enabled */ -class BulkAddEvent extends Event { - public $dir, $results; +class BulkAddEvent extends Event +{ + public $dir; + public $results; - public function __construct(string $dir) { - $this->dir = $dir; - $this->results = array(); - } + public function __construct(string $dir) + { + $this->dir = $dir; + $this->results = []; + } } -class BulkAdd extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("bulk_add")) { - if($user->is_admin() && $user->check_auth_token() && isset($_POST['dir'])) { - set_time_limit(0); - $bae = new BulkAddEvent($_POST['dir']); - send_event($bae); - if(is_array($bae->results)) { - foreach($bae->results as $result) { - $this->theme->add_status("Adding files", $result); - } - } else if(strlen($bae->results) > 0) { - $this->theme->add_status("Adding files", $bae->results); - } - $this->theme->display_upload_results($page); - } - } - } +class BulkAdd extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("bulk_add")) { + if ($user->is_admin() && $user->check_auth_token() && isset($_POST['dir'])) { + set_time_limit(0); + $bae = new BulkAddEvent($_POST['dir']); + send_event($bae); + if (is_array($bae->results)) { + foreach ($bae->results as $result) { + $this->theme->add_status("Adding files", $result); + } + } elseif (strlen($bae->results) > 0) { + $this->theme->add_status("Adding files", $bae->results); + } + $this->theme->display_upload_results($page); + } + } + } - public function onCommand(CommandEvent $event) { - if($event->cmd == "help") { - print "\tbulk-add [directory]\n"; - print "\t\tImport this directory\n\n"; - } - if($event->cmd == "bulk-add") { - if(count($event->args) == 1) { - $bae = new BulkAddEvent($event->args[0]); - send_event($bae); - print(implode("\n", $bae->results)); - } - } - } + public function onCommand(CommandEvent $event) + { + if ($event->cmd == "help") { + print "\tbulk-add [directory]\n"; + print "\t\tImport this directory\n\n"; + } + if ($event->cmd == "bulk-add") { + if (count($event->args) == 1) { + $bae = new BulkAddEvent($event->args[0]); + send_event($bae); + print(implode("\n", $bae->results)); + } + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_admin_block(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_admin_block(); + } - public function onBulkAdd(BulkAddEvent $event) { - if(is_dir($event->dir) && is_readable($event->dir)) { - $event->results = add_dir($event->dir); - } - else { - $h_dir = html_escape($event->dir); - $event->results[] = "Error, $h_dir is not a readable directory"; - } - } + public function onBulkAdd(BulkAddEvent $event) + { + if (is_dir($event->dir) && is_readable($event->dir)) { + $event->results = add_dir($event->dir); + } else { + $h_dir = html_escape($event->dir); + $event->results[] = "Error, $h_dir is not a readable directory"; + } + } } diff --git a/ext/bulk_add/test.php b/ext/bulk_add/test.php index 5ecb7de1..6ffc5fb8 100644 --- a/ext/bulk_add/test.php +++ b/ext/bulk_add/test.php @@ -1,37 +1,42 @@ log_in_as_admin(); +class BulkAddTest extends ShimmiePHPUnitTestCase +{ + public function testBulkAdd() + { + $this->log_in_as_admin(); - $this->get_page('admin'); - $this->assert_title("Admin Tools"); + $this->get_page('admin'); + $this->assert_title("Admin Tools"); - $bae = new BulkAddEvent('asdf'); - send_event($bae); - $this->assertContains("Error, asdf is not a readable directory", - $bae->results, implode("\n", $bae->results)); + $bae = new BulkAddEvent('asdf'); + send_event($bae); + $this->assertContains( + "Error, asdf is not a readable directory", + $bae->results, + implode("\n", $bae->results) + ); - // FIXME: have BAE return a list of successes as well as errors? - $this->markTestIncomplete(); + // FIXME: have BAE return a list of successes as well as errors? + $this->markTestIncomplete(); - $this->get_page('admin'); - $this->assert_title("Admin Tools"); - send_event(new BulkAddEvent('tests')); + $this->get_page('admin'); + $this->assert_title("Admin Tools"); + send_event(new BulkAddEvent('tests')); - # FIXME: test that the output here makes sense, no "adding foo.php ... ok" + # FIXME: test that the output here makes sense, no "adding foo.php ... ok" - $this->get_page("post/list/hash=17fc89f372ed3636e28bd25cc7f3bac1/1"); - $this->assert_title(new PatternExpectation("/^Image \d+: data/")); - $this->click("Delete"); + $this->get_page("post/list/hash=17fc89f372ed3636e28bd25cc7f3bac1/1"); + $this->assert_title(new PatternExpectation("/^Image \d+: data/")); + $this->click("Delete"); - $this->get_page("post/list/hash=feb01bab5698a11dd87416724c7a89e3/1"); - $this->assert_title(new PatternExpectation("/^Image \d+: data/")); - $this->click("Delete"); + $this->get_page("post/list/hash=feb01bab5698a11dd87416724c7a89e3/1"); + $this->assert_title(new PatternExpectation("/^Image \d+: data/")); + $this->click("Delete"); - $this->get_page("post/list/hash=e106ea2983e1b77f11e00c0c54e53805/1"); - $this->assert_title(new PatternExpectation("/^Image \d+: data/")); - $this->click("Delete"); + $this->get_page("post/list/hash=e106ea2983e1b77f11e00c0c54e53805/1"); + $this->assert_title(new PatternExpectation("/^Image \d+: data/")); + $this->click("Delete"); - $this->log_out(); - } + $this->log_out(); + } } diff --git a/ext/bulk_add/theme.php b/ext/bulk_add/theme.php index 98cd9b7f..7ed68914 100644 --- a/ext/bulk_add/theme.php +++ b/ext/bulk_add/theme.php @@ -1,30 +1,33 @@ set_title("Adding folder"); - $page->set_heading("Adding folder"); - $page->add_block(new NavBlock()); - $html = ""; - foreach($this->messages as $block) { - $html .= "
    " . $block->body; - } - $page->add_block(new Block("Results", $html)); - } + /* + * Show a standard page for results to be put into + */ + public function display_upload_results(Page $page) + { + $page->set_title("Adding folder"); + $page->set_heading("Adding folder"); + $page->add_block(new NavBlock()); + $html = ""; + foreach ($this->messages as $block) { + $html .= "
    " . $block->body; + } + $page->add_block(new Block("Results", $html)); + } - /* - * Add a section to the admin page. This should contain a form which - * links to bulk_add with POST[dir] set to the name of a server-side - * directory full of images - */ - public function display_admin_block() { - global $page; - $html = " + /* + * Add a section to the admin page. This should contain a form which + * links to bulk_add with POST[dir] set to the name of a server-side + * directory full of images + */ + public function display_admin_block() + { + global $page; + $html = " Add a folder full of images; any subfolders will have their names used as tags for the images within.
    Note: this is the folder as seen by the server -- you need to @@ -37,10 +40,11 @@ class BulkAddTheme extends Themelet {

    "; - $page->add_block(new Block("Bulk Add", $html)); - } + $page->add_block(new Block("Bulk Add", $html)); + } - public function add_status($title, $body) { - $this->messages[] = new Block($title, $body); - } + public function add_status($title, $body) + { + $this->messages[] = new Block($title, $body); + } } diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php index 5d8b385f..1cb06cec 100644 --- a/ext/bulk_add_csv/main.php +++ b/ext/bulk_add_csv/main.php @@ -15,125 +15,129 @@ * normally static (e.g. SWF) will be displayed at the board's max thumbnail size

    * Useful for importing tagged images without having to do database manipulation.
    *

    Note: requires "Admin Controls" and optionally "Image Ratings" to be enabled

    - * + * */ -class BulkAddCSV extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("bulk_add_csv")) { - if($user->is_admin() && $user->check_auth_token() && isset($_POST['csv'])) { - set_time_limit(0); - $this->add_csv($_POST['csv']); - $this->theme->display_upload_results($page); - } - } - } +class BulkAddCSV extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("bulk_add_csv")) { + if ($user->is_admin() && $user->check_auth_token() && isset($_POST['csv'])) { + set_time_limit(0); + $this->add_csv($_POST['csv']); + $this->theme->display_upload_results($page); + } + } + } - public function onCommand(CommandEvent $event) { - if($event->cmd == "help") { - print " bulk-add-csv [/path/to.csv]\n"; - print " Import this .csv file (refer to documentation)\n\n"; - } - if($event->cmd == "bulk-add-csv") { - global $user; - - //Nag until CLI is admin by default - if (!$user->is_admin()) { - print "Not running as an admin, which can cause problems.\n"; - print "Please add the parameter: -u admin_username"; - } elseif(count($event->args) == 1) { - $this->add_csv($event->args[0]); - } - } - } + public function onCommand(CommandEvent $event) + { + if ($event->cmd == "help") { + print " bulk-add-csv [/path/to.csv]\n"; + print " Import this .csv file (refer to documentation)\n\n"; + } + if ($event->cmd == "bulk-add-csv") { + global $user; + + //Nag until CLI is admin by default + if (!$user->is_admin()) { + print "Not running as an admin, which can cause problems.\n"; + print "Please add the parameter: -u admin_username"; + } elseif (count($event->args) == 1) { + $this->add_csv($event->args[0]); + } + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_admin_block(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_admin_block(); + } - /** - * Generate the necessary DataUploadEvent for a given image and tags. - */ - private function add_image(string $tmpname, string $filename, string $tags, string $source, string $rating, string $thumbfile) { - assert(file_exists($tmpname)); + /** + * Generate the necessary DataUploadEvent for a given image and tags. + */ + private function add_image(string $tmpname, string $filename, string $tags, string $source, string $rating, string $thumbfile) + { + assert(file_exists($tmpname)); - $pathinfo = pathinfo($filename); - if(!array_key_exists('extension', $pathinfo)) { - throw new UploadException("File has no extension"); - } - $metadata = array(); - $metadata['filename'] = $pathinfo['basename']; - $metadata['extension'] = $pathinfo['extension']; - $metadata['tags'] = Tag::explode($tags); - $metadata['source'] = $source; - $event = new DataUploadEvent($tmpname, $metadata); - send_event($event); - if($event->image_id == -1) { - throw new UploadException("File type not recognised"); - } else { - if(class_exists("RatingSetEvent") && in_array($rating, array("s", "q", "e"))) { - $ratingevent = new RatingSetEvent(Image::by_id($event->image_id), $rating); - send_event($ratingevent); - } - if (file_exists($thumbfile)) { - copy($thumbfile, warehouse_path("thumbs", $event->hash)); - } - } - } + $pathinfo = pathinfo($filename); + if (!array_key_exists('extension', $pathinfo)) { + throw new UploadException("File has no extension"); + } + $metadata = []; + $metadata['filename'] = $pathinfo['basename']; + $metadata['extension'] = $pathinfo['extension']; + $metadata['tags'] = Tag::explode($tags); + $metadata['source'] = $source; + $event = new DataUploadEvent($tmpname, $metadata); + send_event($event); + if ($event->image_id == -1) { + throw new UploadException("File type not recognised"); + } else { + if (class_exists("RatingSetEvent") && in_array($rating, ["s", "q", "e"])) { + $ratingevent = new RatingSetEvent(Image::by_id($event->image_id), $rating); + send_event($ratingevent); + } + if (file_exists($thumbfile)) { + copy($thumbfile, warehouse_path("thumbs", $event->hash)); + } + } + } - private function add_csv(string $csvfile) { - if(!file_exists($csvfile)) { - $this->theme->add_status("Error", "$csvfile not found"); - return; - } - if (!is_file($csvfile) || strtolower(substr($csvfile, -4)) != ".csv") { - $this->theme->add_status("Error", "$csvfile doesn't appear to be a csv file"); - return; - } - - $linenum = 1; - $list = ""; - $csvhandle = fopen($csvfile, "r"); - - while (($csvdata = fgetcsv($csvhandle, 0, ",")) !== FALSE) { - if(count($csvdata) != 5) { - if(strlen($list) > 0) { - $this->theme->add_status("Error", "Encountered malformed data. Line $linenum $csvfile
    ".$list); - fclose($csvhandle); - return; - } else { - $this->theme->add_status("Error", "Encountered malformed data. Line $linenum $csvfile
    Check here for the expected format"); - fclose($csvhandle); - return; - } - } - $fullpath = $csvdata[0]; - $tags = trim($csvdata[1]); - $source = $csvdata[2]; - $rating = $csvdata[3]; - $thumbfile = $csvdata[4]; - $pathinfo = pathinfo($fullpath); - $shortpath = $pathinfo["basename"]; - $list .= "
    ".html_escape("$shortpath (".str_replace(" ", ", ", $tags).")... "); - if (file_exists($csvdata[0]) && is_file($csvdata[0])) { - try{ - $this->add_image($fullpath, $pathinfo["basename"], $tags, $source, $rating, $thumbfile); - $list .= "ok\n"; - } - catch(Exception $ex) { - $list .= "failed:
    ". $ex->getMessage(); - } - } else { - $list .= "failed:
    File doesn't exist ".html_escape($csvdata[0]); - } - $linenum += 1; - } - - if(strlen($list) > 0) { - $this->theme->add_status("Adding $csvfile", $list); - } - fclose($csvhandle); - } + private function add_csv(string $csvfile) + { + if (!file_exists($csvfile)) { + $this->theme->add_status("Error", "$csvfile not found"); + return; + } + if (!is_file($csvfile) || strtolower(substr($csvfile, -4)) != ".csv") { + $this->theme->add_status("Error", "$csvfile doesn't appear to be a csv file"); + return; + } + + $linenum = 1; + $list = ""; + $csvhandle = fopen($csvfile, "r"); + + while (($csvdata = fgetcsv($csvhandle, 0, ",")) !== false) { + if (count($csvdata) != 5) { + if (strlen($list) > 0) { + $this->theme->add_status("Error", "Encountered malformed data. Line $linenum $csvfile
    ".$list); + fclose($csvhandle); + return; + } else { + $this->theme->add_status("Error", "Encountered malformed data. Line $linenum $csvfile
    Check here for the expected format"); + fclose($csvhandle); + return; + } + } + $fullpath = $csvdata[0]; + $tags = trim($csvdata[1]); + $source = $csvdata[2]; + $rating = $csvdata[3]; + $thumbfile = $csvdata[4]; + $pathinfo = pathinfo($fullpath); + $shortpath = $pathinfo["basename"]; + $list .= "
    ".html_escape("$shortpath (".str_replace(" ", ", ", $tags).")... "); + if (file_exists($csvdata[0]) && is_file($csvdata[0])) { + try { + $this->add_image($fullpath, $pathinfo["basename"], $tags, $source, $rating, $thumbfile); + $list .= "ok\n"; + } catch (Exception $ex) { + $list .= "failed:
    ". $ex->getMessage(); + } + } else { + $list .= "failed:
    File doesn't exist ".html_escape($csvdata[0]); + } + $linenum += 1; + } + + if (strlen($list) > 0) { + $this->theme->add_status("Adding $csvfile", $list); + } + fclose($csvhandle); + } } - diff --git a/ext/bulk_add_csv/theme.php b/ext/bulk_add_csv/theme.php index 88fcc41d..9f4ec371 100644 --- a/ext/bulk_add_csv/theme.php +++ b/ext/bulk_add_csv/theme.php @@ -1,28 +1,31 @@ set_title("Adding images from csv"); - $page->set_heading("Adding images from csv"); - $page->add_block(new NavBlock()); - foreach($this->messages as $block) { - $page->add_block($block); - } - } + /* + * Show a standard page for results to be put into + */ + public function display_upload_results(Page $page) + { + $page->set_title("Adding images from csv"); + $page->set_heading("Adding images from csv"); + $page->add_block(new NavBlock()); + foreach ($this->messages as $block) { + $page->add_block($block); + } + } - /* - * Add a section to the admin page. This should contain a form which - * links to bulk_add_csv with POST[csv] set to the name of a server-side - * csv file - */ - public function display_admin_block() { - global $page; - $html = " + /* + * Add a section to the admin page. This should contain a form which + * links to bulk_add_csv with POST[csv] set to the name of a server-side + * csv file + */ + public function display_admin_block() + { + global $page; + $html = " Add images from a csv. Images will be tagged and have their source and rating set (if \"Image Ratings\" is enabled)
    Specify the absolute or relative path to a local .csv file. Check here for the expected format. @@ -34,11 +37,11 @@ class BulkAddCSVTheme extends Themelet { "; - $page->add_block(new Block("Bulk Add CSV", $html)); - } + $page->add_block(new Block("Bulk Add CSV", $html)); + } - public function add_status($title, $body) { - $this->messages[] = new Block($title, $body); - } + public function add_status($title, $body) + { + $this->messages[] = new Block($title, $body); + } } - diff --git a/ext/bulk_remove/main.php b/ext/bulk_remove/main.php index 592d85f6..75da254b 100644 --- a/ext/bulk_remove/main.php +++ b/ext/bulk_remove/main.php @@ -6,22 +6,28 @@ * License: GPLv2 * Description: Allows admin to delete many images at once through Board Admin. * Documentation: - * + * */ //todo: removal by tag returns 1 less image in test for some reason, actually a combined search doesn't seem to work for shit either -class BulkRemove extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $user; - if($event->page_matches("bulk_remove") && $user->is_admin() && $user->check_auth_token()) { - if ($event->get_arg(0) == "confirm") $this->do_bulk_remove(); - else $this->show_confirm(); - } - } +class BulkRemove extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $user; + if ($event->page_matches("bulk_remove") && $user->is_admin() && $user->check_auth_token()) { + if ($event->get_arg(0) == "confirm") { + $this->do_bulk_remove(); + } else { + $this->show_confirm(); + } + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - global $page; - $html = "Be extremely careful when using this!
    + public function onAdminBuilding(AdminBuildingEvent $event) + { + global $page; + $html = "Be extremely careful when using this!
    Once an image is removed there is no way to recover it so it is recommended that you first take when removing a large amount of images.
    Note: Entering both an ID range and tags will only remove images between the given ID's that have the given tags. @@ -40,94 +46,95 @@ class BulkRemove extends Extension { "; - $page->add_block(new Block("Bulk Remove", $html)); - } + $page->add_block(new Block("Bulk Remove", $html)); + } - // returns a list of images to be removed - private function determine_images() - { - // set vars - $images_for_removal = array(); - $error = ""; + // returns a list of images to be removed + private function determine_images() + { + // set vars + $images_for_removal = []; + $error = ""; - $min_id = $_POST['remove_id_min']; - $max_id = $_POST['remove_id_max']; - $tags = $_POST['remove_tags']; + $min_id = $_POST['remove_id_min']; + $max_id = $_POST['remove_id_max']; + $tags = $_POST['remove_tags']; - // if using id range to remove (comined removal with tags) - if ($min_id != "" && $max_id != "") - { - // error if values are not correctly entered - if (!is_numeric($min_id) || !is_numeric($max_id) || - intval($max_id) < intval($min_id)) - $error = "Values not correctly entered for removal between id."; - - else { // if min & max id are valid + // if using id range to remove (comined removal with tags) + if ($min_id != "" && $max_id != "") { + // error if values are not correctly entered + if (!is_numeric($min_id) || !is_numeric($max_id) || + intval($max_id) < intval($min_id)) { + $error = "Values not correctly entered for removal between id."; + } else { // if min & max id are valid - // Grab the list of images & place it in the removing array - foreach (Image::find_images(intval($min_id), intval($max_id)) as $image) + // Grab the list of images & place it in the removing array + foreach (Image::find_images(intval($min_id), intval($max_id)) as $image) { array_push($images_for_removal, $image); - } + } } + } - // refine previous results or create results from tags - if ($tags != "") - { - $tags_arr = explode(" ", $_POST['remove_tags']); + // refine previous results or create results from tags + if ($tags != "") { + $tags_arr = explode(" ", $_POST['remove_tags']); - // Search all images with the specified tags & add to list - foreach (Image::find_images(1, 2147483647, $tags_arr) as $image) - array_push($images_for_removal, $image); + // Search all images with the specified tags & add to list + foreach (Image::find_images(1, 2147483647, $tags_arr) as $image) { + array_push($images_for_removal, $image); } - - - // if no images were found with the given info - if (count($images_for_removal) == 0) - $error = "No images selected for removal"; - - //var_dump($tags_arr); - return array( - "error" => $error, - "images_for_removal" => $images_for_removal); } + + + // if no images were found with the given info + if (count($images_for_removal) == 0) { + $error = "No images selected for removal"; + } + + //var_dump($tags_arr); + return [ + "error" => $error, + "images_for_removal" => $images_for_removal]; + } - // displays confirmation to admin before removal - private function show_confirm() - { - global $page; + // displays confirmation to admin before removal + private function show_confirm() + { + global $page; - // set vars - $determined_imgs = $this->determine_images(); - $error = $determined_imgs["error"]; - $images_for_removal = $determined_imgs["images_for_removal"]; + // set vars + $determined_imgs = $this->determine_images(); + $error = $determined_imgs["error"]; + $images_for_removal = $determined_imgs["images_for_removal"]; - // if there was an error in determine_images() - if ($error != "") { - $page->add_block(new Block("Cannot remove images", $error)); - return; - } - // generates the image array & places it in $_POST["bulk_remove_images"] - $_POST["bulk_remove_images"] = $images_for_removal; + // if there was an error in determine_images() + if ($error != "") { + $page->add_block(new Block("Cannot remove images", $error)); + return; + } + // generates the image array & places it in $_POST["bulk_remove_images"] + $_POST["bulk_remove_images"] = $images_for_removal; - // Display confirmation message - $html = make_form(make_link("bulk_remove")). - "Are you sure you want to PERMANENTLY remove ". + // Display confirmation message + $html = make_form(make_link("bulk_remove")). + "Are you sure you want to PERMANENTLY remove ". count($images_for_removal) ." images?
    "; - $page->add_block(new Block("Confirm Removal", $html)); - } + $page->add_block(new Block("Confirm Removal", $html)); + } - private function do_bulk_remove() - { - global $page; - // display error if user didn't go through admin board - if (!isset($_POST["bulk_remove_images"])) { - $page->add_block(new Block("Bulk Remove Error", - "Please use Board Admin to use bulk remove.")); - } - - // - $image_arr = $_POST["bulk_remove_images"]; + private function do_bulk_remove() + { + global $page; + // display error if user didn't go through admin board + if (!isset($_POST["bulk_remove_images"])) { + $page->add_block(new Block( + "Bulk Remove Error", + "Please use Board Admin to use bulk remove." + )); } + + // + $image_arr = $_POST["bulk_remove_images"]; + } } - diff --git a/ext/chatbox/cp/ajax.php b/ext/chatbox/cp/ajax.php index f682649f..7c74d120 100644 --- a/ext/chatbox/cp/ajax.php +++ b/ext/chatbox/cp/ajax.php @@ -8,185 +8,211 @@ include '../php/functions.php'; include '../php/yshout.class.php'; include '../php/ajaxcall.class.php'; -if (isset($_POST['mode'])) - switch($_POST['mode']) { - case 'login': - doLogin(); - break; - case 'logout': - doLogout(); - break; - case 'unban': - doUnban(); - break; - case 'unbanall': - doUnbanAll(); - break; - case 'setpreference': - doSetPreference(); - break; - case 'resetpreferences': - doResetPreferences(); - break; - } - -function doLogin() { - global $kioskMode; - - if ($kioskMode) { - logout(); - $result = array( - 'error' => false, - 'html' => cp() - ); - - echo json_encode($result); - return; - } - - login(md5($_POST['password'])); - $result = array(); - if (loggedIn()) { - $result['error'] = false; - $result['html'] = cp(); - } else - $result['error'] = 'invalid'; - - echo json_encode($result); +if (isset($_POST['mode'])) { + switch ($_POST['mode']) { + case 'login': + doLogin(); + break; + case 'logout': + doLogout(); + break; + case 'unban': + doUnban(); + break; + case 'unbanall': + doUnbanAll(); + break; + case 'setpreference': + doSetPreference(); + break; + case 'resetpreferences': + doResetPreferences(); + break; + } } -function doLogout() { - logout(); +function doLogin() +{ + global $kioskMode; + + if ($kioskMode) { + logout(); + $result = [ + 'error' => false, + 'html' => cp() + ]; + + echo json_encode($result); + return; + } + + login(md5($_POST['password'])); + $result = []; + if (loggedIn()) { + $result['error'] = false; + $result['html'] = cp(); + } else { + $result['error'] = 'invalid'; + } - $result = array( - 'error' => false - ); - - echo json_encode($result); + echo json_encode($result); } -function doUnban() { - global $kioskMode; - - if ($kioskMode) { - $result = array( - 'error' => false - ); - - echo json_encode($result); - return; - } - - if (!loggedIn()) return; +function doLogout() +{ + logout(); - $ys = ys(); - $result = array(); + $result = [ + 'error' => false + ]; - $ip = $_POST['ip']; - - if ($ys->banned($ip)) { - $ys->unban($ip); - $result['error'] = false; - } else - $result['error'] = 'notbanned'; - - - echo json_encode($result); + echo json_encode($result); } -function doUnbanAll() { - global $kioskMode; - - if ($kioskMode) { - $result = array( - 'error' => false - ); - - echo json_encode($result); - return; - } - - if (!loggedIn()) return; +function doUnban() +{ + global $kioskMode; + + if ($kioskMode) { + $result = [ + 'error' => false + ]; + + echo json_encode($result); + return; + } + + if (!loggedIn()) { + return; + } - $ys = ys(); - $ys->unbanAll(); + $ys = ys(); + $result = []; - $result = array( - 'error' => false - ); + $ip = $_POST['ip']; - echo json_encode($result); + if ($ys->banned($ip)) { + $ys->unban($ip); + $result['error'] = false; + } else { + $result['error'] = 'notbanned'; + } + + + echo json_encode($result); +} + +function doUnbanAll() +{ + global $kioskMode; + + if ($kioskMode) { + $result = [ + 'error' => false + ]; + + echo json_encode($result); + return; + } + + if (!loggedIn()) { + return; + } + + $ys = ys(); + $ys->unbanAll(); + + $result = [ + 'error' => false + ]; + + echo json_encode($result); } -function doSetPreference() { - global $prefs, $kioskMode; - - if ($kioskMode) { - $result = array( - 'error' => false - ); - - echo json_encode($result); - return; - } - - if (!loggedIn()) return; +function doSetPreference() +{ + global $prefs, $kioskMode; + + if ($kioskMode) { + $result = [ + 'error' => false + ]; + + echo json_encode($result); + return; + } + + if (!loggedIn()) { + return; + } - $pref = $_POST['preference']; - $value = magic($_POST['value']); + $pref = $_POST['preference']; + $value = magic($_POST['value']); - if ($value === 'true') $value = true; - if ($value === 'false') $value = false; + if ($value === 'true') { + $value = true; + } + if ($value === 'false') { + $value = false; + } - $prefs[$pref] = $value; + $prefs[$pref] = $value; - savePrefs($prefs); + savePrefs($prefs); - if ($pref == 'password') login(md5($value)); + if ($pref == 'password') { + login(md5($value)); + } - $result = array( - 'error' => false - ); + $result = [ + 'error' => false + ]; - echo json_encode($result); + echo json_encode($result); } -function doResetPreferences() { - global $prefs, $kioskMode; - - if ($kioskMode) { - $result = array( - 'error' => false - ); - - echo json_encode($result); - return; - } - - if (!loggedIn()) return; +function doResetPreferences() +{ + global $prefs, $kioskMode; + + if ($kioskMode) { + $result = [ + 'error' => false + ]; + + echo json_encode($result); + return; + } + + if (!loggedIn()) { + return; + } - resetPrefs(); - login(md5($prefs['password'])); + resetPrefs(); + login(md5($prefs['password'])); - // $prefs['password'] = 'lol no'; - $result = array( - 'error' => false, - 'prefs' => $prefs - ); + // $prefs['password'] = 'lol no'; + $result = [ + 'error' => false, + 'prefs' => $prefs + ]; - echo json_encode($result); + echo json_encode($result); } /* CP Display */ -function cp() { - global $kioskMode; - - if (!loggedIn() && !$kioskMode) return 'You\'re not logged in!'; +function cp() +{ + global $kioskMode; + + if (!loggedIn() && !$kioskMode) { + return 'You\'re not logged in!'; + } - return ' + return '

    @@ -236,38 +262,41 @@ function cp() {
    '; } -function bansList() { - global $kioskMode; - - $ys = ys(); - $bans = $ys->bans(); +function bansList() +{ + global $kioskMode; + + $ys = ys(); + $bans = $ys->bans(); - $html = '
      '; + $html = '
        '; - $hasBans = false; - foreach($bans as $ban) { - $hasBans = true; - $html .= ' + $hasBans = false; + foreach ($bans as $ban) { + $hasBans = true; + $html .= '
      • ' . $ban['nickname']. ' (' . ($kioskMode ? '[No IP in Kiosk Mode]' : $ban['ip']) . ') Unban
      • '; - } - - if (!$hasBans) - $html = '

        No one is banned.

        '; - else - $html .= '
      '; + } + + if (!$hasBans) { + $html = '

      No one is banned.

      '; + } else { + $html .= '
    '; + } - return $html; + return $html; } -function preferencesForm() { - global $prefs, $kioskMode; +function preferencesForm() +{ + global $prefs, $kioskMode; - return ' + return '
    @@ -434,10 +463,11 @@ function preferencesForm() { '; } -function about() { - global $prefs; +function about() +{ + global $prefs; - $html = ' + $html = '

    About YShout

    YShout was created and developed by Yuri Vishnevsky. Version 5 is the first one with an about page, so you\'ll have to excuse the lack of appropriate information — I\'m not quite sure what it is that goes on "About" pages anyway.

    @@ -451,7 +481,6 @@ function about() {
    '; - - return $html; + + return $html; } - diff --git a/ext/chatbox/cp/index.php b/ext/chatbox/cp/index.php index c44d3255..5ed6f34b 100644 --- a/ext/chatbox/cp/index.php +++ b/ext/chatbox/cp/index.php @@ -1,5 +1,5 @@ @@ -35,8 +35,10 @@
    + if (loggedIn()) { + echo cp(); + } + ?> diff --git a/ext/chatbox/history/index.php b/ext/chatbox/history/index.php index f3755e98..94272f06 100644 --- a/ext/chatbox/history/index.php +++ b/ext/chatbox/history/index.php @@ -1,92 +1,90 @@ '; + $html = '
    '; - $admin = loggedIn(); - - $log = 1; - - if (isset($_GET['log'])) - { - $log = $_GET['log']; - } - - if (isset($_POST['log'])) - { - $log = $_POST['log']; - } + $admin = loggedIn(); + + $log = 1; + + if (isset($_GET['log'])) { + $log = $_GET['log']; + } + + if (isset($_POST['log'])) { + $log = $_POST['log']; + } - if (filter_var($log, FILTER_VALIDATE_INT) === false) - { - $log = 1; - } - - $ys = ys($log); - $posts = $ys->posts(); + if (filter_var($log, FILTER_VALIDATE_INT) === false) { + $log = 1; + } + + $ys = ys($log); + $posts = $ys->posts(); - if (sizeof($posts) === 0) - $html .= ' + if (sizeof($posts) === 0) { + $html .= '
    Yurivish: Hey, there aren\'t any posts in this log.
    '; + } - $id = 0; + $id = 0; - foreach($posts as $post) { - $id++; + foreach ($posts as $post) { + $id++; - $banned = $ys->banned($post['adminInfo']['ip']); - $html .= '
    ' . "\n"; - - $ts = ''; - - switch($prefs['timestamp']) { - case 12: - $ts = date('h:i', $post['timestamp']); - break; - case 24: - $ts = date('H:i', $post['timestamp']); - break; - case 0: - $ts = ''; - break; - } + $banned = $ys->banned($post['adminInfo']['ip']); + $html .= '
    ' . "\n"; + + $ts = ''; + + switch ($prefs['timestamp']) { + case 12: + $ts = date('h:i', $post['timestamp']); + break; + case 24: + $ts = date('H:i', $post['timestamp']); + break; + case 0: + $ts = ''; + break; + } - $html .= ' ' . "\n"; - $html .= ' ' . $post['nickname'] . '' . $prefs['nicknameSeparator'] . ' ' . "\n"; - $html .= ' ' . $post['message'] . '' . "\n"; - $html .= ' ' . "\n"; + $html .= ' ' . "\n"; + $html .= ' ' . $post['nickname'] . '' . $prefs['nicknameSeparator'] . ' ' . "\n"; + $html .= ' ' . $post['message'] . '' . "\n"; + $html .= ' ' . "\n"; - $html .= ' ' . "\n"; - $html .= ' Info' . ($admin ? ' | Delete | ' . ($banned ? 'Unban' : 'Ban') : '') . "\n"; - $html .= ' ' . "\n"; + $html .= ' ' . "\n"; + $html .= ' Info' . ($admin ? ' | Delete | ' . ($banned ? 'Unban' : 'Ban') : '') . "\n"; + $html .= ' ' . "\n"; - if ($admin) { - $html .= ''; - } + if ($admin) { + $html .= ''; + } - $html .= '
    ' . "\n"; - } + $html .= '
    ' . "\n"; + } - $html .= '
    ' . "\n"; + $html .= '' . "\n"; if (isset($_POST['p'])) { - echo $html; - exit; + echo $html; + exit; } ?> @@ -115,16 +113,17 @@ if (isset($_POST['p'])) {

    YShout.History

    - + Clear this log, or Clear all logs.
    diff --git a/ext/chatbox/include.php b/ext/chatbox/include.php index a3d4b7b7..55e32ad2 100644 --- a/ext/chatbox/include.php +++ b/ext/chatbox/include.php @@ -1,8 +1,7 @@ add_html_header(" + // Adds header to enable chatbox + $root = get_base_href(); + $yPath = make_http($root . "/ext/chatbox/"); + $page->add_html_header(" @@ -27,10 +29,10 @@ class Chatbox extends Extension { ", 500); - // loads the chatbox at the set location - $html = "
    "; - $chatblock = new Block("Chatbox", $html, "main", 97); - $chatblock->is_content = false; - $page->add_block($chatblock); - } + // loads the chatbox at the set location + $html = "
    "; + $chatblock = new Block("Chatbox", $html, "main", 97); + $chatblock->is_content = false; + $page->add_block($chatblock); + } } diff --git a/ext/chatbox/php/ajaxcall.class.php b/ext/chatbox/php/ajaxcall.class.php index 78107e09..f5b1677a 100644 --- a/ext/chatbox/php/ajaxcall.class.php +++ b/ext/chatbox/php/ajaxcall.class.php @@ -1,284 +1,314 @@ reqType = $_POST['reqType']; + } - function AjaxCall($log = null) { - header('Content-type: application/json'); - session_start(); - - if (isset($log)) $_SESSION['yLog'] = $log; - - $this->reqType = $_POST['reqType']; - } + public function process() + { + switch ($this->reqType) { + case 'init': - function process() { - switch($this->reqType) { - case 'init': + $this->initSession(); + $this->sendFirstUpdates(); + break; - $this->initSession(); - $this->sendFirstUpdates(); - break; + case 'post': + $nickname = $_POST['nickname']; + $message = $_POST['message']; + cookie('yNickname', $nickname); + $ys = ys($_SESSION['yLog']); + + if ($ys->banned(ip())) { + $this->sendBanned(); + break; + } + if ($post = $ys->post($nickname, $message)) { + // To use $post somewheres later + $this->sendUpdates(); + } + break; - case 'post': - $nickname = $_POST['nickname']; - $message = $_POST['message']; - cookie('yNickname', $nickname); - $ys = ys($_SESSION['yLog']); - - if ($ys->banned(ip())) { $this->sendBanned(); break; } - if ($post = $ys->post($nickname, $message)) { - // To use $post somewheres later - $this->sendUpdates(); - } - break; + case 'refresh': + $ys = ys($_SESSION['yLog']); + if ($ys->banned(ip())) { + $this->sendBanned(); + break; + } + + $this->sendUpdates(); + break; - case 'refresh': - $ys = ys($_SESSION['yLog']); - if ($ys->banned(ip())) { $this->sendBanned(); break; } - - $this->sendUpdates(); - break; + case 'reload': + $this->reload(); + break; + + case 'ban': + $this->doBan(); + break; - case 'reload': - $this->reload(); - break; - - case 'ban': - $this->doBan(); - break; + case 'unban': + $this->doUnban(); + break; + + case 'delete': + $this->doDelete(); + break; - case 'unban': - $this->doUnban(); - break; - - case 'delete': - $this->doDelete(); - break; + case 'banself': + $this->banSelf(); + break; - case 'banself': - $this->banSelf(); - break; + case 'unbanself': + $this->unbanSelf(); + break; - case 'unbanself': - $this->unbanSelf(); - break; + case 'clearlog': + $this->clearLog(); + break; + + case 'clearlogs': + $this->clearLogs(); + break; + } + } - case 'clearlog': - $this->clearLog(); - break; - - case 'clearlogs': - $this->clearLogs(); - break; - } - } + public function doBan() + { + $ip = $_POST['ip']; + $nickname = $_POST['nickname']; + $send = []; + $ys = ys($_SESSION['yLog']); - function doBan() { - $ip = $_POST['ip']; - $nickname = $_POST['nickname']; - $send = array(); - $ys = ys($_SESSION['yLog']); + switch (true) { + case !loggedIn(): + $send['error'] = 'admin'; + break; + case $ys->banned($ip): + $send['error'] = 'already'; + break; + default: + $ys->ban($ip, $nickname); + if ($ip == ip()) { + $send['bannedSelf'] = true; + } + $send['error'] = false; + } - switch(true) { - case !loggedIn(): - $send['error'] = 'admin'; - break; - case $ys->banned($ip): - $send['error'] = 'already'; - break; - default: - $ys->ban($ip, $nickname); - if ($ip == ip()) - $send['bannedSelf'] = true; - $send['error'] = false; - } + echo json_encode($send); + } - echo json_encode($send); - } + public function doUnban() + { + $ip = $_POST['ip']; + $send = []; + $ys = ys($_SESSION['yLog']); - function doUnban() { - $ip = $_POST['ip']; - $send = array(); - $ys = ys($_SESSION['yLog']); + switch (true) { + case !loggedIn(): + $send['error'] = 'admin'; + break; + case !$ys->banned($ip): + $send['error'] = 'already'; + break; + default: + $ys->unban($ip); + $send['error'] = false; + } - switch(true) { - case !loggedIn(): - $send['error'] = 'admin'; - break; - case !$ys->banned($ip): - $send['error'] = 'already'; - break; - default: - $ys->unban($ip); - $send['error'] = false; - } + echo json_encode($send); + } - echo json_encode($send); - } + public function doDelete() + { + $uid = $_POST['uid']; + $send = []; + $ys = ys($_SESSION['yLog']); - function doDelete() { - $uid = $_POST['uid']; - $send = array(); - $ys = ys($_SESSION['yLog']); + switch (true) { + case !loggedIn(): + $send['error'] = 'admin'; + break; + default: + $ys->delete($uid); + $send['error'] = false; + } - switch(true) { - case !loggedIn(): - $send['error'] = 'admin'; - break; - default: - $ys->delete($uid); - $send['error'] = false; - } + echo json_encode($send); + } - echo json_encode($send); - } + public function banSelf() + { + $ys = ys($_SESSION['yLog']); + $nickname = $_POST['nickname']; + $ys->ban(ip(), $nickname); - function banSelf() { - $ys = ys($_SESSION['yLog']); - $nickname = $_POST['nickname']; - $ys->ban(ip(), $nickname); + $send = []; + $send['error'] = false; + + echo json_encode($send); + } - $send = array(); - $send['error'] = false; - - echo json_encode($send); - } + public function unbanSelf() + { + if (loggedIn()) { + $ys = ys($_SESSION['yLog']); + $ys->unban(ip()); + + $send = []; + $send['error'] = false; + } else { + $send = []; + $send['error'] = 'admin'; + } + + echo json_encode($send); + } + + public function reload() + { + global $prefs; + $ys = ys($_SESSION['yLog']); - function unbanSelf() { - if (loggedIn()) { - $ys = ys($_SESSION['yLog']); - $ys->unban(ip()); - - $send = array(); - $send['error'] = false; - } else { - $send = array(); - $send['error'] = 'admin'; - } - - echo json_encode($send); - } - - function reload() { - global $prefs; - $ys = ys($_SESSION['yLog']); + $posts = $ys->latestPosts($prefs['truncate']); + $this->setSessTimestamp($posts); + $this->updates['posts'] = $posts; + echo json_encode($this->updates); + } - $posts = $ys->latestPosts($prefs['truncate']); - $this->setSessTimestamp($posts); - $this->updates['posts'] = $posts; - echo json_encode($this->updates); - } + public function initSession() + { + $_SESSION['yLatestTimestamp'] = 0; + $_SESSION['yYPath'] = $_POST['yPath']; + $_SESSION['yLog'] = $_POST['log']; + $loginHash = cookieGet('yLoginHash') ; + if (isset($loginHash) && $loginHash != '') { + login($loginHash); + } + } - function initSession() { - $_SESSION['yLatestTimestamp'] = 0; - $_SESSION['yYPath'] = $_POST['yPath']; - $_SESSION['yLog'] = $_POST['log']; - $loginHash = cookieGet('yLoginHash') ; - if (isset($loginHash) && $loginHash != '') { - login($loginHash); - } - } + public function sendBanned() + { + $this->updates = [ + 'banned' => true + ]; - function sendBanned() { - $this->updates = array( - 'banned' => true - ); + echo json_encode($this->updates); + } + + public function sendUpdates() + { + global $prefs; + $ys = ys($_SESSION['yLog']); + if (!$ys->hasPostsAfter($_SESSION['yLatestTimestamp'])) { + return; + } - echo json_encode($this->updates); - } - - function sendUpdates() { - global $prefs; - $ys = ys($_SESSION['yLog']); - if (!$ys->hasPostsAfter($_SESSION['yLatestTimestamp'])) return; + $posts = $ys->postsAfter($_SESSION['yLatestTimestamp']); + $this->setSessTimestamp($posts); - $posts = $ys->postsAfter($_SESSION['yLatestTimestamp']); - $this->setSessTimestamp($posts); + $this->updates['posts'] = $posts; - $this->updates['posts'] = $posts; + echo json_encode($this->updates); + } - echo json_encode($this->updates); - } + public function setSessTimestamp(&$posts) + { + if (!$posts) { + return; + } - function setSessTimestamp(&$posts) { - if (!$posts) return; + $latest = array_slice($posts, -1, 1); + $_SESSION['yLatestTimestamp'] = $latest[0]['timestamp']; + } - $latest = array_slice( $posts, -1, 1); - $_SESSION['yLatestTimestamp'] = $latest[0]['timestamp']; - } + public function sendFirstUpdates() + { + global $prefs, $overrideNickname; - function sendFirstUpdates() { - global $prefs, $overrideNickname; + $this->updates = []; - $this->updates = array(); + $ys = ys($_SESSION['yLog']); - $ys = ys($_SESSION['yLog']); + $posts = $ys->latestPosts($prefs['truncate']); + $this->setSessTimestamp($posts); - $posts = $ys->latestPosts($prefs['truncate']); - $this->setSessTimestamp($posts); + $this->updates['posts'] = $posts; + $this->updates['prefs'] = $this->cleanPrefs($prefs); - $this->updates['posts'] = $posts; - $this->updates['prefs'] = $this->cleanPrefs($prefs); + if ($nickname = cookieGet('yNickname')) { + $this->updates['nickname'] = $nickname; + } + + if ($overrideNickname) { + $this->updates['nickname'] = $overrideNickname; + } + + if ($ys->banned(ip())) { + $this->updates['banned'] = true; + } - if ($nickname = cookieGet('yNickname')) - $this->updates['nickname'] = $nickname; - - if ($overrideNickname) - $this->updates['nickname'] = $overrideNickname; - - if ($ys->banned(ip())) - $this->updates['banned'] = true; + echo json_encode($this->updates); + } + + public function cleanPrefs($prefs) + { + unset($prefs['password']); + return $prefs; + } + + public function clearLog() + { + //$log = $_POST['log']; + $send = []; + $ys = ys($_SESSION['yLog']); - echo json_encode($this->updates); - } - - function cleanPrefs($prefs) { - unset($prefs['password']); - return $prefs; - } - - function clearLog() { - //$log = $_POST['log']; - $send = array(); - $ys = ys($_SESSION['yLog']); + switch (true) { + case !loggedIn(): + $send['error'] = 'admin'; + break; + default: + $ys->clear(); + $send['error'] = false; + } - switch(true) { - case !loggedIn(): - $send['error'] = 'admin'; - break; - default: - $ys->clear(); - $send['error'] = false; - } + echo json_encode($send); + } + + public function clearLogs() + { + global $prefs; + + //$log = $_POST['log']; + $send = []; - echo json_encode($send); - } - - function clearLogs() { - global $prefs; - - //$log = $_POST['log']; - $send = array(); - - //$ys = ys($_SESSION['yLog']); - - switch(true) { - case !loggedIn(): - $send['error'] = 'admin'; - break; - default: - for ($i = 1; $i <= $prefs['logs']; $i++) { - $ys = ys($i); - $ys->clear(); - } - - $send['error'] = false; - } - - echo json_encode($send); - } - } + //$ys = ys($_SESSION['yLog']); + switch (true) { + case !loggedIn(): + $send['error'] = 'admin'; + break; + default: + for ($i = 1; $i <= $prefs['logs']; $i++) { + $ys = ys($i); + $ys->clear(); + } + + $send['error'] = false; + } + echo json_encode($send); + } + } diff --git a/ext/chatbox/php/filestorage.class.php b/ext/chatbox/php/filestorage.class.php index a7ab5ba4..b75e4d82 100644 --- a/ext/chatbox/php/filestorage.class.php +++ b/ext/chatbox/php/filestorage.class.php @@ -1,84 +1,106 @@ shoutLog = $shoutLog; + $folder = 'logs'; + if (!is_dir($folder)) { + $folder = '../' . $folder; + } + if (!is_dir($folder)) { + $folder = '../' . $folder; + } + + $this->path = $folder . '/' . $path . '.txt'; + } + + public function open($lock = false) + { + $this->handle = fopen($this->path, 'a+'); - function FileStorage($path, $shoutLog = false) { - $this->shoutLog = $shoutLog; - $folder = 'logs'; - if (!is_dir($folder)) $folder = '../' . $folder; - if (!is_dir($folder)) $folder = '../' . $folder; - - $this->path = $folder . '/' . $path . '.txt'; - } - - function open($lock = false) { - $this->handle = fopen($this->path, 'a+'); + if ($lock) { + $this->lock(); + return $this->load(); + } + } - if ($lock) { - $this->lock(); - return $this->load(); - } - } + public function close(&$array) + { + if (isset($array)) { + $this->save($array); + } + + $this->unlock(); + fclose($this->handle); + unset($this->handle); + } - function close(&$array) { - if (isset($array)) - $this->save($array); - - $this->unlock(); - fclose($this->handle); - unset($this->handle); - } + public function load() + { + if (($contents = $this->read($this->path)) == null) { + return $this->resetArray(); + } - function load() { - if (($contents = $this->read($this->path)) == null) - return $this->resetArray(); + return unserialize($contents); + } - return unserialize($contents); - } + public function save(&$array, $unlock = true) + { + $contents = serialize($array); + $this->write($contents); + if ($unlock) { + $this->unlock(); + } + } - function save(&$array, $unlock = true) { - $contents = serialize($array); - $this->write($contents); - if ($unlock) $this->unlock(); - } + public function unlock() + { + if (isset($this->handle)) { + flock($this->handle, LOCK_UN); + } + } + + public function lock() + { + if (isset($this->handle)) { + flock($this->handle, LOCK_EX); + } + } - function unlock() { - if (isset($this->handle)) - flock($this->handle, LOCK_UN); - } - - function lock() { - if (isset($this->handle)) - flock($this->handle, LOCK_EX); - } + public function read() + { + fseek($this->handle, 0); + //return stream_get_contents($this->handle); + return file_get_contents($this->path); + } - function read() { - fseek($this->handle, 0); - //return stream_get_contents($this->handle); - return file_get_contents($this->path); - } + public function write($contents) + { + ftruncate($this->handle, 0); + fwrite($this->handle, $contents); + } - function write($contents) { - ftruncate($this->handle, 0); - fwrite($this->handle, $contents); - } + public function resetArray() + { + if ($this->shoutLog) { + $default = [ + 'info' => [ + 'latestTimestamp' => -1 + ], + + 'posts' => [] + ]; + } else { + $default = []; + } - function resetArray() { - if ($this->shoutLog) - $default = array( - 'info' => array( - 'latestTimestamp' => -1 - ), - - 'posts' => array() - ); - else - $default = array(); - - $this->save($default, false); - return $default; - } + $this->save($default, false); + return $default; + } } - diff --git a/ext/chatbox/php/functions.php b/ext/chatbox/php/functions.php index 23eca1c1..9ab9430f 100644 --- a/ext/chatbox/php/functions.php +++ b/ext/chatbox/php/functions.php @@ -1,141 +1,174 @@ = $len) { + break; + } + if ($chr & 0x80) { + $chr <<= 1; + while ($chr & 0x80) { + $i++; + $chr <<= 1; + } + } + } - if ($i >= $len) break; - if ($chr & 0x80) { - $chr <<= 1; - while ($chr & 0x80) { - $i++; - $chr <<= 1; - } - } - } + return $count; + } - return $count; - } + function error($err) + { + echo 'Error: ' . $err; + exit; + } - function error($err) { - echo 'Error: ' . $err; - exit; - } + function ys($log = 1) + { + global $yShout, $prefs; + if ($yShout) { + return $yShout; + } - function ys($log = 1) { - global $yShout, $prefs; - if ($yShout) return $yShout; + if (filter_var($log, FILTER_VALIDATE_INT, ["options" => ["min_range" => 0, "max_range" => $prefs['logs']]]) === false) { + $log = 1; + } + + $log = 'log.' . $log; + return new YShout($log, loggedIn()); + } - if (filter_var($log, FILTER_VALIDATE_INT, array("options" => array("min_range" => 0, "max_range" => $prefs['logs']))) === false) - { - $log = 1; - } - - $log = 'log.' . $log; - return new YShout($log, loggedIn()); - } + function dstart() + { + global $ts; - function dstart() { - global $ts; + $ts = ts(); + } - $ts = ts(); - } + function dstop() + { + global $ts; + echo 'Time elapsed: ' . ((ts() - $ts) * 100000); + exit; + } - function dstop() { - global $ts; - echo 'Time elapsed: ' . ((ts() - $ts) * 100000); - exit; - } + function login($hash) + { + // echo 'login: ' . $hash . "\n"; + + $_SESSION['yLoginHash'] = $hash; + cookie('yLoginHash', $hash); + // return loggedIn(); + } - function login($hash) { - // echo 'login: ' . $hash . "\n"; - - $_SESSION['yLoginHash'] = $hash; - cookie('yLoginHash', $hash); - // return loggedIn(); - } + function logout() + { + $_SESSION['yLoginHash'] = ''; + cookie('yLoginHash', ''); + // cookieClear('yLoginHash'); + } - function logout() { - $_SESSION['yLoginHash'] = ''; - cookie('yLoginHash', ''); -// cookieClear('yLoginHash'); - } + function loggedIn() + { + global $prefs; - function loggedIn() { - global $prefs; + $loginHash = cookieGet('yLoginHash', false); + // echo 'loggedin: ' . $loginHash . "\n"; + // echo 'pw: ' . $prefs['password'] . "\n"; + + if (isset($loginHash)) { + return $loginHash == md5($prefs['password']); + } - $loginHash = cookieGet('yLoginHash', false); -// echo 'loggedin: ' . $loginHash . "\n"; -// echo 'pw: ' . $prefs['password'] . "\n"; - - if (isset($loginHash)) return $loginHash == md5($prefs['password']); - - if (isset($_SESSION['yLoginHash'])) - return $_SESSION['yLoginHash'] == md5($prefs['password']); - - return false; - } + if (isset($_SESSION['yLoginHash'])) { + return $_SESSION['yLoginHash'] == md5($prefs['password']); + } + return false; + } diff --git a/ext/chatbox/php/yshout.class.php b/ext/chatbox/php/yshout.class.php index e3b3f02b..205eda37 100644 --- a/ext/chatbox/php/yshout.class.php +++ b/ext/chatbox/php/yshout.class.php @@ -1,251 +1,292 @@ storage = new $storage($path, true); + $this->admin = $admin; + } - $this->storage = new $storage($path, true); - $this->admin = $admin; - } + public function posts() + { + global $null; + $this->storage->open(); + $s = $this->storage->load(); + $this->storage->close($null); - function posts() { - global $null; - $this->storage->open(); - $s = $this->storage->load(); - $this->storage->close($null); + if ($s) { + return $s['posts']; + } + } - if ($s) - return $s['posts']; - } + public function info() + { + global $null; + $s = $this->storage->open(true); - function info() { - global $null; - $s = $this->storage->open(true); + $this->storage->close($null); - $this->storage->close($null); + if ($s) { + return $s['info']; + } + } - if ($s) - return $s['info']; - } + public function postsAfter($ts) + { + $allPosts = $this->posts(); - function postsAfter($ts) { - $allPosts = $this->posts(); + $posts = []; - $posts = array(); + /* for ($i = sizeof($allPosts) - 1; $i > -1; $i--) { + $post = $allPosts[$i]; - /* for ($i = sizeof($allPosts) - 1; $i > -1; $i--) { - $post = $allPosts[$i]; + if ($post['timestamp'] > $ts) + $posts[] = $post; + } */ - if ($post['timestamp'] > $ts) - $posts[] = $post; - } */ + foreach ($allPosts as $post) { + if ($post['timestamp'] > $ts) { + $posts[] = $post; + } + } - foreach($allPosts as $post) { - if ($post['timestamp'] > $ts) - $posts[] = $post; - } + $this->postProcess($posts); + return $posts; + } - $this->postProcess($posts); - return $posts; - } + public function latestPosts($num) + { + $allPosts = $this->posts(); + $posts = array_slice($allPosts, -$num, $num); - function latestPosts($num) { - $allPosts = $this->posts(); - $posts = array_slice($allPosts, -$num, $num); + $this->postProcess($posts); + return array_values($posts); + } - $this->postProcess($posts); - return array_values($posts); - } + public function hasPostsAfter($ts) + { + $info = $this->info(); + $timestamp = $info['latestTimestamp']; + return $timestamp > $ts; + } - function hasPostsAfter($ts) { - $info = $this->info(); - $timestamp = $info['latestTimestamp']; - return $timestamp > $ts; - } + public function post($nickname, $message) + { + global $prefs; - function post($nickname, $message) { - global $prefs; + if ($this->banned(ip()) /* && !$this->admin*/) { + return false; + } - if ($this->banned(ip()) /* && !$this->admin*/) return false; + if (!$this->validate($message, $prefs['messageLength'])) { + return false; + } + if (!$this->validate($nickname, $prefs['nicknameLength'])) { + return false; + } - if (!$this->validate($message, $prefs['messageLength'])) return false; - if (!$this->validate($nickname, $prefs['nicknameLength'])) return false; + $message = trim(clean($message)); + $nickname = trim(clean($nickname)); + + if ($message == '') { + return false; + } + if ($nickname == '') { + return false; + } + + $timestamp = ts(); + + $message = $this->censor($message); + $nickname = $this->censor($nickname); + + $post = [ + 'nickname' => $nickname, + 'message' => $message, + 'timestamp' => $timestamp, + 'admin' => $this->admin, + 'uid' => md5($timestamp . ' ' . $nickname), + 'adminInfo' => [ + 'ip' => ip() + ] + ]; - $message = trim(clean($message)); - $nickname = trim(clean($nickname)); - - if ($message == '') return false; - if ($nickname == '') return false; - - $timestamp = ts(); - - $message = $this->censor($message); - $nickname = $this->censor($nickname); - - $post = array( - 'nickname' => $nickname, - 'message' => $message, - 'timestamp' => $timestamp, - 'admin' => $this->admin, - 'uid' => md5($timestamp . ' ' . $nickname), - 'adminInfo' => array( - 'ip' => ip() - ) - ); + $s = $this->storage->open(true); - $s = $this->storage->open(true); + $s['posts'][] = $post; - $s['posts'][] = $post; + if (sizeof($s['posts']) > $prefs['history']) { + $this->truncate($s['posts']); + } - if (sizeof($s['posts']) > $prefs['history']) - $this->truncate($s['posts']); + $s['info']['latestTimestamp'] = $post['timestamp']; - $s['info']['latestTimestamp'] = $post['timestamp']; + $this->storage->close($s); + $this->postProcess($post); + return $post; + } - $this->storage->close($s); - $this->postProcess($post); - return $post; - } + public function truncate(&$array) + { + global $prefs; - function truncate(&$array) { - global $prefs; + $array = array_slice($array, -$prefs['history']); + $array = array_values($array); + } - $array = array_slice($array, -$prefs['history']); - $array = array_values($array); - } + public function clear() + { + global $null; - function clear() { - global $null; + $this->storage->open(true); + $this->storage->resetArray(); + // ? Scared to touch it... Misspelled though. Update: Touched! Used to be $nulls... + $this->storage->close($null); + } - $this->storage->open(true); - $this->storage->resetArray(); - // ? Scared to touch it... Misspelled though. Update: Touched! Used to be $nulls... - $this->storage->close($null); - } + public function bans() + { + global $storage, $null; - function bans() { - global $storage, $null; + $s = new $storage('yshout.bans'); + $s->open(); + $bans = $s->load(); + $s->close($null); - $s = new $storage('yshout.bans'); - $s->open(); - $bans = $s->load(); - $s->close($null); + return $bans; + } - return $bans; - } + public function ban($ip, $nickname = '', $info = '') + { + global $storage; - function ban($ip, $nickname = '', $info = '') { - global $storage; + $s = new $storage('yshout.bans'); + $bans = $s->open(true); - $s = new $storage('yshout.bans'); - $bans = $s->open(true); + $bans[] = [ + 'ip' => $ip, + 'nickname' => $nickname, + 'info' => $info, + 'timestamp' => ts() + ]; - $bans[] = array( - 'ip' => $ip, - 'nickname' => $nickname, - 'info' => $info, - 'timestamp' => ts() - ); + $s->close($bans); + } - $s->close($bans); - } + public function banned($ip) + { + global $storage, $null; - function banned($ip) { - global $storage, $null; + $s = new $storage('yshout.bans'); + $bans = $s->open(true); + $s->close($null); - $s = new $storage('yshout.bans'); - $bans = $s->open(true); - $s->close($null); + foreach ($bans as $ban) { + if ($ban['ip'] == $ip) { + return true; + } + } - foreach($bans as $ban) { - if ($ban['ip'] == $ip) - return true; - } + return false; + } - return false; - } + public function unban($ip) + { + global $storage; - function unban($ip) { - global $storage; + $s = new $storage('yshout.bans'); + $bans = $s->open(true); - $s = new $storage('yshout.bans'); - $bans = $s->open(true); + foreach ($bans as $key=>$value) { + if ($value['ip'] == $ip) { + unset($bans[$key]); + } + } - foreach($bans as $key=>$value) - if ($value['ip'] == $ip) { - unset($bans[$key]); - } + $bans = array_values($bans); + $s->close($bans); + } - $bans = array_values($bans); - $s->close($bans); + public function unbanAll() + { + global $storage, $null; - } + $s = new $storage('yshout.bans'); + $s->open(true); + $s->resetArray(); + $s->close($null); + } - function unbanAll() { - global $storage, $null; + public function delete($uid) + { + global $prefs, $storage; - $s = new $storage('yshout.bans'); - $s->open(true); - $s->resetArray(); - $s->close($null); - } + + $s = $this->storage->open(true); - function delete($uid) { - global $prefs, $storage; + $posts = $s['posts']; + + foreach ($posts as $key=>$value) { + if (!isset($value['uid'])) { + unset($posts['key']); + } elseif ($value['uid'] == $uid) { + unset($posts[$key]); + } + } + + $s['posts'] = array_values($posts); + $this->storage->close($s); - - $s = $this->storage->open(true); + return true; + } + + public function validate($str, $maxLen) + { + return len($str) <= $maxLen; + } + + public function censor($str) + { + global $prefs; + + $cWords = explode(' ', $prefs['censorWords']); + $words = explode(' ', $str); + $endings = '|ed|es|ing|s|er|ers'; + $arrEndings = explode('|', $endings); + + foreach ($cWords as $cWord) { + foreach ($words as $i=>$word) { + $pattern = '/^(' . $cWord . ')+(' . $endings . ')\W*$/i'; + $words[$i] = preg_replace($pattern, str_repeat('*', strlen($word)), $word); + } + } + + return implode(' ', $words); + } - $posts = $s['posts']; - - foreach($posts as $key=>$value) { - if (!isset($value['uid'])) - unset($posts['key']); - else - if($value['uid'] == $uid) - unset($posts[$key]); - } - - $s['posts'] = array_values($posts); - $this->storage->close($s); - - return true; - } - - function validate($str, $maxLen) { - return len($str) <= $maxLen; - } - - function censor($str) { - global $prefs; - - $cWords = explode(' ', $prefs['censorWords']); - $words = explode(' ', $str); - $endings = '|ed|es|ing|s|er|ers'; - $arrEndings = explode('|', $endings); - - foreach ($cWords as $cWord) foreach ($words as $i=>$word) { - $pattern = '/^(' . $cWord . ')+(' . $endings . ')\W*$/i'; - $words[$i] = preg_replace($pattern, str_repeat('*', strlen($word)), $word); - } - - return implode(' ', $words); - } - - function postProcess(&$post) { - if (isset($post['message'])) { - if ($this->banned($post['adminInfo']['ip'])) $post['banned'] = true; - if (!$this->admin) unset($post['adminInfo']); - } else { - foreach($post as $key=>$value) { - if ($this->banned($value['adminInfo']['ip'])) $post[$key]['banned'] = true; - if (!$this->admin) unset($post[$key]['adminInfo']); - } - } - } + public function postProcess(&$post) + { + if (isset($post['message'])) { + if ($this->banned($post['adminInfo']['ip'])) { + $post['banned'] = true; + } + if (!$this->admin) { + unset($post['adminInfo']); + } + } else { + foreach ($post as $key=>$value) { + if ($this->banned($value['adminInfo']['ip'])) { + $post[$key]['banned'] = true; + } + if (!$this->admin) { + unset($post[$key]['adminInfo']); + } + } + } + } } - - diff --git a/ext/chatbox/preferences.php b/ext/chatbox/preferences.php index cc72b33b..4a337ac9 100644 --- a/ext/chatbox/preferences.php +++ b/ext/chatbox/preferences.php @@ -1,74 +1,75 @@ open(); - $prefs = $s->load(); - $s->close($null); - } + // If you want to change the nickname, the line below is the one to modify. + // Simply set $overrideNickname to whatever variable you want to appear as the nickname, + // or leave it null to use the set nicknames. + + $overrideNickname = null; + + $storage = 'FileStorage'; + + function loadPrefs() + { + global $prefs, $storage, $null; + $s = new $storage('yshout.prefs'); + $s->open(); + $prefs = $s->load(); + $s->close($null); + } - function savePrefs($newPrefs) { - global $prefs, $storage; + function savePrefs($newPrefs) + { + global $prefs, $storage; - $s = new $storage('yshout.prefs'); - $s->open(true); - $s->close($newPrefs); - $prefs = $newPrefs; - } - - function resetPrefs() { - $defaultPrefs = array( - 'password' => 'fortytwo', // The password for the CP + $s = new $storage('yshout.prefs'); + $s->open(true); + $s->close($newPrefs); + $prefs = $newPrefs; + } + + function resetPrefs() + { + $defaultPrefs = [ + 'password' => 'fortytwo', // The password for the CP - 'refresh' => 6000, // Refresh rate + 'refresh' => 6000, // Refresh rate - 'logs' => 5, // Amount of different log files to allow - 'history' => 200, // Shouts to keep in history + 'logs' => 5, // Amount of different log files to allow + 'history' => 200, // Shouts to keep in history - 'inverse' => false, // Inverse shoutbox / form on top + 'inverse' => false, // Inverse shoutbox / form on top - 'truncate' => 15, // Truncate messages client-side - 'doTruncate' => true, // Truncate messages? + 'truncate' => 15, // Truncate messages client-side + 'doTruncate' => true, // Truncate messages? - 'timestamp' => 12, // Timestamp format 12- or 24-hour + 'timestamp' => 12, // Timestamp format 12- or 24-hour - 'defaultNickname' => 'Nickname', - 'defaultMessage' => 'Message Text', - 'defaultSubmit' => 'Shout!', - 'showSubmit' => true, - - 'nicknameLength' => 25, - 'messageLength' => 175, + 'defaultNickname' => 'Nickname', + 'defaultMessage' => 'Message Text', + 'defaultSubmit' => 'Shout!', + 'showSubmit' => true, + + 'nicknameLength' => 25, + 'messageLength' => 175, - 'nicknameSeparator' => ':', - - 'flood' => true, - 'floodTimeout' => 5000, - 'floodMessages' => 4, - 'floodDisable' => 8000, - 'floodDelete' => false, - - 'autobanFlood' => 0, // Autoban people for flooding after X messages + 'nicknameSeparator' => ':', + + 'flood' => true, + 'floodTimeout' => 5000, + 'floodMessages' => 4, + 'floodDisable' => 8000, + 'floodDelete' => false, + + 'autobanFlood' => 0, // Autoban people for flooding after X messages - 'censorWords' => 'fuck shit bitch ass', - - 'postFormLink' => 'history', - - 'info' => 'inline' - ); - - savePrefs($defaultPrefs); - } - - resetPrefs(); - //loadPrefs(); + 'censorWords' => 'fuck shit bitch ass', + + 'postFormLink' => 'history', + 'info' => 'inline' + ]; + savePrefs($defaultPrefs); + } + + resetPrefs(); + //loadPrefs(); diff --git a/ext/chatbox/yshout.php b/ext/chatbox/yshout.php index 0994309f..dfa356b9 100644 --- a/ext/chatbox/yshout.php +++ b/ext/chatbox/yshout.php @@ -5,34 +5,35 @@ ob_start(); set_error_handler('errorOccurred'); include 'include.php'; -if (isset($_POST['reqFor'])) - switch($_POST['reqFor']) { - case 'shout': +if (isset($_POST['reqFor'])) { + switch ($_POST['reqFor']) { + case 'shout': - $ajax = new AjaxCall(); - $ajax->process(); - break; + $ajax = new AjaxCall(); + $ajax->process(); + break; - case 'history': - - // echo $_POST['log']; - $ajax = new AjaxCall($_POST['log']); - $ajax->process(); - break; + case 'history': + + // echo $_POST['log']; + $ajax = new AjaxCall($_POST['log']); + $ajax->process(); + break; - default: - exit; - } else { - include 'example.html'; - } - -function errorOccurred($num, $str, $file, $line) { - $err = array ( - 'yError' => "$str. \n File: $file \n Line: $line" - ); - - echo json_encode($err); - - exit; + default: + exit; + } +} else { + include 'example.html'; } +function errorOccurred($num, $str, $file, $line) +{ + $err = [ + 'yError' => "$str. \n File: $file \n Line: $line" + ]; + + echo json_encode($err); + + exit; +} diff --git a/ext/comment/main.php b/ext/comment/main.php index 3def8f60..ba4b58e4 100644 --- a/ext/comment/main.php +++ b/ext/comment/main.php @@ -11,19 +11,21 @@ require_once "vendor/ifixit/php-akismet/akismet.class.php"; -class CommentPostingEvent extends Event { - /** @var int */ - public $image_id; - /** @var \User */ - public $user; - /** @var string */ - public $comment; +class CommentPostingEvent extends Event +{ + /** @var int */ + public $image_id; + /** @var \User */ + public $user; + /** @var string */ + public $comment; - public function __construct(int $image_id, User $user, string $comment) { - $this->image_id = $image_id; - $this->user = $user; - $this->comment = $comment; - } + public function __construct(int $image_id, User $user, string $comment) + { + $this->image_id = $image_id; + $this->user = $user; + $this->comment = $comment; + } } /** @@ -31,66 +33,85 @@ class CommentPostingEvent extends Event { * detectors to get a feel for what should be deleted * and what should be kept? */ -class CommentDeletionEvent extends Event { - /** @var int */ - public $comment_id; +class CommentDeletionEvent extends Event +{ + /** @var int */ + public $comment_id; - public function __construct(int $comment_id) { - $this->comment_id = $comment_id; - } + public function __construct(int $comment_id) + { + $this->comment_id = $comment_id; + } } -class CommentPostingException extends SCoreException {} +class CommentPostingException extends SCoreException +{ +} -class Comment { - public $owner, $owner_id, $owner_name, $owner_email, $owner_class; - public $comment, $comment_id; - public $image_id, $poster_ip, $posted; +class Comment +{ + public $owner; + public $owner_id; + public $owner_name; + public $owner_email; + public $owner_class; + public $comment; + public $comment_id; + public $image_id; + public $poster_ip; + public $posted; - public function __construct($row) { - $this->owner = null; - $this->owner_id = $row['user_id']; - $this->owner_name = $row['user_name']; - $this->owner_email = $row['user_email']; // deprecated - $this->owner_class = $row['user_class']; - $this->comment = $row['comment']; - $this->comment_id = $row['comment_id']; - $this->image_id = $row['image_id']; - $this->poster_ip = $row['poster_ip']; - $this->posted = $row['posted']; - } + public function __construct($row) + { + $this->owner = null; + $this->owner_id = $row['user_id']; + $this->owner_name = $row['user_name']; + $this->owner_email = $row['user_email']; // deprecated + $this->owner_class = $row['user_class']; + $this->comment = $row['comment']; + $this->comment_id = $row['comment_id']; + $this->image_id = $row['image_id']; + $this->poster_ip = $row['poster_ip']; + $this->posted = $row['posted']; + } - public static function count_comments_by_user(User $user): int { - global $database; - return $database->get_one(" + public static function count_comments_by_user(User $user): int + { + global $database; + return $database->get_one(" SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id - ", array("owner_id"=>$user->id)); - } + ", ["owner_id"=>$user->id]); + } - public function get_owner(): User { - if(empty($this->owner)) $this->owner = User::by_id($this->owner_id); - return $this->owner; - } + public function get_owner(): User + { + if (empty($this->owner)) { + $this->owner = User::by_id($this->owner_id); + } + return $this->owner; + } } -class CommentList extends Extension { - /** @var CommentListTheme $theme */ - public $theme; +class CommentList extends Extension +{ + /** @var CommentListTheme $theme */ + public $theme; - public function onInitExt(InitExtEvent $event) { - global $config, $database; - $config->set_default_int('comment_window', 5); - $config->set_default_int('comment_limit', 10); - $config->set_default_int('comment_list_count', 10); - $config->set_default_int('comment_count', 5); - $config->set_default_bool('comment_captcha', false); + public function onInitExt(InitExtEvent $event) + { + global $config, $database; + $config->set_default_int('comment_window', 5); + $config->set_default_int('comment_limit', 10); + $config->set_default_int('comment_list_count', 10); + $config->set_default_int('comment_count', 5); + $config->set_default_bool('comment_captcha', false); - if($config->get_int("ext_comments_version") < 3) { - // shortcut to latest - if($config->get_int("ext_comments_version") < 1) { - $database->create_table("comments", " + if ($config->get_int("ext_comments_version") < 3) { + // shortcut to latest + if ($config->get_int("ext_comments_version") < 1) { + $database->create_table("comments", " id SCORE_AIPK, image_id INTEGER NOT NULL, owner_id INTEGER NOT NULL, @@ -100,15 +121,15 @@ class CommentList extends Extension { FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT "); - $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", array()); - $database->execute("CREATE INDEX comments_owner_id_idx ON comments(owner_id)", array()); - $database->execute("CREATE INDEX comments_posted_idx ON comments(posted)", array()); - $config->set_int("ext_comments_version", 3); - } + $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", []); + $database->execute("CREATE INDEX comments_owner_id_idx ON comments(owner_id)", []); + $database->execute("CREATE INDEX comments_posted_idx ON comments(posted)", []); + $config->set_int("ext_comments_version", 3); + } - // the whole history - if($config->get_int("ext_comments_version") < 1) { - $database->create_table("comments", " + // the whole history + if ($config->get_int("ext_comments_version") < 1) { + $database->create_table("comments", " id SCORE_AIPK, image_id INTEGER NOT NULL, owner_id INTEGER NOT NULL, @@ -116,278 +137,293 @@ class CommentList extends Extension { posted SCORE_DATETIME DEFAULT NULL, comment TEXT NOT NULL "); - $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", array()); - $config->set_int("ext_comments_version", 1); - } + $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", []); + $config->set_int("ext_comments_version", 1); + } - if($config->get_int("ext_comments_version") == 1) { - $database->Execute("CREATE INDEX comments_owner_ip ON comments(owner_ip)"); - $database->Execute("CREATE INDEX comments_posted ON comments(posted)"); - $config->set_int("ext_comments_version", 2); - } + if ($config->get_int("ext_comments_version") == 1) { + $database->Execute("CREATE INDEX comments_owner_ip ON comments(owner_ip)"); + $database->Execute("CREATE INDEX comments_posted ON comments(posted)"); + $config->set_int("ext_comments_version", 2); + } - if($config->get_int("ext_comments_version") == 2) { - $config->set_int("ext_comments_version", 3); - $database->Execute("ALTER TABLE comments ADD FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE"); - $database->Execute("ALTER TABLE comments ADD FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT"); - } + if ($config->get_int("ext_comments_version") == 2) { + $config->set_int("ext_comments_version", 3); + $database->Execute("ALTER TABLE comments ADD FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE"); + $database->Execute("ALTER TABLE comments ADD FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT"); + } - // FIXME: add foreign keys, bump to v3 - } - } + // FIXME: add foreign keys, bump to v3 + } + } - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("comment")) { - switch($event->get_arg(0)) { - case "add": $this->onPageRequest_add(); break; - case "delete": $this->onPageRequest_delete($event); break; - case "bulk_delete": $this->onPageRequest_bulk_delete(); break; - case "list": $this->onPageRequest_list($event); break; - case "beta-search": $this->onPageRequest_beta_search($event); break; - } - } - } + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("comment")) { + switch ($event->get_arg(0)) { + case "add": $this->onPageRequest_add(); break; + case "delete": $this->onPageRequest_delete($event); break; + case "bulk_delete": $this->onPageRequest_bulk_delete(); break; + case "list": $this->onPageRequest_list($event); break; + case "beta-search": $this->onPageRequest_beta_search($event); break; + } + } + } - private function onPageRequest_add() { - global $user, $page; - if (isset($_POST['image_id']) && isset($_POST['comment'])) { - try { - $i_iid = int_escape($_POST['image_id']); - $cpe = new CommentPostingEvent($_POST['image_id'], $user, $_POST['comment']); - send_event($cpe); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$i_iid#comment_on_$i_iid")); - } catch (CommentPostingException $ex) { - $this->theme->display_error(403, "Comment Blocked", $ex->getMessage()); - } - } - } + private function onPageRequest_add() + { + global $user, $page; + if (isset($_POST['image_id']) && isset($_POST['comment'])) { + try { + $i_iid = int_escape($_POST['image_id']); + $cpe = new CommentPostingEvent($_POST['image_id'], $user, $_POST['comment']); + send_event($cpe); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$i_iid#comment_on_$i_iid")); + } catch (CommentPostingException $ex) { + $this->theme->display_error(403, "Comment Blocked", $ex->getMessage()); + } + } + } - private function onPageRequest_delete(PageRequestEvent $event) { - global $user, $page; - if ($user->can("delete_comment")) { - // FIXME: post, not args - if ($event->count_args() === 3) { - send_event(new CommentDeletionEvent($event->get_arg(1))); - flash_message("Deleted comment"); - $page->set_mode("redirect"); - if (!empty($_SERVER['HTTP_REFERER'])) { - $page->set_redirect($_SERVER['HTTP_REFERER']); - } else { - $page->set_redirect(make_link("post/view/" . $event->get_arg(2))); - } - } - } else { - $this->theme->display_permission_denied(); - } - } + private function onPageRequest_delete(PageRequestEvent $event) + { + global $user, $page; + if ($user->can("delete_comment")) { + // FIXME: post, not args + if ($event->count_args() === 3) { + send_event(new CommentDeletionEvent($event->get_arg(1))); + flash_message("Deleted comment"); + $page->set_mode("redirect"); + if (!empty($_SERVER['HTTP_REFERER'])) { + $page->set_redirect($_SERVER['HTTP_REFERER']); + } else { + $page->set_redirect(make_link("post/view/" . $event->get_arg(2))); + } + } + } else { + $this->theme->display_permission_denied(); + } + } - private function onPageRequest_bulk_delete() { - global $user, $database, $page; - if ($user->can("delete_comment") && !empty($_POST["ip"])) { - $ip = $_POST['ip']; + private function onPageRequest_bulk_delete() + { + global $user, $database, $page; + if ($user->can("delete_comment") && !empty($_POST["ip"])) { + $ip = $_POST['ip']; - $comment_ids = $database->get_col(" + $comment_ids = $database->get_col(" SELECT id FROM comments WHERE owner_ip=:ip - ", array("ip" => $ip)); - $num = count($comment_ids); - log_warning("comment", "Deleting $num comments from $ip"); - foreach($comment_ids as $cid) { - send_event(new CommentDeletionEvent($cid)); - } - flash_message("Deleted $num comments"); + ", ["ip" => $ip]); + $num = count($comment_ids); + log_warning("comment", "Deleting $num comments from $ip"); + foreach ($comment_ids as $cid) { + send_event(new CommentDeletionEvent($cid)); + } + flash_message("Deleted $num comments"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("admin")); - } else { - $this->theme->display_permission_denied(); - } - } + $page->set_mode("redirect"); + $page->set_redirect(make_link("admin")); + } else { + $this->theme->display_permission_denied(); + } + } - private function onPageRequest_list(PageRequestEvent $event) { - $page_num = int_escape($event->get_arg(1)); - $this->build_page($page_num); - } + private function onPageRequest_list(PageRequestEvent $event) + { + $page_num = int_escape($event->get_arg(1)); + $this->build_page($page_num); + } - private function onPageRequest_beta_search(PageRequestEvent $event) { - $search = $event->get_arg(1); - $page_num = int_escape($event->get_arg(2)); - $duser = User::by_name($search); - $i_comment_count = Comment::count_comments_by_user($duser); - $com_per_page = 50; - $total_pages = ceil($i_comment_count / $com_per_page); - $page_num = clamp($page_num, 1, $total_pages); - $comments = $this->get_user_comments($duser->id, $com_per_page, ($page_num - 1) * $com_per_page); - $this->theme->display_all_user_comments($comments, $page_num, $total_pages, $duser); - } + private function onPageRequest_beta_search(PageRequestEvent $event) + { + $search = $event->get_arg(1); + $page_num = int_escape($event->get_arg(2)); + $duser = User::by_name($search); + $i_comment_count = Comment::count_comments_by_user($duser); + $com_per_page = 50; + $total_pages = ceil($i_comment_count / $com_per_page); + $page_num = clamp($page_num, 1, $total_pages); + $comments = $this->get_user_comments($duser->id, $com_per_page, ($page_num - 1) * $com_per_page); + $this->theme->display_all_user_comments($comments, $page_num, $total_pages, $duser); + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_admin_block(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_admin_block(); + } - public function onPostListBuilding(PostListBuildingEvent $event) { - global $config, $database; - $cc = $config->get_int("comment_count"); - if($cc > 0) { - $recent = $database->cache->get("recent_comments"); - if(empty($recent)) { - $recent = $this->get_recent_comments($cc); - $database->cache->set("recent_comments", $recent, 60); - } - if(count($recent) > 0) { - $this->theme->display_recent_comments($recent); - } - } - } + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $config, $database; + $cc = $config->get_int("comment_count"); + if ($cc > 0) { + $recent = $database->cache->get("recent_comments"); + if (empty($recent)) { + $recent = $this->get_recent_comments($cc); + $database->cache->set("recent_comments", $recent, 60); + } + if (count($recent) > 0) { + $this->theme->display_recent_comments($recent); + } + } + } - public function onUserPageBuilding(UserPageBuildingEvent $event) { - $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; - $i_comment_count = Comment::count_comments_by_user($event->display_user); - $h_comment_rate = sprintf("%.1f", ($i_comment_count / $i_days_old)); - $event->add_stats("Comments made: $i_comment_count, $h_comment_rate per day"); + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; + $i_comment_count = Comment::count_comments_by_user($event->display_user); + $h_comment_rate = sprintf("%.1f", ($i_comment_count / $i_days_old)); + $event->add_stats("Comments made: $i_comment_count, $h_comment_rate per day"); - $recent = $this->get_user_comments($event->display_user->id, 10); - $this->theme->display_recent_user_comments($recent, $event->display_user); - } + $recent = $this->get_user_comments($event->display_user->id, 10); + $this->theme->display_recent_user_comments($recent, $event->display_user); + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $user; - $this->theme->display_image_comments( - $event->image, - $this->get_comments($event->image->id), - $user->can("create_comment") - ); - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $user; + $this->theme->display_image_comments( + $event->image, + $this->get_comments($event->image->id), + $user->can("create_comment") + ); + } - // TODO: split akismet into a separate class, which can veto the event - public function onCommentPosting(CommentPostingEvent $event) { - $this->add_comment_wrapper($event->image_id, $event->user, $event->comment); - } + // TODO: split akismet into a separate class, which can veto the event + public function onCommentPosting(CommentPostingEvent $event) + { + $this->add_comment_wrapper($event->image_id, $event->user, $event->comment); + } - public function onCommentDeletion(CommentDeletionEvent $event) { - global $database; - $database->Execute(" + public function onCommentDeletion(CommentDeletionEvent $event) + { + global $database; + $database->Execute(" DELETE FROM comments WHERE id=:comment_id - ", array("comment_id"=>$event->comment_id)); - log_info("comment", "Deleting Comment #{$event->comment_id}"); - } + ", ["comment_id"=>$event->comment_id]); + log_info("comment", "Deleting Comment #{$event->comment_id}"); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Comment Options"); - $sb->add_bool_option("comment_captcha", "Require CAPTCHA for anonymous comments: "); - $sb->add_label("
    Limit to "); - $sb->add_int_option("comment_limit"); - $sb->add_label(" comments per "); - $sb->add_int_option("comment_window"); - $sb->add_label(" minutes"); - $sb->add_label("
    Show "); - $sb->add_int_option("comment_count"); - $sb->add_label(" recent comments on the index"); - $sb->add_label("
    Show "); - $sb->add_int_option("comment_list_count"); - $sb->add_label(" comments per image on the list"); - $sb->add_label("
    Make samefags public "); - $sb->add_bool_option("comment_samefags_public"); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Comment Options"); + $sb->add_bool_option("comment_captcha", "Require CAPTCHA for anonymous comments: "); + $sb->add_label("
    Limit to "); + $sb->add_int_option("comment_limit"); + $sb->add_label(" comments per "); + $sb->add_int_option("comment_window"); + $sb->add_label(" minutes"); + $sb->add_label("
    Show "); + $sb->add_int_option("comment_count"); + $sb->add_label(" recent comments on the index"); + $sb->add_label("
    Show "); + $sb->add_int_option("comment_list_count"); + $sb->add_label(" comments per image on the list"); + $sb->add_label("
    Make samefags public "); + $sb->add_bool_option("comment_samefags_public"); + $event->panel->add_block($sb); + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; - if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $comments = $matches[2]; - $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); - } - else if(preg_match("/^commented_by[=|:](.*)$/i", $event->term, $matches)) { - $user = User::by_name($matches[1]); - if(!is_null($user)) { - $user_id = $user->id; - } else { - $user_id = -1; - } + if (preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $comments = $matches[2]; + $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); + } elseif (preg_match("/^commented_by[=|:](.*)$/i", $event->term, $matches)) { + $user = User::by_name($matches[1]); + if (!is_null($user)) { + $user_id = $user->id; + } else { + $user_id = -1; + } - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); - } - else if(preg_match("/^commented_by_userno[=|:]([0-9]+)$/i", $event->term, $matches)) { - $user_id = int_escape($matches[1]); - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); - } - } + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); + } elseif (preg_match("/^commented_by_userno[=|:]([0-9]+)$/i", $event->term, $matches)) { + $user_id = int_escape($matches[1]); + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); + } + } -// page building {{{ - private function build_page(int $current_page) { - global $database, $user; + // page building {{{ + private function build_page(int $current_page) + { + global $database, $user; - $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; - - $total_pages = $database->cache->get("comment_pages"); - if(empty($total_pages)) { - $total_pages = (int)($database->get_one(" + $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; + + $total_pages = $database->cache->get("comment_pages"); + if (empty($total_pages)) { + $total_pages = (int)($database->get_one(" SELECT COUNT(c1) FROM (SELECT COUNT(image_id) AS c1 FROM comments $where GROUP BY image_id) AS s1 ") / 10); - $database->cache->set("comment_pages", $total_pages, 600); - } - $total_pages = max($total_pages, 1); + $database->cache->set("comment_pages", $total_pages, 600); + } + $total_pages = max($total_pages, 1); - $current_page = clamp($current_page, 1, $total_pages); - - $threads_per_page = 10; - $start = $threads_per_page * ($current_page - 1); + $current_page = clamp($current_page, 1, $total_pages); + + $threads_per_page = 10; + $start = $threads_per_page * ($current_page - 1); - $result = $database->Execute(" + $result = $database->Execute(" SELECT image_id,MAX(posted) AS latest FROM comments $where GROUP BY image_id ORDER BY latest DESC LIMIT :limit OFFSET :offset - ", array("limit"=>$threads_per_page, "offset"=>$start)); + ", ["limit"=>$threads_per_page, "offset"=>$start]); - $user_ratings = ext_is_live("Ratings") ? Ratings::get_user_privs($user) : ""; + $user_ratings = ext_is_live("Ratings") ? Ratings::get_user_privs($user) : ""; - $images = array(); - while($row = $result->fetch()) { - $image = Image::by_id($row["image_id"]); - if( - ext_is_live("Ratings") && !is_null($image) && - strpos($user_ratings, $image->rating) === FALSE - ) { - $image = null; // this is "clever", I may live to regret it - } - if(!is_null($image)) { - $comments = $this->get_comments($image->id); - $images[] = array($image, $comments); - } - } + $images = []; + while ($row = $result->fetch()) { + $image = Image::by_id($row["image_id"]); + if ( + ext_is_live("Ratings") && !is_null($image) && + strpos($user_ratings, $image->rating) === false + ) { + $image = null; // this is "clever", I may live to regret it + } + if (!is_null($image)) { + $comments = $this->get_comments($image->id); + $images[] = [$image, $comments]; + } + } - $this->theme->display_comment_list($images, $current_page, $total_pages, $user->can("create_comment")); - } -// }}} + $this->theme->display_comment_list($images, $current_page, $total_pages, $user->can("create_comment")); + } + // }}} -// get comments {{{ - /** - * #return Comment[] - */ - private function get_generic_comments(string $query, array $args): array { - global $database; - $rows = $database->get_all($query, $args); - $comments = array(); - foreach($rows as $row) { - $comments[] = new Comment($row); - } - return $comments; - } + // get comments {{{ + /** + * #return Comment[] + */ + private function get_generic_comments(string $query, array $args): array + { + global $database; + $rows = $database->get_all($query, $args); + $comments = []; + foreach ($rows as $row) { + $comments[] = new Comment($row); + } + return $comments; + } - /** - * #return Comment[] - */ - private function get_recent_comments(int $count): array { - return $this->get_generic_comments(" + /** + * #return Comment[] + */ + private function get_recent_comments(int $count): array + { + return $this->get_generic_comments(" SELECT users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, comments.comment as comment, comments.id as comment_id, @@ -397,14 +433,15 @@ class CommentList extends Extension { LEFT JOIN users ON comments.owner_id=users.id ORDER BY comments.id DESC LIMIT :limit - ", array("limit"=>$count)); - } + ", ["limit"=>$count]); + } - /** - * #return Comment[] - */ - private function get_user_comments(int $user_id, int $count, int $offset=0): array { - return $this->get_generic_comments(" + /** + * #return Comment[] + */ + private function get_user_comments(int $user_id, int $count, int $offset=0): array + { + return $this->get_generic_comments(" SELECT users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, comments.comment as comment, comments.id as comment_id, @@ -415,14 +452,15 @@ class CommentList extends Extension { WHERE users.id = :user_id ORDER BY comments.id DESC LIMIT :limit OFFSET :offset - ", array("user_id"=>$user_id, "offset"=>$offset, "limit"=>$count)); - } + ", ["user_id"=>$user_id, "offset"=>$offset, "limit"=>$count]); + } - /** - * #return Comment[] - */ - private function get_comments(int $image_id): array { - return $this->get_generic_comments(" + /** + * #return Comment[] + */ + private function get_comments(int $image_id): array + { + return $this->get_generic_comments(" SELECT users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, comments.comment as comment, comments.id as comment_id, @@ -432,163 +470,170 @@ class CommentList extends Extension { LEFT JOIN users ON comments.owner_id=users.id WHERE comments.image_id=:image_id ORDER BY comments.id ASC - ", array("image_id"=>$image_id)); - } -// }}} + ", ["image_id"=>$image_id]); + } + // }}} -// add / remove / edit comments {{{ - private function is_comment_limit_hit(): bool { - global $config, $database; + // add / remove / edit comments {{{ + private function is_comment_limit_hit(): bool + { + global $config, $database; - // sqlite fails at intervals - if($database->get_driver_name() === "sqlite") return false; + // sqlite fails at intervals + if ($database->get_driver_name() === "sqlite") { + return false; + } - $window = int_escape($config->get_int('comment_window')); - $max = int_escape($config->get_int('comment_limit')); + $window = int_escape($config->get_int('comment_window')); + $max = int_escape($config->get_int('comment_limit')); - if($database->get_driver_name() == "mysql") $window_sql = "interval $window minute"; - else $window_sql = "interval '$window minute'"; + if ($database->get_driver_name() == "mysql") { + $window_sql = "interval $window minute"; + } else { + $window_sql = "interval '$window minute'"; + } - // window doesn't work as an SQL param because it's inside quotes >_< - $result = $database->get_all(" + // window doesn't work as an SQL param because it's inside quotes >_< + $result = $database->get_all(" SELECT * FROM comments WHERE owner_ip = :remote_ip AND posted > now() - $window_sql - ", array("remote_ip"=>$_SERVER['REMOTE_ADDR'])); + ", ["remote_ip"=>$_SERVER['REMOTE_ADDR']]); - return (count($result) >= $max); - } + return (count($result) >= $max); + } - private function hash_match(): bool { - return ($_POST['hash'] == $this->get_hash()); - } + private function hash_match(): bool + { + return ($_POST['hash'] == $this->get_hash()); + } - /** - * get a hash which semi-uniquely identifies a submission form, - * to stop spam bots which download the form once then submit - * many times. - * - * FIXME: assumes comments are posted via HTTP... - */ - public static function get_hash(): string { - return md5($_SERVER['REMOTE_ADDR'] . date("%Y%m%d")); - } + /** + * get a hash which semi-uniquely identifies a submission form, + * to stop spam bots which download the form once then submit + * many times. + * + * FIXME: assumes comments are posted via HTTP... + */ + public static function get_hash(): string + { + return md5($_SERVER['REMOTE_ADDR'] . date("%Y%m%d")); + } - private function is_spam_akismet(string $text): bool { - global $config, $user; - if(strlen($config->get_string('comment_wordpress_key')) > 0) { - $comment = array( - 'author' => $user->name, - 'email' => $user->email, - 'website' => '', - 'body' => $text, - 'permalink' => '', - ); + private function is_spam_akismet(string $text): bool + { + global $config, $user; + if (strlen($config->get_string('comment_wordpress_key')) > 0) { + $comment = [ + 'author' => $user->name, + 'email' => $user->email, + 'website' => '', + 'body' => $text, + 'permalink' => '', + ]; - # akismet breaks if there's no referrer in the environment; so if there - # isn't, supply one manually - if(!isset($_SERVER['HTTP_REFERER'])) { - $comment['referrer'] = 'none'; - log_warning("comment", "User '{$user->name}' commented with no referrer: $text"); - } - if(!isset($_SERVER['HTTP_USER_AGENT'])) { - $comment['user_agent'] = 'none'; - log_warning("comment", "User '{$user->name}' commented with no user-agent: $text"); - } + # akismet breaks if there's no referrer in the environment; so if there + # isn't, supply one manually + if (!isset($_SERVER['HTTP_REFERER'])) { + $comment['referrer'] = 'none'; + log_warning("comment", "User '{$user->name}' commented with no referrer: $text"); + } + if (!isset($_SERVER['HTTP_USER_AGENT'])) { + $comment['user_agent'] = 'none'; + log_warning("comment", "User '{$user->name}' commented with no user-agent: $text"); + } - $akismet = new Akismet( - $_SERVER['SERVER_NAME'], - $config->get_string('comment_wordpress_key'), - $comment); + $akismet = new Akismet( + $_SERVER['SERVER_NAME'], + $config->get_string('comment_wordpress_key'), + $comment + ); - if($akismet->errorsExist()) { - return false; - } - else { - return $akismet->isSpam(); - } - } + if ($akismet->errorsExist()) { + return false; + } else { + return $akismet->isSpam(); + } + } - return false; - } + return false; + } - private function is_dupe(int $image_id, string $comment): bool { - global $database; - return (bool)$database->get_row(" + private function is_dupe(int $image_id, string $comment): bool + { + global $database; + return (bool)$database->get_row(" SELECT * FROM comments WHERE image_id=:image_id AND comment=:comment - ", array("image_id"=>$image_id, "comment"=>$comment)); - } -// do some checks + ", ["image_id"=>$image_id, "comment"=>$comment]); + } + // do some checks - private function add_comment_wrapper(int $image_id, User $user, string $comment) { - global $database, $page; + private function add_comment_wrapper(int $image_id, User $user, string $comment) + { + global $database, $page; - if(!$user->can("bypass_comment_checks")) { - // will raise an exception if anything is wrong - $this->comment_checks($image_id, $user, $comment); - } + if (!$user->can("bypass_comment_checks")) { + // will raise an exception if anything is wrong + $this->comment_checks($image_id, $user, $comment); + } - // all checks passed - if($user->is_anonymous()) { - $page->add_cookie("nocache", "Anonymous Commenter", time()+60*60*24, "/"); - } - $database->Execute( - "INSERT INTO comments(image_id, owner_id, owner_ip, posted, comment) ". - "VALUES(:image_id, :user_id, :remote_addr, now(), :comment)", - array("image_id"=>$image_id, "user_id"=>$user->id, "remote_addr"=>$_SERVER['REMOTE_ADDR'], "comment"=>$comment)); - $cid = $database->get_last_insert_id('comments_id_seq'); - $snippet = substr($comment, 0, 100); - $snippet = str_replace("\n", " ", $snippet); - $snippet = str_replace("\r", " ", $snippet); - log_info("comment", "Comment #$cid added to Image #$image_id: $snippet", null, array("image_id"=>$image_id, "comment_id"=>$cid)); - } + // all checks passed + if ($user->is_anonymous()) { + $page->add_cookie("nocache", "Anonymous Commenter", time()+60*60*24, "/"); + } + $database->Execute( + "INSERT INTO comments(image_id, owner_id, owner_ip, posted, comment) ". + "VALUES(:image_id, :user_id, :remote_addr, now(), :comment)", + ["image_id"=>$image_id, "user_id"=>$user->id, "remote_addr"=>$_SERVER['REMOTE_ADDR'], "comment"=>$comment] + ); + $cid = $database->get_last_insert_id('comments_id_seq'); + $snippet = substr($comment, 0, 100); + $snippet = str_replace("\n", " ", $snippet); + $snippet = str_replace("\r", " ", $snippet); + log_info("comment", "Comment #$cid added to Image #$image_id: $snippet", null, ["image_id"=>$image_id, "comment_id"=>$cid]); + } - private function comment_checks(int $image_id, User $user, string $comment) { - global $config, $page; + private function comment_checks(int $image_id, User $user, string $comment) + { + global $config, $page; - // basic sanity checks - if(!$user->can("create_comment")) { - throw new CommentPostingException("Anonymous posting has been disabled"); - } - else if(is_null(Image::by_id($image_id))) { - throw new CommentPostingException("The image does not exist"); - } - else if(trim($comment) == "") { - throw new CommentPostingException("Comments need text..."); - } - else if(strlen($comment) > 9000) { - throw new CommentPostingException("Comment too long~"); - } + // basic sanity checks + if (!$user->can("create_comment")) { + throw new CommentPostingException("Anonymous posting has been disabled"); + } elseif (is_null(Image::by_id($image_id))) { + throw new CommentPostingException("The image does not exist"); + } elseif (trim($comment) == "") { + throw new CommentPostingException("Comments need text..."); + } elseif (strlen($comment) > 9000) { + throw new CommentPostingException("Comment too long~"); + } - // advanced sanity checks - else if(strlen($comment)/strlen(gzcompress($comment)) > 10) { - throw new CommentPostingException("Comment too repetitive~"); - } - else if($user->is_anonymous() && !$this->hash_match()) { - $page->add_cookie("nocache", "Anonymous Commenter", time()+60*60*24, "/"); - throw new CommentPostingException( - "Comment submission form is out of date; refresh the ". - "comment form to show you aren't a spammer~"); - } + // advanced sanity checks + elseif (strlen($comment)/strlen(gzcompress($comment)) > 10) { + throw new CommentPostingException("Comment too repetitive~"); + } elseif ($user->is_anonymous() && !$this->hash_match()) { + $page->add_cookie("nocache", "Anonymous Commenter", time()+60*60*24, "/"); + throw new CommentPostingException( + "Comment submission form is out of date; refresh the ". + "comment form to show you aren't a spammer~" + ); + } - // database-querying checks - else if($this->is_comment_limit_hit()) { - throw new CommentPostingException("You've posted several comments recently; wait a minute and try again..."); - } - else if($this->is_dupe($image_id, $comment)) { - throw new CommentPostingException("Someone already made that comment on that image -- try and be more original?"); - } + // database-querying checks + elseif ($this->is_comment_limit_hit()) { + throw new CommentPostingException("You've posted several comments recently; wait a minute and try again..."); + } elseif ($this->is_dupe($image_id, $comment)) { + throw new CommentPostingException("Someone already made that comment on that image -- try and be more original?"); + } - // rate-limited external service checks last - else if($config->get_bool('comment_captcha') && !captcha_check()) { - throw new CommentPostingException("Error in captcha"); - } - else if($user->is_anonymous() && $this->is_spam_akismet($comment)) { - throw new CommentPostingException("Akismet thinks that your comment is spam. Try rewriting the comment, or logging in."); - } - } -// }}} + // rate-limited external service checks last + elseif ($config->get_bool('comment_captcha') && !captcha_check()) { + throw new CommentPostingException("Error in captcha"); + } elseif ($user->is_anonymous() && $this->is_spam_akismet($comment)) { + throw new CommentPostingException("Akismet thinks that your comment is spam. Try rewriting the comment, or logging in."); + } + } + // }}} } - diff --git a/ext/comment/test.php b/ext/comment/test.php index 93230a71..8967a595 100644 --- a/ext/comment/test.php +++ b/ext/comment/test.php @@ -1,110 +1,111 @@ set_int("comment_limit", 100); - $this->log_out(); - } +class CommentListTest extends ShimmiePHPUnitTestCase +{ + public function setUp() + { + global $config; + parent::setUp(); + $config->set_int("comment_limit", 100); + $this->log_out(); + } - public function tearDown() { - global $config; - $config->set_int("comment_limit", 10); - parent::tearDown(); - } + public function tearDown() + { + global $config; + $config->set_int("comment_limit", 10); + parent::tearDown(); + } - public function testCommentsPage() { - global $user; + public function testCommentsPage() + { + global $user; - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - # a good comment - send_event(new CommentPostingEvent($image_id, $user, "Test Comment ASDFASDF")); - $this->get_page("post/view/$image_id"); - $this->assert_text("ASDFASDF"); + # a good comment + send_event(new CommentPostingEvent($image_id, $user, "Test Comment ASDFASDF")); + $this->get_page("post/view/$image_id"); + $this->assert_text("ASDFASDF"); - # dupe - try { - send_event(new CommentPostingEvent($image_id, $user, "Test Comment ASDFASDF")); - } - catch(CommentPostingException $e) { - $this->assertContains("try and be more original", $e->getMessage()); - } + # dupe + try { + send_event(new CommentPostingEvent($image_id, $user, "Test Comment ASDFASDF")); + } catch (CommentPostingException $e) { + $this->assertContains("try and be more original", $e->getMessage()); + } - # empty comment - try { - send_event(new CommentPostingEvent($image_id, $user, "")); - } - catch(CommentPostingException $e) { - $this->assertContains("Comments need text", $e->getMessage()); - } + # empty comment + try { + send_event(new CommentPostingEvent($image_id, $user, "")); + } catch (CommentPostingException $e) { + $this->assertContains("Comments need text", $e->getMessage()); + } - # whitespace is still empty... - try { - send_event(new CommentPostingEvent($image_id, $user, " \t\r\n")); - } - catch(CommentPostingException $e) { - $this->assertContains("Comments need text", $e->getMessage()); - } + # whitespace is still empty... + try { + send_event(new CommentPostingEvent($image_id, $user, " \t\r\n")); + } catch (CommentPostingException $e) { + $this->assertContains("Comments need text", $e->getMessage()); + } - # repetitive (aka. gzip gives >= 10x improvement) - try { - send_event(new CommentPostingEvent($image_id, $user, str_repeat("U", 5000))); - } - catch(CommentPostingException $e) { - $this->assertContains("Comment too repetitive", $e->getMessage()); - } + # repetitive (aka. gzip gives >= 10x improvement) + try { + send_event(new CommentPostingEvent($image_id, $user, str_repeat("U", 5000))); + } catch (CommentPostingException $e) { + $this->assertContains("Comment too repetitive", $e->getMessage()); + } - # test UTF8 - send_event(new CommentPostingEvent($image_id, $user, "Test Comment むちむち")); - $this->get_page("post/view/$image_id"); - $this->assert_text("むちむち"); + # test UTF8 + send_event(new CommentPostingEvent($image_id, $user, "Test Comment むちむち")); + $this->get_page("post/view/$image_id"); + $this->assert_text("むちむち"); - # test that search by comment metadata works -// $this->get_page("post/list/commented_by=test/1"); -// $this->assert_title("Image $image_id: pbx"); -// $this->get_page("post/list/comments=2/1"); -// $this->assert_title("Image $image_id: pbx"); + # test that search by comment metadata works + // $this->get_page("post/list/commented_by=test/1"); + // $this->assert_title("Image $image_id: pbx"); + // $this->get_page("post/list/comments=2/1"); + // $this->assert_title("Image $image_id: pbx"); - $this->log_out(); + $this->log_out(); - $this->get_page('comment/list'); - $this->assert_title('Comments'); - $this->assert_text('ASDFASDF'); + $this->get_page('comment/list'); + $this->assert_title('Comments'); + $this->assert_text('ASDFASDF'); - $this->get_page('comment/list/2'); - $this->assert_title('Comments'); + $this->get_page('comment/list/2'); + $this->assert_title('Comments'); - $this->log_in_as_admin(); - $this->delete_image($image_id); - $this->log_out(); + $this->log_in_as_admin(); + $this->delete_image($image_id); + $this->log_out(); - $this->get_page('comment/list'); - $this->assert_title('Comments'); - $this->assert_no_text('ASDFASDF'); - } + $this->get_page('comment/list'); + $this->assert_title('Comments'); + $this->assert_no_text('ASDFASDF'); + } - public function testSingleDel() { - $this->markTestIncomplete(); + public function testSingleDel() + { + $this->markTestIncomplete(); - $this->log_in_as_admin(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->log_in_as_admin(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - # make a comment - $this->get_page("post/view/$image_id"); - $this->set_field('comment', "Test Comment ASDFASDF"); - $this->click("Post Comment"); - $this->assert_title("Image $image_id: pbx"); - $this->assert_text("ASDFASDF"); + # make a comment + $this->get_page("post/view/$image_id"); + $this->set_field('comment', "Test Comment ASDFASDF"); + $this->click("Post Comment"); + $this->assert_title("Image $image_id: pbx"); + $this->assert_text("ASDFASDF"); - # delete it - $this->click("Del"); - $this->assert_title("Image $image_id: pbx"); - $this->assert_no_text("ASDFASDF"); + # delete it + $this->click("Del"); + $this->assert_title("Image $image_id: pbx"); + $this->assert_no_text("ASDFASDF"); - # tidy up - $this->delete_image($image_id); - $this->log_out(); - } + # tidy up + $this->delete_image($image_id); + $this->log_out(); + } } diff --git a/ext/comment/theme.php b/ext/comment/theme.php index c9d8d420..fb8532ef 100644 --- a/ext/comment/theme.php +++ b/ext/comment/theme.php @@ -1,109 +1,111 @@ ct)) { - $this->ct = hsl_rainbow(); - } - if(!array_key_exists($ip, $this->anon_map)) { - $this->anon_map[$ip] = $this->ct[$this->anon_cid++ % count($this->ct)]; - } - return $this->anon_map[$ip]; - } + private function get_anon_colour($ip) + { + if (is_null($this->ct)) { + $this->ct = hsl_rainbow(); + } + if (!array_key_exists($ip, $this->anon_map)) { + $this->anon_map[$ip] = $this->ct[$this->anon_cid++ % count($this->ct)]; + } + return $this->anon_map[$ip]; + } - /** - * Display a page with a list of images, and for each image, the image's comments. - */ - public function display_comment_list(array $images, int $page_number, int $total_pages, bool $can_post) { - global $config, $page, $user; + /** + * Display a page with a list of images, and for each image, the image's comments. + */ + public function display_comment_list(array $images, int $page_number, int $total_pages, bool $can_post) + { + global $config, $page, $user; - // aaaaaaargh php - assert(is_array($images)); - assert(is_numeric($page_number)); - assert(is_numeric($total_pages)); - assert(is_bool($can_post)); + // aaaaaaargh php + assert(is_array($images)); + assert(is_numeric($page_number)); + assert(is_numeric($total_pages)); + assert(is_bool($can_post)); - // parts for the whole page - $prev = $page_number - 1; - $next = $page_number + 1; + // parts for the whole page + $prev = $page_number - 1; + $next = $page_number + 1; - $h_prev = ($page_number <= 1) ? "Prev" : - 'Prev'; - $h_index = "Index"; - $h_next = ($page_number >= $total_pages) ? "Next" : - 'Next'; + $h_prev = ($page_number <= 1) ? "Prev" : + 'Prev'; + $h_index = "Index"; + $h_next = ($page_number >= $total_pages) ? "Next" : + 'Next'; - $nav = $h_prev.' | '.$h_index.' | '.$h_next; + $nav = $h_prev.' | '.$h_index.' | '.$h_next; - $page->set_title("Comments"); - $page->set_heading("Comments"); - $page->add_block(new Block("Navigation", $nav, "left")); - $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); + $page->set_title("Comments"); + $page->set_heading("Comments"); + $page->add_block(new Block("Navigation", $nav, "left")); + $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); - // parts for each image - $position = 10; + // parts for each image + $position = 10; - $comment_limit = $config->get_int("comment_list_count", 10); - $comment_captcha = $config->get_bool('comment_captcha'); - - foreach($images as $pair) { - $image = $pair[0]; - $comments = $pair[1]; + $comment_limit = $config->get_int("comment_list_count", 10); + $comment_captcha = $config->get_bool('comment_captcha'); + + foreach ($images as $pair) { + $image = $pair[0]; + $comments = $pair[1]; - $thumb_html = $this->build_thumb_html($image); - $comment_html = ""; - - $comment_count = count($comments); - if($comment_limit > 0 && $comment_count > $comment_limit) { - $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; - $comments = array_slice($comments, -$comment_limit); - $this->show_anon_id = false; - } - else { - $this->show_anon_id = true; - } - $this->anon_id = 1; - foreach($comments as $comment) { - $comment_html .= $this->comment_to_html($comment); - } - if(!$user->is_anonymous()) { - if($can_post) { - $comment_html .= $this->build_postbox($image->id); - } - } else { - if ($can_post) { - if(!$comment_captcha) { - $comment_html .= $this->build_postbox($image->id); - } - else { - $link = make_link("post/view/".$image->id); - $comment_html .= "Add Comment"; - } - } - } + $thumb_html = $this->build_thumb_html($image); + $comment_html = ""; + + $comment_count = count($comments); + if ($comment_limit > 0 && $comment_count > $comment_limit) { + $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; + $comments = array_slice($comments, -$comment_limit); + $this->show_anon_id = false; + } else { + $this->show_anon_id = true; + } + $this->anon_id = 1; + foreach ($comments as $comment) { + $comment_html .= $this->comment_to_html($comment); + } + if (!$user->is_anonymous()) { + if ($can_post) { + $comment_html .= $this->build_postbox($image->id); + } + } else { + if ($can_post) { + if (!$comment_captcha) { + $comment_html .= $this->build_postbox($image->id); + } else { + $link = make_link("post/view/".$image->id); + $comment_html .= "Add Comment"; + } + } + } - $html = ' + $html = '
    '.$thumb_html.' '.$comment_html.'
    '; - $page->add_block(new Block( $image->id.': '.$image->get_tag_list(), $html, "main", $position++, "comment-list-list")); - } - } + $page->add_block(new Block($image->id.': '.$image->get_tag_list(), $html, "main", $position++, "comment-list-list")); + } + } - public function display_admin_block() { - global $page; + public function display_admin_block() + { + global $page; - $html = ' + $html = ' Delete comments by IP.

    '.make_form(make_link("comment/bulk_delete"), 'POST')." @@ -113,161 +115,163 @@ class CommentListTheme extends Themelet { "; - $page->add_block(new Block("Mass Comment Delete", $html)); - } + $page->add_block(new Block("Mass Comment Delete", $html)); + } - /** - * Add some comments to the page, probably in a sidebar. - * - * #param Comment[] $comments An array of Comment objects to be shown - */ - public function display_recent_comments(array $comments) { - global $page; - $this->show_anon_id = false; - $html = ""; - foreach($comments as $comment) { - $html .= $this->comment_to_html($comment, true); - } - $html .= "Full List"; - $page->add_block(new Block("Comments", $html, "left", 50, "comment-list-recent")); - } + /** + * Add some comments to the page, probably in a sidebar. + * + * #param Comment[] $comments An array of Comment objects to be shown + */ + public function display_recent_comments(array $comments) + { + global $page; + $this->show_anon_id = false; + $html = ""; + foreach ($comments as $comment) { + $html .= $this->comment_to_html($comment, true); + } + $html .= "Full List"; + $page->add_block(new Block("Comments", $html, "left", 50, "comment-list-recent")); + } - /** - * Show comments for an image. - * - * #param Comment[] $comments - */ - public function display_image_comments(Image $image, array $comments, bool $postbox) { - global $page; - $this->show_anon_id = true; - $html = ""; - foreach($comments as $comment) { - $html .= $this->comment_to_html($comment); - } - if($postbox) { - $html .= $this->build_postbox($image->id); - } - $page->add_block(new Block("Comments", $html, "main", 30, "comment-list-image")); - } + /** + * Show comments for an image. + * + * #param Comment[] $comments + */ + public function display_image_comments(Image $image, array $comments, bool $postbox) + { + global $page; + $this->show_anon_id = true; + $html = ""; + foreach ($comments as $comment) { + $html .= $this->comment_to_html($comment); + } + if ($postbox) { + $html .= $this->build_postbox($image->id); + } + $page->add_block(new Block("Comments", $html, "main", 30, "comment-list-image")); + } - /** - * Show comments made by a user. - * - * #param Comment[] $comments - */ - public function display_recent_user_comments(array $comments, User $user) { - global $page; - $html = ""; - foreach($comments as $comment) { - $html .= $this->comment_to_html($comment, true); - } - if(empty($html)) { - $html = '

    No comments by this user.

    '; - } - else { - $html .= "

    More

    "; - } - $page->add_block(new Block("Comments", $html, "left", 70, "comment-list-user")); - } + /** + * Show comments made by a user. + * + * #param Comment[] $comments + */ + public function display_recent_user_comments(array $comments, User $user) + { + global $page; + $html = ""; + foreach ($comments as $comment) { + $html .= $this->comment_to_html($comment, true); + } + if (empty($html)) { + $html = '

    No comments by this user.

    '; + } else { + $html .= "

    More

    "; + } + $page->add_block(new Block("Comments", $html, "left", 70, "comment-list-user")); + } - public function display_all_user_comments(array $comments, int $page_number, int $total_pages, User $user) { - global $page; - - assert(is_numeric($page_number)); - assert(is_numeric($total_pages)); - - $html = ""; - foreach($comments as $comment) { - $html .= $this->comment_to_html($comment, true); - } - if(empty($html)) { - $html = '

    No comments by this user.

    '; - } - $page->add_block(new Block("Comments", $html, "main", 70, "comment-list-user")); + public function display_all_user_comments(array $comments, int $page_number, int $total_pages, User $user) + { + global $page; + + assert(is_numeric($page_number)); + assert(is_numeric($total_pages)); + + $html = ""; + foreach ($comments as $comment) { + $html .= $this->comment_to_html($comment, true); + } + if (empty($html)) { + $html = '

    No comments by this user.

    '; + } + $page->add_block(new Block("Comments", $html, "main", 70, "comment-list-user")); - $prev = $page_number - 1; - $next = $page_number + 1; - - //$search_terms = array('I','have','no','idea','what','this','does!'); - //$u_tags = url_escape(Tag::implode($search_terms)); - //$query = empty($u_tags) ? "" : '/'.$u_tags; + $prev = $page_number - 1; + $next = $page_number + 1; + + //$search_terms = array('I','have','no','idea','what','this','does!'); + //$u_tags = url_escape(Tag::implode($search_terms)); + //$query = empty($u_tags) ? "" : '/'.$u_tags; - $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; - $h_index = "Index"; - $h_next = ($page_number >= $total_pages) ? "Next" : "Next"; + $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; + $h_index = "Index"; + $h_next = ($page_number >= $total_pages) ? "Next" : "Next"; - $page->set_title(html_escape($user->name)."'s comments"); - $page->add_block(new Block("Navigation", $h_prev.' | '.$h_index.' | '.$h_next, "left", 0)); - $this->display_paginator($page, "comment/beta-search/{$user->name}", null, $page_number, $total_pages); - } + $page->set_title(html_escape($user->name)."'s comments"); + $page->add_block(new Block("Navigation", $h_prev.' | '.$h_index.' | '.$h_next, "left", 0)); + $this->display_paginator($page, "comment/beta-search/{$user->name}", null, $page_number, $total_pages); + } - protected function comment_to_html(Comment $comment, bool $trim=false): string { - global $config, $user; + protected function comment_to_html(Comment $comment, bool $trim=false): string + { + global $config, $user; - $tfe = new TextFormattingEvent($comment->comment); - send_event($tfe); + $tfe = new TextFormattingEvent($comment->comment); + send_event($tfe); - $i_uid = int_escape($comment->owner_id); - $h_name = html_escape($comment->owner_name); - $h_timestamp = autodate($comment->posted); - $h_comment = ($trim ? truncate($tfe->stripped, 50) : $tfe->formatted); - $i_comment_id = int_escape($comment->comment_id); - $i_image_id = int_escape($comment->image_id); + $i_uid = int_escape($comment->owner_id); + $h_name = html_escape($comment->owner_name); + $h_timestamp = autodate($comment->posted); + $h_comment = ($trim ? truncate($tfe->stripped, 50) : $tfe->formatted); + $i_comment_id = int_escape($comment->comment_id); + $i_image_id = int_escape($comment->image_id); - if($i_uid == $config->get_int("anon_id")) { - $anoncode = ""; - $anoncode2 = ""; - if($this->show_anon_id) { - $anoncode = ''.$this->anon_id.''; - if(!array_key_exists($comment->poster_ip, $this->anon_map)) { - $this->anon_map[$comment->poster_ip] = $this->anon_id; - } - #if($user->can("view_ip")) { - #$style = " style='color: ".$this->get_anon_colour($comment->poster_ip).";'"; - if($user->can("view_ip") || $config->get_bool("comment_samefags_public", false)) { - if($this->anon_map[$comment->poster_ip] != $this->anon_id) { - $anoncode2 = '('.$this->anon_map[$comment->poster_ip].')'; - } - } - } - $h_userlink = "" . $h_name . $anoncode . $anoncode2 . ""; - $this->anon_id++; - } - else { - $h_userlink = ''.$h_name.''; - } + if ($i_uid == $config->get_int("anon_id")) { + $anoncode = ""; + $anoncode2 = ""; + if ($this->show_anon_id) { + $anoncode = ''.$this->anon_id.''; + if (!array_key_exists($comment->poster_ip, $this->anon_map)) { + $this->anon_map[$comment->poster_ip] = $this->anon_id; + } + #if($user->can("view_ip")) { + #$style = " style='color: ".$this->get_anon_colour($comment->poster_ip).";'"; + if ($user->can("view_ip") || $config->get_bool("comment_samefags_public", false)) { + if ($this->anon_map[$comment->poster_ip] != $this->anon_id) { + $anoncode2 = '('.$this->anon_map[$comment->poster_ip].')'; + } + } + } + $h_userlink = "" . $h_name . $anoncode . $anoncode2 . ""; + $this->anon_id++; + } else { + $h_userlink = ''.$h_name.''; + } - $hb = ($comment->owner_class == "hellbanned" ? "hb" : ""); - if($trim) { - $html = " + $hb = ($comment->owner_class == "hellbanned" ? "hb" : ""); + if ($trim) { + $html = "
    $h_userlink: $h_comment >>>
    "; - } - else { - $h_avatar = ""; - if(!empty($comment->owner_email)) { - $hash = md5(strtolower($comment->owner_email)); - $cb = date("Y-m-d"); - $h_avatar = "
    "; - } - $h_reply = " - Reply"; - $h_ip = $user->can("view_ip") ? "
    ".show_ip($comment->poster_ip, "Comment posted {$comment->posted}") : ""; - $h_del = ""; - if ($user->can("delete_comment")) { - $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); - $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); - $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); - $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); - $h_del = " - Del"; - } - $html = " + } else { + $h_avatar = ""; + if (!empty($comment->owner_email)) { + $hash = md5(strtolower($comment->owner_email)); + $cb = date("Y-m-d"); + $h_avatar = "
    "; + } + $h_reply = " - Reply"; + $h_ip = $user->can("view_ip") ? "
    ".show_ip($comment->poster_ip, "Comment posted {$comment->posted}") : ""; + $h_del = ""; + if ($user->can("delete_comment")) { + $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); + $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); + $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); + $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); + $h_del = " - Del"; + } + $html = "
    $h_avatar @@ -276,18 +280,19 @@ class CommentListTheme extends Themelet { $h_userlink: $h_comment
    "; - } - return $html; - } + } + return $html; + } - protected function build_postbox(int $image_id): string { - global $config; + protected function build_postbox(int $image_id): string + { + global $config; - $i_image_id = int_escape($image_id); - $hash = CommentList::get_hash(); - $h_captcha = $config->get_bool("comment_captcha") ? captcha_get_html() : ""; + $i_image_id = int_escape($image_id); + $hash = CommentList::get_hash(); + $h_captcha = $config->get_bool("comment_captcha") ? captcha_get_html() : ""; - return ' + return '
    '.make_form(make_link("comment/add")).' @@ -298,6 +303,5 @@ class CommentListTheme extends Themelet {
    '; - } + } } - diff --git a/ext/cron_uploader/main.php b/ext/cron_uploader/main.php index 15df4693..1af4a68b 100644 --- a/ext/cron_uploader/main.php +++ b/ext/cron_uploader/main.php @@ -7,76 +7,77 @@ * Description: Uploads images automatically using Cron Jobs * Documentation: Installation guide: activate this extension and navigate to www.yoursite.com/cron_upload */ -class CronUploader extends Extension { - // TODO: Checkbox option to only allow localhost + a list of additional IP adresses that can be set in /cron_upload - // TODO: Change logging to MySQL + display log at /cron_upload - // TODO: Move stuff to theme.php - - /** - * Lists all log events this session - * @var string - */ - private $upload_info = ""; - - /** - * Lists all files & info required to upload. - * @var array - */ - private $image_queue = array(); - - /** - * Cron Uploader root directory - * @var string - */ - private $root_dir = ""; - - /** - * Key used to identify uploader - * @var string - */ - private $upload_key = ""; - - /** - * Checks if the cron upload page has been accessed - * and initializes the upload. - */ - public function onPageRequest(PageRequestEvent $event) { - global $config, $user; - - if ($event->page_matches ( "cron_upload" )) { - $this->upload_key = $config->get_string ( "cron_uploader_key", "" ); - - // If the key is in the url, upload - if ($this->upload_key != "" && $event->get_arg ( 0 ) == $this->upload_key) { - // log in as admin - $this->process_upload(); // Start upload - } - else if ($user->is_admin()) { - $this->set_dir(); - $this->display_documentation(); - } - - } - } - - private function display_documentation() { - global $page; - $this->set_dir(); // Determines path to cron_uploader_dir - - - $queue_dir = $this->root_dir . "/queue"; - $uploaded_dir = $this->root_dir . "/uploaded"; - $failed_dir = $this->root_dir . "/failed_to_upload"; - - $queue_dirinfo = $this->scan_dir($queue_dir); - $uploaded_dirinfo = $this->scan_dir($uploaded_dir); - $failed_dirinfo = $this->scan_dir($failed_dir); - - $cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); - $cron_cmd = "curl --silent $cron_url"; - $log_path = $this->root_dir . "/uploads.log"; - - $info_html = "Information +class CronUploader extends Extension +{ + // TODO: Checkbox option to only allow localhost + a list of additional IP adresses that can be set in /cron_upload + // TODO: Change logging to MySQL + display log at /cron_upload + // TODO: Move stuff to theme.php + + /** + * Lists all log events this session + * @var string + */ + private $upload_info = ""; + + /** + * Lists all files & info required to upload. + * @var array + */ + private $image_queue = []; + + /** + * Cron Uploader root directory + * @var string + */ + private $root_dir = ""; + + /** + * Key used to identify uploader + * @var string + */ + private $upload_key = ""; + + /** + * Checks if the cron upload page has been accessed + * and initializes the upload. + */ + public function onPageRequest(PageRequestEvent $event) + { + global $config, $user; + + if ($event->page_matches("cron_upload")) { + $this->upload_key = $config->get_string("cron_uploader_key", ""); + + // If the key is in the url, upload + if ($this->upload_key != "" && $event->get_arg(0) == $this->upload_key) { + // log in as admin + $this->process_upload(); // Start upload + } elseif ($user->is_admin()) { + $this->set_dir(); + $this->display_documentation(); + } + } + } + + private function display_documentation() + { + global $page; + $this->set_dir(); // Determines path to cron_uploader_dir + + + $queue_dir = $this->root_dir . "/queue"; + $uploaded_dir = $this->root_dir . "/uploaded"; + $failed_dir = $this->root_dir . "/failed_to_upload"; + + $queue_dirinfo = $this->scan_dir($queue_dir); + $uploaded_dirinfo = $this->scan_dir($uploaded_dir); + $failed_dirinfo = $this->scan_dir($failed_dir); + + $cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); + $cron_cmd = "curl --silent $cron_url"; + $log_path = $this->root_dir . "/uploads.log"; + + $info_html = "Information
    @@ -104,8 +105,8 @@ class CronUploader extends Extension {
    Cron Command:
    Create a cron job with the command above.
    Read the documentation if you're not sure what to do.
    "; - - $install_html = " + + $install_html = " This cron uploader is fairly easy to use but has to be configured first.
    1. Install & activate this plugin.
    @@ -129,289 +130,308 @@ class CronUploader extends Extension {
    So when you want to manually upload an image, all you have to do is open the link once.
    This link can be found under 'Cron Command' in the board config, just remove the 'wget ' part and only the url remains.
    ($cron_url)"; - - - $block = new Block("Cron Uploader", $info_html, "main", 10); - $block_install = new Block("Installation Guide", $install_html, "main", 20); - $page->add_block($block); - $page->add_block($block_install); - } + + + $block = new Block("Cron Uploader", $info_html, "main", 10); + $block_install = new Block("Installation Guide", $install_html, "main", 20); + $page->add_block($block); + $page->add_block($block_install); + } - public function onInitExt(InitExtEvent $event) { - global $config; - // Set default values - if ($config->get_string("cron_uploader_key", "")) { - $this->upload_key = $this->generate_key (); - - $config->set_default_int ( 'cron_uploader_count', 1 ); - $config->set_default_string ( 'cron_uploader_key', $this->upload_key ); - $this->set_dir(); - } - } - - public function onSetupBuilding(SetupBuildingEvent $event) { - $this->set_dir(); - - $cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); - $cron_cmd = "curl --silent $cron_url"; - $documentation_link = make_http(make_link("cron_upload")); - - $sb = new SetupBlock ( "Cron Uploader" ); - $sb->add_label ( "Settings
    " ); - $sb->add_int_option ( "cron_uploader_count", "How many to upload each time" ); - $sb->add_text_option ( "cron_uploader_dir", "
    Set Cron Uploader root directory
    "); - - $sb->add_label ("
    Cron Command:
    + public function onInitExt(InitExtEvent $event) + { + global $config; + // Set default values + if ($config->get_string("cron_uploader_key", "")) { + $this->upload_key = $this->generate_key(); + + $config->set_default_int('cron_uploader_count', 1); + $config->set_default_string('cron_uploader_key', $this->upload_key); + $this->set_dir(); + } + } + + public function onSetupBuilding(SetupBuildingEvent $event) + { + $this->set_dir(); + + $cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); + $cron_cmd = "curl --silent $cron_url"; + $documentation_link = make_http(make_link("cron_upload")); + + $sb = new SetupBlock("Cron Uploader"); + $sb->add_label("Settings
    "); + $sb->add_int_option("cron_uploader_count", "How many to upload each time"); + $sb->add_text_option("cron_uploader_dir", "
    Set Cron Uploader root directory
    "); + + $sb->add_label("
    Cron Command:
    Create a cron job with the command above.
    Read the documentation if you're not sure what to do."); - $event->panel->add_block ( $sb ); - } - - /* - * Generates a unique key for the website to prevent unauthorized access. - */ - private function generate_key() { - $length = 20; - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $randomString = ''; - - for($i = 0; $i < $length; $i ++) { - $randomString .= $characters [rand ( 0, strlen ( $characters ) - 1 )]; - } - - return $randomString; - } - - /* - * Set the directory for the image queue. If no directory was given, set it to the default directory. - */ - private function set_dir() { - global $config; - // Determine directory (none = default) - - $dir = $config->get_string("cron_uploader_dir", ""); - - // Sets new default dir if not in config yet/anymore - if ($dir == "") { - $dir = data_path("cron_uploader"); - $config->set_string ('cron_uploader_dir', $dir); - } - - // Make the directory if it doesn't exist yet - if (!is_dir($dir . "/queue/")) - mkdir ( $dir . "/queue/", 0775, true ); - if (!is_dir($dir . "/uploaded/")) - mkdir ( $dir . "/uploaded/", 0775, true ); - if (!is_dir($dir . "/failed_to_upload/")) - mkdir ( $dir . "/failed_to_upload/", 0775, true ); - - $this->root_dir = $dir; - return $dir; - } - - /** - * Returns amount of files & total size of dir. - */ - function scan_dir(string $path): array{ - $ite=new RecursiveDirectoryIterator($path); - - $bytestotal=0; - $nbfiles=0; - foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) { - $filesize = $cur->getSize(); - $bytestotal += $filesize; - $nbfiles++; - } - - $size_mb = $bytestotal / 1048576; // to mb - $size_mb = number_format($size_mb, 2, '.', ''); - return array('total_files'=>$nbfiles,'total_mb'=>$size_mb); - } - - /** - * Uploads the image & handles everything - */ - public function process_upload(int $upload_count = 0): bool { - global $config; - set_time_limit(0); - $this->set_dir(); - $this->generate_image_queue(); - - // Gets amount of imgs to upload - if ($upload_count == 0) $upload_count = $config->get_int ("cron_uploader_count", 1); - - // Throw exception if there's nothing in the queue - if (count($this->image_queue) == 0) { - $this->add_upload_info("Your queue is empty so nothing could be uploaded."); - $this->handle_log(); - return false; - } - - // Randomize Images - shuffle($this->image_queue); + $event->panel->add_block($sb); + } + + /* + * Generates a unique key for the website to prevent unauthorized access. + */ + private function generate_key() + { + $length = 20; + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $randomString = ''; + + for ($i = 0; $i < $length; $i ++) { + $randomString .= $characters [rand(0, strlen($characters) - 1)]; + } + + return $randomString; + } + + /* + * Set the directory for the image queue. If no directory was given, set it to the default directory. + */ + private function set_dir() + { + global $config; + // Determine directory (none = default) + + $dir = $config->get_string("cron_uploader_dir", ""); + + // Sets new default dir if not in config yet/anymore + if ($dir == "") { + $dir = data_path("cron_uploader"); + $config->set_string('cron_uploader_dir', $dir); + } + + // Make the directory if it doesn't exist yet + if (!is_dir($dir . "/queue/")) { + mkdir($dir . "/queue/", 0775, true); + } + if (!is_dir($dir . "/uploaded/")) { + mkdir($dir . "/uploaded/", 0775, true); + } + if (!is_dir($dir . "/failed_to_upload/")) { + mkdir($dir . "/failed_to_upload/", 0775, true); + } + + $this->root_dir = $dir; + return $dir; + } + + /** + * Returns amount of files & total size of dir. + */ + public function scan_dir(string $path): array + { + $ite=new RecursiveDirectoryIterator($path); + + $bytestotal=0; + $nbfiles=0; + foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) { + $filesize = $cur->getSize(); + $bytestotal += $filesize; + $nbfiles++; + } + + $size_mb = $bytestotal / 1048576; // to mb + $size_mb = number_format($size_mb, 2, '.', ''); + return ['total_files'=>$nbfiles,'total_mb'=>$size_mb]; + } + + /** + * Uploads the image & handles everything + */ + public function process_upload(int $upload_count = 0): bool + { + global $config; + set_time_limit(0); + $this->set_dir(); + $this->generate_image_queue(); + + // Gets amount of imgs to upload + if ($upload_count == 0) { + $upload_count = $config->get_int("cron_uploader_count", 1); + } + + // Throw exception if there's nothing in the queue + if (count($this->image_queue) == 0) { + $this->add_upload_info("Your queue is empty so nothing could be uploaded."); + $this->handle_log(); + return false; + } + + // Randomize Images + shuffle($this->image_queue); - // Upload the file(s) - for ($i = 0; $i < $upload_count; $i++) { - $img = $this->image_queue[$i]; - - try { - $this->add_image($img[0], $img[1], $img[2]); - $this->move_uploaded($img[0], $img[1], false); - - } - catch (Exception $e) { - $this->move_uploaded($img[0], $img[1], true); - } - - // Remove img from queue array - unset($this->image_queue[$i]); - } - - // Display & save upload log - $this->handle_log(); - - return true; - } - - private function move_uploaded($path, $filename, $corrupt = false) { - global $config; - - // Create - $newDir = $this->root_dir; - - // Determine which dir to move to - if ($corrupt) { - // Move to corrupt dir - $newDir .= "/failed_to_upload/"; - $info = "ERROR: Image was not uploaded."; - } - else { - $newDir .= "/uploaded/"; - $info = "Image successfully uploaded. "; - } - - // move file to correct dir - rename($path, $newDir.$filename); - - $this->add_upload_info($info . "Image \"$filename\" moved from queue to \"$newDir\"."); - } + // Upload the file(s) + for ($i = 0; $i < $upload_count; $i++) { + $img = $this->image_queue[$i]; + + try { + $this->add_image($img[0], $img[1], $img[2]); + $this->move_uploaded($img[0], $img[1], false); + } catch (Exception $e) { + $this->move_uploaded($img[0], $img[1], true); + } + + // Remove img from queue array + unset($this->image_queue[$i]); + } + + // Display & save upload log + $this->handle_log(); + + return true; + } + + private function move_uploaded($path, $filename, $corrupt = false) + { + global $config; + + // Create + $newDir = $this->root_dir; + + // Determine which dir to move to + if ($corrupt) { + // Move to corrupt dir + $newDir .= "/failed_to_upload/"; + $info = "ERROR: Image was not uploaded."; + } else { + $newDir .= "/uploaded/"; + $info = "Image successfully uploaded. "; + } + + // move file to correct dir + rename($path, $newDir.$filename); + + $this->add_upload_info($info . "Image \"$filename\" moved from queue to \"$newDir\"."); + } - /** - * Generate the necessary DataUploadEvent for a given image and tags. - */ - private function add_image(string $tmpname, string $filename, string $tags) { - assert ( file_exists ( $tmpname ) ); - - $pathinfo = pathinfo ( $filename ); - if (! array_key_exists ( 'extension', $pathinfo )) { - throw new UploadException ( "File has no extension" ); - } - $metadata = array(); - $metadata ['filename'] = $pathinfo ['basename']; - $metadata ['extension'] = $pathinfo ['extension']; - $metadata ['tags'] = array(); // = $tags; doesn't work when not logged in here - $metadata ['source'] = null; - $event = new DataUploadEvent ( $tmpname, $metadata ); - send_event ( $event ); - - // Generate info message - $infomsg = ""; // Will contain info message - if ($event->image_id == -1) - $infomsg = "File type not recognised. Filename: {$filename}"; - else $infomsg = "Image uploaded. ID: {$event->image_id} - Filename: {$filename} - Tags: {$tags}"; - $msgNumber = $this->add_upload_info($infomsg); - - // Set tags - $img = Image::by_id($event->image_id); - $img->set_tags(Tag::explode($tags)); - } - - private function generate_image_queue($base = "", $subdir = "") { - if ($base == "") - $base = $this->root_dir . "/queue"; - - if (! is_dir ( $base )) { - $this->add_upload_info("Image Queue Directory could not be found at \"$base\"."); - return array(); - } - - foreach ( glob ( "$base/$subdir/*" ) as $fullpath ) { - $fullpath = str_replace ( "//", "/", $fullpath ); - //$shortpath = str_replace ( $base, "", $fullpath ); - - if (is_link ( $fullpath )) { - // ignore - } else if (is_dir ( $fullpath )) { - $this->generate_image_queue ( $base, str_replace ( $base, "", $fullpath ) ); - } else { - $pathinfo = pathinfo ( $fullpath ); - $matches = array (); - - if (preg_match ( "/\d+ - (.*)\.([a-zA-Z]+)/", $pathinfo ["basename"], $matches )) { - $tags = $matches [1]; - } else { - $tags = $subdir; - $tags = str_replace ( "/", " ", $tags ); - $tags = str_replace ( "__", " ", $tags ); - if ($tags == "") $tags = " "; - $tags = trim ( $tags ); - } - - $img = array ( - 0 => $fullpath, - 1 => $pathinfo ["basename"], - 2 => $tags - ); - array_push ($this->image_queue, $img ); - } - } - } - - /** - * Adds a message to the info being published at the end - */ - private function add_upload_info(string $text, int $addon = 0): int { - $info = $this->upload_info; - $time = "[" .date('Y-m-d H:i:s'). "]"; - - // If addon function is not used - if ($addon == 0) { - $this->upload_info .= "$time $text\r\n"; - - // Returns the number of the current line - $currentLine = substr_count($this->upload_info, "\n") -1; - return $currentLine; - } - - // else if addon function is used, select the line & modify it - $lines = substr($info, "\n"); // Seperate the string to array in lines - $lines[$addon] = "$lines[$addon] $text"; // Add the content to the line - $this->upload_info = implode("\n", $lines); // Put string back together & update - - return $addon; // Return line number - } - - /** - * This is run at the end to display & save the log. - */ - private function handle_log() { - global $page; - - // Display message - $page->set_mode("data"); - $page->set_type("text/plain"); - $page->set_data($this->upload_info); - - // Save log - $log_path = $this->root_dir . "/uploads.log"; - - if (file_exists($log_path)) - $prev_content = file_get_contents($log_path); - else $prev_content = ""; - - $content = $prev_content ."\r\n".$this->upload_info; - file_put_contents ($log_path, $content); - } + /** + * Generate the necessary DataUploadEvent for a given image and tags. + */ + private function add_image(string $tmpname, string $filename, string $tags) + { + assert(file_exists($tmpname)); + + $pathinfo = pathinfo($filename); + if (! array_key_exists('extension', $pathinfo)) { + throw new UploadException("File has no extension"); + } + $metadata = []; + $metadata ['filename'] = $pathinfo ['basename']; + $metadata ['extension'] = $pathinfo ['extension']; + $metadata ['tags'] = []; // = $tags; doesn't work when not logged in here + $metadata ['source'] = null; + $event = new DataUploadEvent($tmpname, $metadata); + send_event($event); + + // Generate info message + $infomsg = ""; // Will contain info message + if ($event->image_id == -1) { + $infomsg = "File type not recognised. Filename: {$filename}"; + } else { + $infomsg = "Image uploaded. ID: {$event->image_id} - Filename: {$filename} - Tags: {$tags}"; + } + $msgNumber = $this->add_upload_info($infomsg); + + // Set tags + $img = Image::by_id($event->image_id); + $img->set_tags(Tag::explode($tags)); + } + + private function generate_image_queue($base = "", $subdir = "") + { + if ($base == "") { + $base = $this->root_dir . "/queue"; + } + + if (! is_dir($base)) { + $this->add_upload_info("Image Queue Directory could not be found at \"$base\"."); + return []; + } + + foreach (glob("$base/$subdir/*") as $fullpath) { + $fullpath = str_replace("//", "/", $fullpath); + //$shortpath = str_replace ( $base, "", $fullpath ); + + if (is_link($fullpath)) { + // ignore + } elseif (is_dir($fullpath)) { + $this->generate_image_queue($base, str_replace($base, "", $fullpath)); + } else { + $pathinfo = pathinfo($fullpath); + $matches = []; + + if (preg_match("/\d+ - (.*)\.([a-zA-Z]+)/", $pathinfo ["basename"], $matches)) { + $tags = $matches [1]; + } else { + $tags = $subdir; + $tags = str_replace("/", " ", $tags); + $tags = str_replace("__", " ", $tags); + if ($tags == "") { + $tags = " "; + } + $tags = trim($tags); + } + + $img = [ + 0 => $fullpath, + 1 => $pathinfo ["basename"], + 2 => $tags + ]; + array_push($this->image_queue, $img); + } + } + } + + /** + * Adds a message to the info being published at the end + */ + private function add_upload_info(string $text, int $addon = 0): int + { + $info = $this->upload_info; + $time = "[" .date('Y-m-d H:i:s'). "]"; + + // If addon function is not used + if ($addon == 0) { + $this->upload_info .= "$time $text\r\n"; + + // Returns the number of the current line + $currentLine = substr_count($this->upload_info, "\n") -1; + return $currentLine; + } + + // else if addon function is used, select the line & modify it + $lines = substr($info, "\n"); // Seperate the string to array in lines + $lines[$addon] = "$lines[$addon] $text"; // Add the content to the line + $this->upload_info = implode("\n", $lines); // Put string back together & update + + return $addon; // Return line number + } + + /** + * This is run at the end to display & save the log. + */ + private function handle_log() + { + global $page; + + // Display message + $page->set_mode("data"); + $page->set_type("text/plain"); + $page->set_data($this->upload_info); + + // Save log + $log_path = $this->root_dir . "/uploads.log"; + + if (file_exists($log_path)) { + $prev_content = file_get_contents($log_path); + } else { + $prev_content = ""; + } + + $content = $prev_content ."\r\n".$this->upload_info; + file_put_contents($log_path, $content); + } } - diff --git a/ext/custom_html_headers/main.php b/ext/custom_html_headers/main.php index df04b436..3125f3b1 100644 --- a/ext/custom_html_headers/main.php +++ b/ext/custom_html_headers/main.php @@ -8,65 +8,75 @@ * Documentation: * When you go to board config you can find a block named Custom HTML Headers. * In that block you can simply place any thing you can place within <head></head> - * + * * This can be useful if you want to add website tracking code or other javascript. - * NOTE: Only use if you know what you're doing. - * + * NOTE: Only use if you know what you're doing. + * * You can also add your website name as prefix or suffix to the title of each page on your website. */ -class custom_html_headers extends Extension { +class custom_html_headers extends Extension +{ # Adds setup block for custom content - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Custom HTML Headers"); + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Custom HTML Headers"); - // custom headers - $sb->add_longtext_option("custom_html_headers", - "HTML Code to place within <head></head> on all pages
    "); + // custom headers + $sb->add_longtext_option( + "custom_html_headers", + "HTML Code to place within <head></head> on all pages
    " + ); - // modified title - $sb->add_choice_option("sitename_in_title", array( - "none" => 0, - "as prefix" => 1, - "as suffix" => 2 - ), "
    Add website name in title"); + // modified title + $sb->add_choice_option("sitename_in_title", [ + "none" => 0, + "as prefix" => 1, + "as suffix" => 2 + ], "
    Add website name in title"); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int("sitename_in_title", 0); - } + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int("sitename_in_title", 0); + } - # Load Analytics tracking code on page request - public function onPageRequest(PageRequestEvent $event) { - $this->handle_custom_html_headers(); - $this->handle_modified_page_title(); - } + # Load Analytics tracking code on page request + public function onPageRequest(PageRequestEvent $event) + { + $this->handle_custom_html_headers(); + $this->handle_modified_page_title(); + } - private function handle_custom_html_headers() { - global $config, $page; + private function handle_custom_html_headers() + { + global $config, $page; - $header = $config->get_string('custom_html_headers',''); - if ($header!='') $page->add_html_header($header); + $header = $config->get_string('custom_html_headers', ''); + if ($header!='') { + $page->add_html_header($header); } + } - private function handle_modified_page_title() { - global $config, $page; + private function handle_modified_page_title() + { + global $config, $page; - // get config values - $site_title = $config->get_string("title"); - $sitename_in_title = $config->get_int("sitename_in_title"); + // get config values + $site_title = $config->get_string("title"); + $sitename_in_title = $config->get_int("sitename_in_title"); - // if feature is enabled & sitename isn't already in title - // (can occur on index & other pages) - if ($sitename_in_title != 0 && !strstr($page->title, $site_title)) - { - if ($sitename_in_title == 1) - $page->title = "$site_title - $page->title"; // as prefix - else if ($sitename_in_title == 2) - $page->title = "$page->title - $site_title"; // as suffix - } + // if feature is enabled & sitename isn't already in title + // (can occur on index & other pages) + if ($sitename_in_title != 0 && !strstr($page->title, $site_title)) { + if ($sitename_in_title == 1) { + $page->title = "$site_title - $page->title"; + } // as prefix + elseif ($sitename_in_title == 2) { + $page->title = "$page->title - $site_title"; + } // as suffix } + } } - diff --git a/ext/danbooru_api/main.php b/ext/danbooru_api/main.php index cc6e416f..7ee0579c 100644 --- a/ext/danbooru_api/main.php +++ b/ext/danbooru_api/main.php @@ -47,222 +47,222 @@ Completely compatibility will probably involve a rewrite with a different URL */ -class DanbooruApi extends Extension { - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("api") && ($event->get_arg(0) == 'danbooru')) { - $this->api_danbooru($event); - } - } +class DanbooruApi extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("api") && ($event->get_arg(0) == 'danbooru')) { + $this->api_danbooru($event); + } + } - // Danbooru API - private function api_danbooru(PageRequestEvent $event) { - global $page; - $page->set_mode("data"); + // Danbooru API + private function api_danbooru(PageRequestEvent $event) + { + global $page; + $page->set_mode("data"); - if(($event->get_arg(1) == 'add_post') || (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'create.xml'))) { - // No XML data is returned from this function - $page->set_type("text/plain"); - $this->api_add_post(); - } + if (($event->get_arg(1) == 'add_post') || (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'create.xml'))) { + // No XML data is returned from this function + $page->set_type("text/plain"); + $this->api_add_post(); + } elseif (($event->get_arg(1) == 'find_posts') || (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'index.xml'))) { + $page->set_type("application/xml"); + $page->set_data($this->api_find_posts()); + } elseif ($event->get_arg(1) == 'find_tags') { + $page->set_type("application/xml"); + $page->set_data($this->api_find_tags()); + } - elseif(($event->get_arg(1) == 'find_posts') || (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'index.xml'))) { - $page->set_type("application/xml"); - $page->set_data($this->api_find_posts()); - } + // Hackery for danbooruup 0.3.2 providing the wrong view url. This simply redirects to the proper + // Shimmie view page + // Example: danbooruup says the url is http://shimmie/api/danbooru/post/show/123 + // This redirects that to http://shimmie/post/view/123 + elseif (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'show')) { + $fixedlocation = make_link("post/view/" . $event->get_arg(3)); + $page->set_mode("redirect"); + $page->set_redirect($fixedlocation); + } + } - elseif($event->get_arg(1) == 'find_tags') { - $page->set_type("application/xml"); - $page->set_data($this->api_find_tags()); - } + /** + * Turns out I use this a couple times so let's make it a utility function + * Authenticates a user based on the contents of the login and password parameters + * or makes them anonymous. Does not set any cookies or anything permanent. + */ + private function authenticate_user() + { + global $config, $user; - // Hackery for danbooruup 0.3.2 providing the wrong view url. This simply redirects to the proper - // Shimmie view page - // Example: danbooruup says the url is http://shimmie/api/danbooru/post/show/123 - // This redirects that to http://shimmie/post/view/123 - elseif(($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'show')) { - $fixedlocation = make_link("post/view/" . $event->get_arg(3)); - $page->set_mode("redirect"); - $page->set_redirect($fixedlocation); - } - } + if (isset($_REQUEST['login']) && isset($_REQUEST['password'])) { + // Get this user from the db, if it fails the user becomes anonymous + // Code borrowed from /ext/user + $name = $_REQUEST['login']; + $pass = $_REQUEST['password']; + $duser = User::by_name_and_pass($name, $pass); + if (!is_null($duser)) { + $user = $duser; + } else { + $user = User::by_id($config->get_int("anon_id", 0)); + } + } + } - /** - * Turns out I use this a couple times so let's make it a utility function - * Authenticates a user based on the contents of the login and password parameters - * or makes them anonymous. Does not set any cookies or anything permanent. - */ - private function authenticate_user() { - global $config, $user; - - if(isset($_REQUEST['login']) && isset($_REQUEST['password'])) { - // Get this user from the db, if it fails the user becomes anonymous - // Code borrowed from /ext/user - $name = $_REQUEST['login']; - $pass = $_REQUEST['password']; - $duser = User::by_name_and_pass($name, $pass); - if(!is_null($duser)) { - $user = $duser; - } - else { - $user = User::by_id($config->get_int("anon_id", 0)); - } - } - } - - /** + /** * find_tags() - * Find all tags that match the search criteria. - * + * Find all tags that match the search criteria. + * * Parameters * - id: A comma delimited list of tag id numbers. * - name: A comma delimited list of tag names. * - tags: any typical tag query. See Tag#parse_query for details. * - after_id: limit results to tags with an id number after after_id. Useful if you only want to refresh - * - * #return string - */ - private function api_find_tags() { - global $database; - $results = array(); - if(isset($_GET['id'])) { - $idlist = explode(",", $_GET['id']); - foreach ($idlist as $id) { - $sqlresult = $database->get_all( - "SELECT id,tag,count FROM tags WHERE id = ?", - array($id)); - foreach ($sqlresult as $row) { - $results[] = array($row['count'], $row['tag'], $row['id']); - } - } - } - elseif(isset($_GET['name'])) { - $namelist = explode(",", $_GET['name']); - foreach ($namelist as $name) { - $sqlresult = $database->get_all( - "SELECT id,tag,count FROM tags WHERE tag = ?", - array($name)); - foreach ($sqlresult as $row) { - $results[] = array($row['count'], $row['tag'], $row['id']); - } - } - } - // Currently disabled to maintain identical functionality to danbooru 1.0's own "broken" find_tags - elseif(false && isset($_GET['tags'])) { - $start = isset($_GET['after_id']) ? int_escape($_GET['offset']) : 0; - $tags = Tag::explode($_GET['tags']); - } - else { - $start = isset($_GET['after_id']) ? int_escape($_GET['offset']) : 0; - $sqlresult = $database->get_all( - "SELECT id,tag,count FROM tags WHERE count > 0 AND id >= ? ORDER BY id DESC", - array($start)); - foreach ($sqlresult as $row) { - $results[] = array($row['count'], $row['tag'], $row['id']); - } - } + */ + private function api_find_tags(): string + { + global $database; + $results = []; + if (isset($_GET['id'])) { + $idlist = explode(",", $_GET['id']); + foreach ($idlist as $id) { + $sqlresult = $database->get_all( + "SELECT id,tag,count FROM tags WHERE id = ?", + [$id] + ); + foreach ($sqlresult as $row) { + $results[] = [$row['count'], $row['tag'], $row['id']]; + } + } + } elseif (isset($_GET['name'])) { + $namelist = explode(",", $_GET['name']); + foreach ($namelist as $name) { + $sqlresult = $database->get_all( + "SELECT id,tag,count FROM tags WHERE tag = ?", + [$name] + ); + foreach ($sqlresult as $row) { + $results[] = [$row['count'], $row['tag'], $row['id']]; + } + } + } + // Currently disabled to maintain identical functionality to danbooru 1.0's own "broken" find_tags + elseif (false && isset($_GET['tags'])) { + $start = isset($_GET['after_id']) ? int_escape($_GET['offset']) : 0; + $tags = Tag::explode($_GET['tags']); + } else { + $start = isset($_GET['after_id']) ? int_escape($_GET['offset']) : 0; + $sqlresult = $database->get_all( + "SELECT id,tag,count FROM tags WHERE count > 0 AND id >= ? ORDER BY id DESC", + [$start] + ); + foreach ($sqlresult as $row) { + $results[] = [$row['count'], $row['tag'], $row['id']]; + } + } - // Tag results collected, build XML output - $xml = "\n"; - foreach ($results as $tag) { - $xml .= xml_tag("tag", array( - "type" => "0", - "counts" => $tag[0], - "name" => $tag[1], - "id" => $tag[2], - )); - } - $xml .= ""; - return $xml; - } + // Tag results collected, build XML output + $xml = "\n"; + foreach ($results as $tag) { + $xml .= xml_tag("tag", [ + "type" => "0", + "counts" => $tag[0], + "name" => $tag[1], + "id" => $tag[2], + ]); + } + $xml .= ""; + return $xml; + } - /** - * find_posts() - * Find all posts that match the search criteria. Posts will be ordered by id descending. - * - * Parameters: - * - md5: md5 hash to search for (comma delimited) - * - id: id to search for (comma delimited) - * - tags: what tags to search for - * - limit: limit - * - page: page number - * - after_id: limit results to posts added after this id - * - * #return string - */ - private function api_find_posts() { - $results = array(); + /** + * find_posts() + * Find all posts that match the search criteria. Posts will be ordered by id descending. + * + * Parameters: + * - md5: md5 hash to search for (comma delimited) + * - id: id to search for (comma delimited) + * - tags: what tags to search for + * - limit: limit + * - page: page number + * - after_id: limit results to posts added after this id + * + * #return string + */ + private function api_find_posts() + { + $results = []; - $this->authenticate_user(); - $start = 0; + $this->authenticate_user(); + $start = 0; - if(isset($_GET['md5'])) { - $md5list = explode(",", $_GET['md5']); - foreach ($md5list as $md5) { - $results[] = Image::by_hash($md5); - } - $count = count($results); - } - elseif(isset($_GET['id'])) { - $idlist = explode(",", $_GET['id']); - foreach ($idlist as $id) { - $results[] = Image::by_id($id); - } - $count = count($results); - } - else { - $limit = isset($_GET['limit']) ? int_escape($_GET['limit']) : 100; + if (isset($_GET['md5'])) { + $md5list = explode(",", $_GET['md5']); + foreach ($md5list as $md5) { + $results[] = Image::by_hash($md5); + } + $count = count($results); + } elseif (isset($_GET['id'])) { + $idlist = explode(",", $_GET['id']); + foreach ($idlist as $id) { + $results[] = Image::by_id($id); + } + $count = count($results); + } else { + $limit = isset($_GET['limit']) ? int_escape($_GET['limit']) : 100; - // Calculate start offset. - if (isset($_GET['page'])) // Danbooru API uses 'page' >= 1 - $start = (int_escape($_GET['page']) - 1) * $limit; - else if (isset($_GET['pid'])) // Gelbooru API uses 'pid' >= 0 - $start = int_escape($_GET['pid']) * $limit; - else - $start = 0; + // Calculate start offset. + if (isset($_GET['page'])) { // Danbooru API uses 'page' >= 1 + $start = (int_escape($_GET['page']) - 1) * $limit; + } elseif (isset($_GET['pid'])) { // Gelbooru API uses 'pid' >= 0 + $start = int_escape($_GET['pid']) * $limit; + } else { + $start = 0; + } - $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : array(); - $count = Image::count_images($tags); - $results = Image::find_images(max($start, 0), min($limit, 100), $tags); - } + $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : []; + $count = Image::count_images($tags); + $results = Image::find_images(max($start, 0), min($limit, 100), $tags); + } - // Now we have the array $results filled with Image objects - // Let's display them - $xml = "\n"; - foreach ($results as $img) { - // Sanity check to see if $img is really an image object - // If it isn't (e.g. someone requested an invalid md5 or id), break out of the this - if (!is_object($img)) - continue; - $taglist = $img->get_tag_list(); - $owner = $img->get_owner(); - $previewsize = get_thumbnail_size($img->width, $img->height); - $xml .= xml_tag("post", array( - "id" => $img->id, - "md5" => $img->hash, - "file_name" => $img->filename, - "file_url" => $img->get_image_link(), - "height" => $img->height, - "width" => $img->width, - "preview_url" => $img->get_thumb_link(), - "preview_height" => $previewsize[1], - "preview_width" => $previewsize[0], - "rating" => "u", - "date" => $img->posted, - "is_warehoused" => false, - "tags" => $taglist, - "source" => $img->source, - "score" => 0, - "author" => $owner->name - )); - } - $xml .= ""; - return $xml; - } + // Now we have the array $results filled with Image objects + // Let's display them + $xml = "\n"; + foreach ($results as $img) { + // Sanity check to see if $img is really an image object + // If it isn't (e.g. someone requested an invalid md5 or id), break out of the this + if (!is_object($img)) { + continue; + } + $taglist = $img->get_tag_list(); + $owner = $img->get_owner(); + $previewsize = get_thumbnail_size($img->width, $img->height); + $xml .= xml_tag("post", [ + "id" => $img->id, + "md5" => $img->hash, + "file_name" => $img->filename, + "file_url" => $img->get_image_link(), + "height" => $img->height, + "width" => $img->width, + "preview_url" => $img->get_thumb_link(), + "preview_height" => $previewsize[1], + "preview_width" => $previewsize[0], + "rating" => "u", + "date" => $img->posted, + "is_warehoused" => false, + "tags" => $taglist, + "source" => $img->source, + "score" => 0, + "author" => $owner->name + ]); + } + $xml .= ""; + return $xml; + } - /** + /** * add_post() * Adds a post to the database. - * + * * Parameters: * - login: login * - password: password @@ -272,124 +272,127 @@ class DanbooruApi extends Extension { * - tags: list of tags as a string, delimited by whitespace * - md5: MD5 hash of upload in hexadecimal format * - rating: rating of the post. can be explicit, questionable, or safe. **IGNORED** - * + * * Notes: * - The only necessary parameter is tags and either file or source. * - If you want to sign your post, you need a way to authenticate your account, either by supplying login and password, or by supplying a cookie. * - If an account is not supplied or if it doesn‘t authenticate, he post will be added anonymously. * - If the md5 parameter is supplied and does not match the hash of what‘s on the server, the post is rejected. - * + * * Response * The response depends on the method used: * Post: * - X-Danbooru-Location set to the URL for newly uploaded post. * Get: * - Redirected to the newly uploaded post. - */ - private function api_add_post() { - global $user, $config, $page; - $danboorup_kludge = 1; // danboorup for firefox makes broken links out of location: /path + */ + private function api_add_post() + { + global $user, $config, $page; + $danboorup_kludge = 1; // danboorup for firefox makes broken links out of location: /path - // Check first if a login was supplied, if it wasn't check if the user is logged in via cookie - // If all that fails, it's an anonymous upload - $this->authenticate_user(); - // Now we check if a file was uploaded or a url was provided to transload - // Much of this code is borrowed from /ext/upload + // Check first if a login was supplied, if it wasn't check if the user is logged in via cookie + // If all that fails, it's an anonymous upload + $this->authenticate_user(); + // Now we check if a file was uploaded or a url was provided to transload + // Much of this code is borrowed from /ext/upload - if (!$user->can("create_image")) { - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: authentication error"); - return; - } + if (!$user->can("create_image")) { + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: authentication error"); + return; + } - if (isset($_FILES['file'])) { // A file was POST'd in - $file = $_FILES['file']['tmp_name']; - $filename = $_FILES['file']['name']; - // If both a file is posted and a source provided, I'm assuming source is the source of the file - if (isset($_REQUEST['source']) && !empty($_REQUEST['source'])) { - $source = $_REQUEST['source']; - } else { - $source = null; - } - } elseif (isset($_FILES['post'])) { - $file = $_FILES['post']['tmp_name']['file']; - $filename = $_FILES['post']['name']['file']; - if (isset($_REQUEST['post']['source']) && !empty($_REQUEST['post']['source'])) { - $source = $_REQUEST['post']['source']; - } else { - $source = null; - } - } elseif (isset($_REQUEST['source']) || isset($_REQUEST['post']['source'])) { // A url was provided - $source = isset($_REQUEST['source']) ? $_REQUEST['source'] : $_REQUEST['post']['source']; - $file = tempnam("/tmp", "shimmie_transload"); - $ok = transload($source, $file); - if (!$ok) { - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: fopen read error"); - return; - } - $filename = basename($source); - } else { // Nothing was specified at all - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: no input files"); - return; - } + if (isset($_FILES['file'])) { // A file was POST'd in + $file = $_FILES['file']['tmp_name']; + $filename = $_FILES['file']['name']; + // If both a file is posted and a source provided, I'm assuming source is the source of the file + if (isset($_REQUEST['source']) && !empty($_REQUEST['source'])) { + $source = $_REQUEST['source']; + } else { + $source = null; + } + } elseif (isset($_FILES['post'])) { + $file = $_FILES['post']['tmp_name']['file']; + $filename = $_FILES['post']['name']['file']; + if (isset($_REQUEST['post']['source']) && !empty($_REQUEST['post']['source'])) { + $source = $_REQUEST['post']['source']; + } else { + $source = null; + } + } elseif (isset($_REQUEST['source']) || isset($_REQUEST['post']['source'])) { // A url was provided + $source = isset($_REQUEST['source']) ? $_REQUEST['source'] : $_REQUEST['post']['source']; + $file = tempnam("/tmp", "shimmie_transload"); + $ok = transload($source, $file); + if (!$ok) { + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: fopen read error"); + return; + } + $filename = basename($source); + } else { // Nothing was specified at all + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: no input files"); + return; + } - // Get tags out of url - $posttags = Tag::explode(isset($_REQUEST['tags']) ? $_REQUEST['tags'] : $_REQUEST['post']['tags']); + // Get tags out of url + $posttags = Tag::explode(isset($_REQUEST['tags']) ? $_REQUEST['tags'] : $_REQUEST['post']['tags']); - // Was an md5 supplied? Does it match the file hash? - $hash = md5_file($file); - if (isset($_REQUEST['md5']) && strtolower($_REQUEST['md5']) != $hash) { - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: md5 mismatch"); - return; - } - // Upload size checking is now performed in the upload extension - // It is also currently broken due to some confusion over file variable ($tmp_filename?) + // Was an md5 supplied? Does it match the file hash? + $hash = md5_file($file); + if (isset($_REQUEST['md5']) && strtolower($_REQUEST['md5']) != $hash) { + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: md5 mismatch"); + return; + } + // Upload size checking is now performed in the upload extension + // It is also currently broken due to some confusion over file variable ($tmp_filename?) - // Does it exist already? - $existing = Image::by_hash($hash); - if (!is_null($existing)) { - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: duplicate"); - $existinglink = make_link("post/view/" . $existing->id); - if ($danboorup_kludge) $existinglink = make_http($existinglink); - $page->add_http_header("X-Danbooru-Location: $existinglink"); - return; - } + // Does it exist already? + $existing = Image::by_hash($hash); + if (!is_null($existing)) { + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: duplicate"); + $existinglink = make_link("post/view/" . $existing->id); + if ($danboorup_kludge) { + $existinglink = make_http($existinglink); + } + $page->add_http_header("X-Danbooru-Location: $existinglink"); + return; + } - // Fire off an event which should process the new file and add it to the db - $fileinfo = pathinfo($filename); - $metadata = array(); - $metadata['filename'] = $fileinfo['basename']; - $metadata['extension'] = $fileinfo['extension']; - $metadata['tags'] = $posttags; - $metadata['source'] = $source; - //log_debug("danbooru_api","========== NEW($filename) ========="); - //log_debug("danbooru_api", "upload($filename): fileinfo(".var_export($fileinfo,TRUE)."), metadata(".var_export($metadata,TRUE).")..."); + // Fire off an event which should process the new file and add it to the db + $fileinfo = pathinfo($filename); + $metadata = []; + $metadata['filename'] = $fileinfo['basename']; + $metadata['extension'] = $fileinfo['extension']; + $metadata['tags'] = $posttags; + $metadata['source'] = $source; + //log_debug("danbooru_api","========== NEW($filename) ========="); + //log_debug("danbooru_api", "upload($filename): fileinfo(".var_export($fileinfo,TRUE)."), metadata(".var_export($metadata,TRUE).")..."); - try { - $nevent = new DataUploadEvent($file, $metadata); - //log_debug("danbooru_api", "send_event(".var_export($nevent,TRUE).")"); - send_event($nevent); - // If it went ok, grab the id for the newly uploaded image and pass it in the header - $newimg = Image::by_hash($hash); // FIXME: Unsupported file doesn't throw an error? - $newid = make_link("post/view/" . $newimg->id); - if ($danboorup_kludge) $newid = make_http($newid); + try { + $nevent = new DataUploadEvent($file, $metadata); + //log_debug("danbooru_api", "send_event(".var_export($nevent,TRUE).")"); + send_event($nevent); + // If it went ok, grab the id for the newly uploaded image and pass it in the header + $newimg = Image::by_hash($hash); // FIXME: Unsupported file doesn't throw an error? + $newid = make_link("post/view/" . $newimg->id); + if ($danboorup_kludge) { + $newid = make_http($newid); + } - // Did we POST or GET this call? - if ($_SERVER['REQUEST_METHOD'] == 'POST') { - $page->add_http_header("X-Danbooru-Location: $newid"); - } else { - $page->add_http_header("Location: $newid"); - } - } catch (UploadException $ex) { - // Did something screw up? - $page->set_code(409); - $page->add_http_header("X-Danbooru-Errors: exception - " . $ex->getMessage()); - } - } + // Did we POST or GET this call? + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $page->add_http_header("X-Danbooru-Location: $newid"); + } else { + $page->add_http_header("Location: $newid"); + } + } catch (UploadException $ex) { + // Did something screw up? + $page->set_code(409); + $page->add_http_header("X-Danbooru-Errors: exception - " . $ex->getMessage()); + } + } } - - diff --git a/ext/danbooru_api/test.php b/ext/danbooru_api/test.php index 6ea0fef7..4fd2812f 100644 --- a/ext/danbooru_api/test.php +++ b/ext/danbooru_api/test.php @@ -1,23 +1,25 @@ log_in_as_admin(); +class DanbooruApiTest extends ShimmiePHPUnitTestCase +{ + public function testSearch() + { + $this->log_in_as_admin(); - $image_id = $this->post_image("tests/bedroom_workshop.jpg", "data"); + $image_id = $this->post_image("tests/bedroom_workshop.jpg", "data"); - $this->get_page("api/danbooru/find_posts"); - $this->get_page("api/danbooru/find_posts?id=$image_id"); - $this->get_page("api/danbooru/find_posts?md5=17fc89f372ed3636e28bd25cc7f3bac1"); + $this->get_page("api/danbooru/find_posts"); + $this->get_page("api/danbooru/find_posts?id=$image_id"); + $this->get_page("api/danbooru/find_posts?md5=17fc89f372ed3636e28bd25cc7f3bac1"); - $this->get_page("api/danbooru/find_tags"); - $this->get_page("api/danbooru/find_tags?id=1"); - $this->get_page("api/danbooru/find_tags?name=data"); + $this->get_page("api/danbooru/find_tags"); + $this->get_page("api/danbooru/find_tags?id=1"); + $this->get_page("api/danbooru/find_tags?name=data"); - $this->get_page("api/danbooru/post/show/$image_id"); - //$this->assert_response(302); // FIXME + $this->get_page("api/danbooru/post/show/$image_id"); + //$this->assert_response(302); // FIXME - $this->get_page("post/list/md5:17fc89f372ed3636e28bd25cc7f3bac1/1"); - //$this->assert_title(new PatternExpectation("/^Image \d+: data/")); - //$this->click("Delete"); - } + $this->get_page("post/list/md5:17fc89f372ed3636e28bd25cc7f3bac1/1"); + //$this->assert_title(new PatternExpectation("/^Image \d+: data/")); + //$this->click("Delete"); + } } diff --git a/ext/downtime/main.php b/ext/downtime/main.php index 20fa4918..891d87c3 100644 --- a/ext/downtime/main.php +++ b/ext/downtime/main.php @@ -12,35 +12,45 @@ * message specified in the box. */ -class Downtime extends Extension { - public function get_priority(): int {return 10;} +class Downtime extends Extension +{ + public function get_priority(): int + { + return 10; + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Downtime"); - $sb->add_bool_option("downtime", "Disable non-admin access: "); - $sb->add_longtext_option("downtime_message", "
    "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Downtime"); + $sb->add_bool_option("downtime", "Disable non-admin access: "); + $sb->add_longtext_option("downtime_message", "
    "); + $event->panel->add_block($sb); + } - public function onPageRequest(PageRequestEvent $event) { - global $config, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $config, $page, $user; - if($config->get_bool("downtime")) { - if(!$user->can("ignore_downtime") && !$this->is_safe_page($event)) { - $msg = $config->get_string("downtime_message"); - $this->theme->display_message($msg); - if(!defined("UNITTEST")) { // hax D: - header("HTTP/1.0 {$page->code} Downtime"); - print($page->data); - exit; - } - } - $this->theme->display_notification($page); - } - } + if ($config->get_bool("downtime")) { + if (!$user->can("ignore_downtime") && !$this->is_safe_page($event)) { + $msg = $config->get_string("downtime_message"); + $this->theme->display_message($msg); + if (!defined("UNITTEST")) { // hax D: + header("HTTP/1.0 {$page->code} Downtime"); + print($page->data); + exit; + } + } + $this->theme->display_notification($page); + } + } - private function is_safe_page(PageRequestEvent $event) { - if($event->page_matches("user_admin/login")) return true; - else return false; - } + private function is_safe_page(PageRequestEvent $event) + { + if ($event->page_matches("user_admin/login")) { + return true; + } else { + return false; + } + } } diff --git a/ext/downtime/test.php b/ext/downtime/test.php index 4331e27f..fb5bec90 100644 --- a/ext/downtime/test.php +++ b/ext/downtime/test.php @@ -1,39 +1,42 @@ set_bool("downtime", false); - } +class DowntimeTest extends ShimmiePHPUnitTestCase +{ + public function tearDown() + { + global $config; + $config->set_bool("downtime", false); + } - public function testDowntime() { - global $config; + public function testDowntime() + { + global $config; - $config->set_string("downtime_message", "brb, unit testing"); + $config->set_string("downtime_message", "brb, unit testing"); - // downtime on - $config->set_bool("downtime", true); + // downtime on + $config->set_bool("downtime", true); - $this->log_in_as_admin(); - $this->get_page("post/list"); - $this->assert_text("DOWNTIME MODE IS ON!"); - $this->assert_response(200); + $this->log_in_as_admin(); + $this->get_page("post/list"); + $this->assert_text("DOWNTIME MODE IS ON!"); + $this->assert_response(200); - $this->log_in_as_user(); - $this->get_page("post/list"); - $this->assert_content("brb, unit testing"); - $this->assert_response(503); + $this->log_in_as_user(); + $this->get_page("post/list"); + $this->assert_content("brb, unit testing"); + $this->assert_response(503); - // downtime off - $config->set_bool("downtime", false); + // downtime off + $config->set_bool("downtime", false); - $this->log_in_as_admin(); - $this->get_page("post/list"); - $this->assert_no_text("DOWNTIME MODE IS ON!"); - $this->assert_response(200); + $this->log_in_as_admin(); + $this->get_page("post/list"); + $this->assert_no_text("DOWNTIME MODE IS ON!"); + $this->assert_response(200); - $this->log_in_as_user(); - $this->get_page("post/list"); - $this->assert_no_content("brb, unit testing"); - $this->assert_response(200); - } + $this->log_in_as_user(); + $this->get_page("post/list"); + $this->assert_no_content("brb, unit testing"); + $this->assert_response(200); + } } diff --git a/ext/downtime/theme.php b/ext/downtime/theme.php index 84a36f39..feb7e4ea 100644 --- a/ext/downtime/theme.php +++ b/ext/downtime/theme.php @@ -1,27 +1,35 @@ add_block(new Block("Downtime", - "
    DOWNTIME MODE IS ON!
    ", "left", 0)); - } +class DowntimeTheme extends Themelet +{ + /** + * Show the admin that downtime mode is enabled + */ + public function display_notification(Page $page) + { + $page->add_block(new Block( + "Downtime", + "
    DOWNTIME MODE IS ON!
    ", + "left", + 0 + )); + } - /** - * Display $message and exit - */ - public function display_message(string $message) { - global $config, $user, $page; - $theme_name = $config->get_string('theme'); - $data_href = get_base_href(); - $login_link = make_link("user_admin/login"); - $auth = $user->get_auth_html(); + /** + * Display $message and exit + */ + public function display_message(string $message) + { + global $config, $user, $page; + $theme_name = $config->get_string('theme'); + $data_href = get_base_href(); + $login_link = make_link("user_admin/login"); + $auth = $user->get_auth_html(); - $page->set_mode('data'); - $page->set_code(503); - $page->set_data(<<set_mode('data'); + $page->set_code(503); + $page->set_data( + << Downtime @@ -59,5 +67,5 @@ class DowntimeTheme extends Themelet { EOD ); - } + } } diff --git a/ext/emoticons/main.php b/ext/emoticons/main.php index 0738c817..37d48d73 100644 --- a/ext/emoticons/main.php +++ b/ext/emoticons/main.php @@ -16,26 +16,30 @@ /** * Class Emoticons */ -class Emoticons extends FormatterExtension { - public function format(string $text): string { - $data_href = get_base_href(); - $text = preg_replace("/:([a-z]*?):/s", "", $text); - return $text; - } +class Emoticons extends FormatterExtension +{ + public function format(string $text): string + { + $data_href = get_base_href(); + $text = preg_replace("/:([a-z]*?):/s", "", $text); + return $text; + } - public function strip(string $text): string { - return $text; - } + public function strip(string $text): string + { + return $text; + } } /** * Class EmoticonList */ -class EmoticonList extends Extension { - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("emote/list")) { - $this->theme->display_emotes(glob("ext/emoticons/default/*")); - } - } +class EmoticonList extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("emote/list")) { + $this->theme->display_emotes(glob("ext/emoticons/default/*")); + } + } } - diff --git a/ext/emoticons/test.php b/ext/emoticons/test.php index bc4a8af9..2867dbb6 100644 --- a/ext/emoticons/test.php +++ b/ext/emoticons/test.php @@ -1,19 +1,20 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - send_event(new CommentPostingEvent($image_id, $user, ":cool: :beans:")); + send_event(new CommentPostingEvent($image_id, $user, ":cool: :beans:")); - $this->get_page("post/view/$image_id"); - $this->assert_no_text(":cool:"); # FIXME: test for working image link - //$this->assert_text(":beans:"); # FIXME: this should be left as-is + $this->get_page("post/view/$image_id"); + $this->assert_no_text(":cool:"); # FIXME: test for working image link + //$this->assert_text(":beans:"); # FIXME: this should be left as-is - $this->get_page("emote/list"); - //$this->assert_text(":arrow:"); - } + $this->get_page("emote/list"); + //$this->assert_text(":arrow:"); + } } - diff --git a/ext/emoticons/theme.php b/ext/emoticons/theme.php index 38c6f196..a673c308 100644 --- a/ext/emoticons/theme.php +++ b/ext/emoticons/theme.php @@ -1,21 +1,24 @@ Emoticon list"; - $html .= "
    "; - $n = 1; - foreach($list as $item) { - $pathinfo = pathinfo($item); - $name = $pathinfo["filename"]; - $html .= ""; - if($n++ % 3 == 0) $html .= ""; - } - $html .= "
    :$name:
    "; - $html .= ""; - $page->set_mode("data"); - $page->set_data($html); - } +class EmoticonListTheme extends Themelet +{ + public function display_emotes(array $list) + { + global $page; + $data_href = get_base_href(); + $html = "Emoticon list"; + $html .= ""; + $n = 1; + foreach ($list as $item) { + $pathinfo = pathinfo($item); + $name = $pathinfo["filename"]; + $html .= ""; + if ($n++ % 3 == 0) { + $html .= ""; + } + } + $html .= "
    :$name:
    "; + $html .= ""; + $page->set_mode("data"); + $page->set_data($html); + } } - diff --git a/ext/et/main.php b/ext/et/main.php index 21f1f77a..c56c0f4d 100644 --- a/ext/et/main.php +++ b/ext/et/main.php @@ -12,74 +12,76 @@ * versions of PHP I should test with, etc. */ -class ET extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $user; - if($event->page_matches("system_info")) { - if($user->can("view_sysinfo")) { - $this->theme->display_info_page($this->get_info()); - } - } - } +class ET extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $user; + if ($event->page_matches("system_info")) { + if ($user->can("view_sysinfo")) { + $this->theme->display_info_page($this->get_info()); + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("view_sysinfo")) { - $event->add_link("System Info", make_link("system_info")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("view_sysinfo")) { + $event->add_link("System Info", make_link("system_info")); + } + } - /** - * Collect the information and return it in a keyed array. - */ - private function get_info() { - global $config, $database; + /** + * Collect the information and return it in a keyed array. + */ + private function get_info() + { + global $config, $database; - $info = array(); - $info['site_title'] = $config->get_string("title"); - $info['site_theme'] = $config->get_string("theme"); - $info['site_url'] = "http://" . $_SERVER["HTTP_HOST"] . get_base_href(); + $info = []; + $info['site_title'] = $config->get_string("title"); + $info['site_theme'] = $config->get_string("theme"); + $info['site_url'] = "http://" . $_SERVER["HTTP_HOST"] . get_base_href(); - $info['sys_shimmie'] = VERSION; - $info['sys_schema'] = $config->get_string("db_version"); - $info['sys_php'] = phpversion(); - $info['sys_db'] = $database->get_driver_name(); - $info['sys_os'] = php_uname(); - $info['sys_disk'] = to_shorthand_int(disk_total_space("./") - disk_free_space("./")) . " / " . - to_shorthand_int(disk_total_space("./")); - $info['sys_server'] = isset($_SERVER["SERVER_SOFTWARE"]) ? $_SERVER["SERVER_SOFTWARE"] : 'unknown'; - - $info['thumb_engine'] = $config->get_string("thumb_engine"); - $info['thumb_quality'] = $config->get_int('thumb_quality'); - $info['thumb_width'] = $config->get_int('thumb_width'); - $info['thumb_height'] = $config->get_int('thumb_height'); - $info['thumb_mem'] = $config->get_int("thumb_mem_limit"); + $info['sys_shimmie'] = VERSION; + $info['sys_schema'] = $config->get_string("db_version"); + $info['sys_php'] = phpversion(); + $info['sys_db'] = $database->get_driver_name(); + $info['sys_os'] = php_uname(); + $info['sys_disk'] = to_shorthand_int(disk_total_space("./") - disk_free_space("./")) . " / " . + to_shorthand_int(disk_total_space("./")); + $info['sys_server'] = isset($_SERVER["SERVER_SOFTWARE"]) ? $_SERVER["SERVER_SOFTWARE"] : 'unknown'; + + $info['thumb_engine'] = $config->get_string("thumb_engine"); + $info['thumb_quality'] = $config->get_int('thumb_quality'); + $info['thumb_width'] = $config->get_int('thumb_width'); + $info['thumb_height'] = $config->get_int('thumb_height'); + $info['thumb_mem'] = $config->get_int("thumb_mem_limit"); - $info['stat_images'] = $database->get_one("SELECT COUNT(*) FROM images"); - $info['stat_comments'] = $database->get_one("SELECT COUNT(*) FROM comments"); - $info['stat_users'] = $database->get_one("SELECT COUNT(*) FROM users"); - $info['stat_tags'] = $database->get_one("SELECT COUNT(*) FROM tags"); - $info['stat_image_tags'] = $database->get_one("SELECT COUNT(*) FROM image_tags"); + $info['stat_images'] = $database->get_one("SELECT COUNT(*) FROM images"); + $info['stat_comments'] = $database->get_one("SELECT COUNT(*) FROM comments"); + $info['stat_users'] = $database->get_one("SELECT COUNT(*) FROM users"); + $info['stat_tags'] = $database->get_one("SELECT COUNT(*) FROM tags"); + $info['stat_image_tags'] = $database->get_one("SELECT COUNT(*) FROM image_tags"); - $els = array(); - foreach(get_declared_classes() as $class) { - $rclass = new ReflectionClass($class); - if($rclass->isAbstract()) { - // don't do anything - } - elseif(is_subclass_of($class, "Extension")) { - $els[] = $class; - } - } - $info['sys_extensions'] = join(', ', $els); + $els = []; + foreach (get_declared_classes() as $class) { + $rclass = new ReflectionClass($class); + if ($rclass->isAbstract()) { + // don't do anything + } elseif (is_subclass_of($class, "Extension")) { + $els[] = $class; + } + } + $info['sys_extensions'] = join(', ', $els); - //$cfs = array(); - //foreach($database->get_all("SELECT name, value FROM config") as $pair) { - // $cfs[] = $pair['name']."=".$pair['value']; - //} - //$info[''] = "Config: ".join(", ", $cfs); + //$cfs = array(); + //foreach($database->get_all("SELECT name, value FROM config") as $pair) { + // $cfs[] = $pair['name']."=".$pair['value']; + //} + //$info[''] = "Config: ".join(", ", $cfs); - return $info; - } + return $info; + } } - diff --git a/ext/et/test.php b/ext/et/test.php index 1d741eda..c9508107 100644 --- a/ext/et/test.php +++ b/ext/et/test.php @@ -1,8 +1,10 @@ log_in_as_admin(); - $this->get_page("system_info"); - $this->assert_title("System Info"); - } +class ETTest extends ShimmiePHPUnitTestCase +{ + public function testET() + { + $this->log_in_as_admin(); + $this->get_page("system_info"); + $this->assert_title("System Info"); + } } diff --git a/ext/et/theme.php b/ext/et/theme.php index 2239807b..f23ea296 100644 --- a/ext/et/theme.php +++ b/ext/et/theme.php @@ -1,22 +1,25 @@ $value) - */ - public function display_info_page($info) { - global $page; +class ETTheme extends Themelet +{ + /* + * Create a page showing info + * + * $info = an array of ($name => $value) + */ + public function display_info_page($info) + { + global $page; - $page->set_title("System Info"); - $page->set_heading("System Info"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Information:", $this->build_data_form($info))); - } + $page->set_title("System Info"); + $page->set_heading("System Info"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Information:", $this->build_data_form($info))); + } - protected function build_data_form($info) { - $data = << @@ -56,7 +59,6 @@ EOD; of web servers / databases / etc I need to support. EOD; - return $html; - } + return $html; + } } - diff --git a/ext/ext_manager/main.php b/ext/ext_manager/main.php index de26e527..f9ef6bba 100644 --- a/ext/ext_manager/main.php +++ b/ext/ext_manager/main.php @@ -12,193 +12,204 @@ * extensions and read their documentation */ -function __extman_extcmp(ExtensionInfo $a, ExtensionInfo $b): int { - return strcmp($a->name, $b->name); +function __extman_extcmp(ExtensionInfo $a, ExtensionInfo $b): int +{ + return strcmp($a->name, $b->name); } -class ExtensionInfo { - public $ext_name, $name, $link, $author, $email; - public $description, $documentation, $version, $visibility; - public $enabled; +class ExtensionInfo +{ + public $ext_name; + public $name; + public $link; + public $author; + public $email; + public $description; + public $documentation; + public $version; + public $visibility; + public $enabled; - public function __construct($main) { - $matches = array(); - $lines = file($main); - $number_of_lines = count($lines); - preg_match("#ext/(.*)/main.php#", $main, $matches); - $this->ext_name = $matches[1]; - $this->name = $this->ext_name; - $this->enabled = $this->is_enabled($this->ext_name); + public function __construct($main) + { + $matches = []; + $lines = file($main); + $number_of_lines = count($lines); + preg_match("#ext/(.*)/main.php#", $main, $matches); + $this->ext_name = $matches[1]; + $this->name = $this->ext_name; + $this->enabled = $this->is_enabled($this->ext_name); - for($i=0; $i<$number_of_lines; $i++) { - $line = $lines[$i]; - if(preg_match("/Name: (.*)/", $line, $matches)) { - $this->name = $matches[1]; - } - else if(preg_match("/Visibility: (.*)/", $line, $matches)) { - $this->visibility = $matches[1]; - } - else if(preg_match("/Link: (.*)/", $line, $matches)) { - $this->link = $matches[1]; - if($this->link[0] == "/") { - $this->link = make_link(substr($this->link, 1)); - } - } - else if(preg_match("/Version: (.*)/", $line, $matches)) { - $this->version = $matches[1]; - } - else if(preg_match("/Author: (.*) [<\(](.*@.*)[>\)]/", $line, $matches)) { - $this->author = $matches[1]; - $this->email = $matches[2]; - } - else if(preg_match("/Author: (.*)/", $line, $matches)) { - $this->author = $matches[1]; - } - else if(preg_match("/(.*)Description: ?(.*)/", $line, $matches)) { - $this->description = $matches[2]; - $start = $matches[1]." "; - $start_len = strlen($start); - while(substr($lines[$i+1], 0, $start_len) == $start) { - $this->description .= " ".substr($lines[$i+1], $start_len); - $i++; - } - } - else if(preg_match("/(.*)Documentation: ?(.*)/", $line, $matches)) { - $this->documentation = $matches[2]; - $start = $matches[1]." "; - $start_len = strlen($start); - while(substr($lines[$i+1], 0, $start_len) == $start) { - $this->documentation .= " ".substr($lines[$i+1], $start_len); - $i++; - } - $this->documentation = str_replace('$site', make_http(get_base_href()), $this->documentation); - } - else if(preg_match("/\*\//", $line, $matches)) { - break; - } - } - } + for ($i=0; $i<$number_of_lines; $i++) { + $line = $lines[$i]; + if (preg_match("/Name: (.*)/", $line, $matches)) { + $this->name = $matches[1]; + } elseif (preg_match("/Visibility: (.*)/", $line, $matches)) { + $this->visibility = $matches[1]; + } elseif (preg_match("/Link: (.*)/", $line, $matches)) { + $this->link = $matches[1]; + if ($this->link[0] == "/") { + $this->link = make_link(substr($this->link, 1)); + } + } elseif (preg_match("/Version: (.*)/", $line, $matches)) { + $this->version = $matches[1]; + } elseif (preg_match("/Author: (.*) [<\(](.*@.*)[>\)]/", $line, $matches)) { + $this->author = $matches[1]; + $this->email = $matches[2]; + } elseif (preg_match("/Author: (.*)/", $line, $matches)) { + $this->author = $matches[1]; + } elseif (preg_match("/(.*)Description: ?(.*)/", $line, $matches)) { + $this->description = $matches[2]; + $start = $matches[1]." "; + $start_len = strlen($start); + while (substr($lines[$i+1], 0, $start_len) == $start) { + $this->description .= " ".substr($lines[$i+1], $start_len); + $i++; + } + } elseif (preg_match("/(.*)Documentation: ?(.*)/", $line, $matches)) { + $this->documentation = $matches[2]; + $start = $matches[1]." "; + $start_len = strlen($start); + while (substr($lines[$i+1], 0, $start_len) == $start) { + $this->documentation .= " ".substr($lines[$i+1], $start_len); + $i++; + } + $this->documentation = str_replace('$site', make_http(get_base_href()), $this->documentation); + } elseif (preg_match("/\*\//", $line, $matches)) { + break; + } + } + } - private function is_enabled(string $fname): ?bool { - $core = explode(",", CORE_EXTS); - $extra = explode(",", EXTRA_EXTS); + private function is_enabled(string $fname): ?bool + { + $core = explode(",", CORE_EXTS); + $extra = explode(",", EXTRA_EXTS); - if(in_array($fname, $extra)) return true; // enabled - if(in_array($fname, $core)) return null; // core - return false; // not enabled - } + if (in_array($fname, $extra)) { + return true; + } // enabled + if (in_array($fname, $core)) { + return null; + } // core + return false; // not enabled + } } -class ExtManager extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("ext_manager")) { - if($user->can("manage_extension_list")) { - if($event->get_arg(0) == "set" && $user->check_auth_token()) { - if(is_writable("data/config")) { - $this->set_things($_POST); - log_warning("ext_manager", "Active extensions changed", "Active extensions changed"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("ext_manager")); - } - else { - $this->theme->display_error(500, "File Operation Failed", - "The config file (data/config/extensions.conf.php) isn't writable by the web server :("); - } - } - else { - $this->theme->display_table($page, $this->get_extensions(true), true); - } - } - else { - $this->theme->display_table($page, $this->get_extensions(false), false); - } - } +class ExtManager extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("ext_manager")) { + if ($user->can("manage_extension_list")) { + if ($event->get_arg(0) == "set" && $user->check_auth_token()) { + if (is_writable("data/config")) { + $this->set_things($_POST); + log_warning("ext_manager", "Active extensions changed", "Active extensions changed"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("ext_manager")); + } else { + $this->theme->display_error( + 500, + "File Operation Failed", + "The config file (data/config/extensions.conf.php) isn't writable by the web server :(" + ); + } + } else { + $this->theme->display_table($page, $this->get_extensions(true), true); + } + } else { + $this->theme->display_table($page, $this->get_extensions(false), false); + } + } - if($event->page_matches("ext_doc")) { - $ext = $event->get_arg(0); - if(file_exists("ext/$ext/main.php")) { - $info = new ExtensionInfo("ext/$ext/main.php"); - $this->theme->display_doc($page, $info); - } - else { - $this->theme->display_table($page, $this->get_extensions(false), false); - } - } - } + if ($event->page_matches("ext_doc")) { + $ext = $event->get_arg(0); + if (file_exists("ext/$ext/main.php")) { + $info = new ExtensionInfo("ext/$ext/main.php"); + $this->theme->display_doc($page, $info); + } else { + $this->theme->display_table($page, $this->get_extensions(false), false); + } + } + } - public function onCommand(CommandEvent $event) { - if($event->cmd == "help") { - print "\tdisable-all-ext\n"; - print "\t\tdisable all extensions\n\n"; - } - if($event->cmd == "disable-all-ext") { - $this->write_config(array()); - } - } + public function onCommand(CommandEvent $event) + { + if ($event->cmd == "help") { + print "\tdisable-all-ext\n"; + print "\t\tdisable all extensions\n\n"; + } + if ($event->cmd == "disable-all-ext") { + $this->write_config([]); + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("manage_extension_list")) { - $event->add_link("Extension Manager", make_link("ext_manager")); - } - else { - $event->add_link("Help", make_link("ext_doc")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("manage_extension_list")) { + $event->add_link("Extension Manager", make_link("ext_manager")); + } else { + $event->add_link("Help", make_link("ext_doc")); + } + } - /** - * #return ExtensionInfo[] - */ - private function get_extensions(bool $all): array { - $extensions = array(); - if($all) { - $exts = zglob("ext/*/main.php"); - } - else { - $exts = zglob("ext/{".ENABLED_EXTS."}/main.php"); - } - foreach($exts as $main) { - $extensions[] = new ExtensionInfo($main); - } - usort($extensions, "__extman_extcmp"); - return $extensions; - } + /** + * #return ExtensionInfo[] + */ + private function get_extensions(bool $all): array + { + $extensions = []; + if ($all) { + $exts = zglob("ext/*/main.php"); + } else { + $exts = zglob("ext/{".ENABLED_EXTS."}/main.php"); + } + foreach ($exts as $main) { + $extensions[] = new ExtensionInfo($main); + } + usort($extensions, "__extman_extcmp"); + return $extensions; + } - private function set_things($settings) { - $core = explode(",", CORE_EXTS); - $extras = array(); + private function set_things($settings) + { + $core = explode(",", CORE_EXTS); + $extras = []; - foreach(glob("ext/*/main.php") as $main) { - $matches = array(); - preg_match("#ext/(.*)/main.php#", $main, $matches); - $fname = $matches[1]; + foreach (glob("ext/*/main.php") as $main) { + $matches = []; + preg_match("#ext/(.*)/main.php#", $main, $matches); + $fname = $matches[1]; - if(!in_array($fname, $core) && isset($settings["ext_$fname"])) { - $extras[] = $fname; - } - } + if (!in_array($fname, $core) && isset($settings["ext_$fname"])) { + $extras[] = $fname; + } + } - $this->write_config($extras); - } + $this->write_config($extras); + } /** * #param string[] $extras */ - private function write_config(array $extras) { - file_put_contents( - "data/config/extensions.conf.php", - '<'.'?php'."\n". - 'define("EXTRA_EXTS", "'.implode(",", $extras).'");'."\n". - '?'.">" - ); + private function write_config(array $extras) + { + file_put_contents( + "data/config/extensions.conf.php", + '<'.'?php'."\n". + 'define("EXTRA_EXTS", "'.implode(",", $extras).'");'."\n". + '?'.">" + ); - // when the list of active extensions changes, we can be - // pretty sure that the list of who reacts to what will - // change too - if(file_exists("data/cache/event_listeners.php")) { - unlink("data/cache/event_listeners.php"); - } - } + // when the list of active extensions changes, we can be + // pretty sure that the list of who reacts to what will + // change too + if (file_exists("data/cache/event_listeners.php")) { + unlink("data/cache/event_listeners.php"); + } + } } diff --git a/ext/ext_manager/test.php b/ext/ext_manager/test.php index 850abc27..6af85a07 100644 --- a/ext/ext_manager/test.php +++ b/ext/ext_manager/test.php @@ -1,25 +1,27 @@ get_page('ext_manager'); - $this->assert_title("Extensions"); +class ExtManagerTest extends ShimmiePHPUnitTestCase +{ + public function testAuth() + { + $this->get_page('ext_manager'); + $this->assert_title("Extensions"); - $this->get_page('ext_doc'); - $this->assert_title("Extensions"); + $this->get_page('ext_doc'); + $this->assert_title("Extensions"); - $this->get_page('ext_doc/ext_manager'); - $this->assert_title("Documentation for Extension Manager"); - $this->assert_text("view a list of all extensions"); + $this->get_page('ext_doc/ext_manager'); + $this->assert_title("Documentation for Extension Manager"); + $this->assert_text("view a list of all extensions"); - # test author without email - $this->get_page('ext_doc/user'); + # test author without email + $this->get_page('ext_doc/user'); - $this->log_in_as_admin(); - $this->get_page('ext_manager'); - $this->assert_title("Extensions"); - //$this->assert_text("SimpleTest integration"); // FIXME: something which still exists - $this->log_out(); + $this->log_in_as_admin(); + $this->get_page('ext_manager'); + $this->assert_title("Extensions"); + //$this->assert_text("SimpleTest integration"); // FIXME: something which still exists + $this->log_out(); - # FIXME: test that some extensions can be added and removed? :S - } + # FIXME: test that some extensions can be added and removed? :S + } } diff --git a/ext/ext_manager/theme.php b/ext/ext_manager/theme.php index e260d7d6..88853cf8 100644 --- a/ext/ext_manager/theme.php +++ b/ext/ext_manager/theme.php @@ -1,12 +1,14 @@ Enabled" : ""; - $html = " +class ExtManagerTheme extends Themelet +{ + /** + * #param ExtensionInfo[] $extensions + */ + public function display_table(Page $page, array $extensions, bool $editable) + { + $h_en = $editable ? "Enabled" : ""; + $html = " ".make_form(make_link("ext_manager/set"))." @@ -19,110 +21,112 @@ class ExtManagerTheme extends Themelet { "; - foreach($extensions as $extension) { - if(!$editable && $extension->visibility == "admin") continue; + foreach ($extensions as $extension) { + if (!$editable && $extension->visibility == "admin") { + continue; + } - $h_name = html_escape(empty($extension->name) ? $extension->ext_name : $extension->name); - $h_description = html_escape($extension->description); - $h_link = make_link("ext_doc/".url_escape($extension->ext_name)); - $h_enabled = ($extension->enabled === TRUE ? " checked='checked'" : ($extension->enabled === FALSE ? "" : " disabled checked='checked'")); - $h_enabled_box = $editable ? "" : ""; - $h_docs = ($extension->documentation ? "" : ""); //TODO: A proper "docs" symbol would be preferred here. + $h_name = html_escape(empty($extension->name) ? $extension->ext_name : $extension->name); + $h_description = html_escape($extension->description); + $h_link = make_link("ext_doc/".url_escape($extension->ext_name)); + $h_enabled = ($extension->enabled === true ? " checked='checked'" : ($extension->enabled === false ? "" : " disabled checked='checked'")); + $h_enabled_box = $editable ? "" : ""; + $h_docs = ($extension->documentation ? "" : ""); //TODO: A proper "docs" symbol would be preferred here. - $html .= " + $html .= " {$h_enabled_box} "; - } - $h_set = $editable ? "" : ""; - $html .= " + } + $h_set = $editable ? "" : ""; + $html .= " $h_set
    {$h_name} {$h_docs} {$h_description}
    "; - $page->set_title("Extensions"); - $page->set_heading("Extensions"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Extension Manager", $html)); - } + $page->set_title("Extensions"); + $page->set_heading("Extensions"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Extension Manager", $html)); + } - /* - public function display_blocks(Page $page, $extensions) { - global $user; - $col_1 = ""; - $col_2 = ""; - foreach($extensions as $extension) { - $ext_name = $extension->ext_name; - $h_name = empty($extension->name) ? $ext_name : html_escape($extension->name); - $h_email = html_escape($extension->email); - $h_link = isset($extension->link) ? - "link)."\">Original Site" : ""; - $h_doc = isset($extension->documentation) ? - "ext_name))."\">Documentation" : ""; - $h_author = html_escape($extension->author); - $h_description = html_escape($extension->description); - $h_enabled = $extension->enabled ? " checked='checked'" : ""; - $h_author_link = empty($h_email) ? - "$h_author" : - "$h_author"; + /* + public function display_blocks(Page $page, $extensions) { + global $user; + $col_1 = ""; + $col_2 = ""; + foreach($extensions as $extension) { + $ext_name = $extension->ext_name; + $h_name = empty($extension->name) ? $ext_name : html_escape($extension->name); + $h_email = html_escape($extension->email); + $h_link = isset($extension->link) ? + "link)."\">Original Site" : ""; + $h_doc = isset($extension->documentation) ? + "ext_name))."\">Documentation" : ""; + $h_author = html_escape($extension->author); + $h_description = html_escape($extension->description); + $h_enabled = $extension->enabled ? " checked='checked'" : ""; + $h_author_link = empty($h_email) ? + "$h_author" : + "$h_author"; - $html = " -

    - - - - - - - - - - -
    $h_name
    By $h_author_linkEnabled: 
    $h_description

    $h_link $h_doc

    - "; - if($n++ % 2 == 0) { - $col_1 .= $html; - } - else { - $col_2 .= $html; - } - } - $html = " - ".make_form(make_link("ext_manager/set"))." - ".$user->get_auth_html()." - - - -
    $col_1$col_2
    - - "; + $html = " +

    + + + + + + + + + + +
    $h_name
    By $h_author_linkEnabled: 
    $h_description

    $h_link $h_doc

    + "; + if($n++ % 2 == 0) { + $col_1 .= $html; + } + else { + $col_2 .= $html; + } + } + $html = " + ".make_form(make_link("ext_manager/set"))." + ".$user->get_auth_html()." + + + +
    $col_1$col_2
    + + "; - $page->set_title("Extensions"); - $page->set_heading("Extensions"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Extension Manager", $html)); - } - */ + $page->set_title("Extensions"); + $page->set_heading("Extensions"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Extension Manager", $html)); + } + */ - public function display_doc(Page $page, ExtensionInfo $info) { - $author = ""; - if($info->author) { - if($info->email) { - $author = "
    Author: email)."\">".html_escape($info->author).""; - } - else { - $author = "
    Author: ".html_escape($info->author); - } - } - $version = ($info->version) ? "
    Version: ".html_escape($info->version) : ""; - $link = ($info->link) ? "
    Home Page: link)."\">Link" : ""; - $doc = $info->documentation; - $html = " + public function display_doc(Page $page, ExtensionInfo $info) + { + $author = ""; + if ($info->author) { + if ($info->email) { + $author = "
    Author: email)."\">".html_escape($info->author).""; + } else { + $author = "
    Author: ".html_escape($info->author); + } + } + $version = ($info->version) ? "
    Version: ".html_escape($info->version) : ""; + $link = ($info->link) ? "
    Home Page: link)."\">Link" : ""; + $doc = $info->documentation; + $html = "

    $author $version @@ -132,10 +136,9 @@ class ExtManagerTheme extends Themelet {

    Back to the list

    "; - $page->set_title("Documentation for ".html_escape($info->name)); - $page->set_heading(html_escape($info->name)); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Documentation", $html)); - } + $page->set_title("Documentation for ".html_escape($info->name)); + $page->set_heading(html_escape($info->name)); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Documentation", $html)); + } } - diff --git a/ext/favorites/main.php b/ext/favorites/main.php index 48b3e03c..4dc2df1f 100644 --- a/ext/favorites/main.php +++ b/ext/favorites/main.php @@ -13,146 +13,158 @@ * using the $favorites placeholder */ -class FavoriteSetEvent extends Event { - /** @var int */ - public $image_id; - /** @var \User */ - public $user; - /** @var bool */ - public $do_set; +class FavoriteSetEvent extends Event +{ + /** @var int */ + public $image_id; + /** @var \User */ + public $user; + /** @var bool */ + public $do_set; - public function __construct(int $image_id, User $user, bool $do_set) { - assert(is_int($image_id)); - assert(is_bool($do_set)); + public function __construct(int $image_id, User $user, bool $do_set) + { + assert(is_int($image_id)); + assert(is_bool($do_set)); - $this->image_id = $image_id; - $this->user = $user; - $this->do_set = $do_set; - } + $this->image_id = $image_id; + $this->user = $user; + $this->do_set = $do_set; + } } -class Favorites extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - if($config->get_int("ext_favorites_version", 0) < 1) { - $this->install(); - } - } +class Favorites extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + if ($config->get_int("ext_favorites_version", 0) < 1) { + $this->install(); + } + } - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $database, $user; - if(!$user->is_anonymous()) { - $user_id = $user->id; - $image_id = $event->image->id; + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $database, $user; + if (!$user->is_anonymous()) { + $user_id = $user->id; + $image_id = $event->image->id; - $is_favorited = $database->get_one( - "SELECT COUNT(*) AS ct FROM user_favorites WHERE user_id = :user_id AND image_id = :image_id", - array("user_id"=>$user_id, "image_id"=>$image_id)) > 0; - - $event->add_part($this->theme->get_voter_html($event->image, $is_favorited)); - } - } + $is_favorited = $database->get_one( + "SELECT COUNT(*) AS ct FROM user_favorites WHERE user_id = :user_id AND image_id = :image_id", + ["user_id"=>$user_id, "image_id"=>$image_id] + ) > 0; + + $event->add_part($this->theme->get_voter_html($event->image, $is_favorited)); + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - $people = $this->list_persons_who_have_favorited($event->image); - if(count($people) > 0) { - $this->theme->display_people($people); - } - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + $people = $this->list_persons_who_have_favorited($event->image); + if (count($people) > 0) { + $this->theme->display_people($people); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("change_favorite") && !$user->is_anonymous() && $user->check_auth_token()) { - $image_id = int_escape($_POST['image_id']); - if((($_POST['favorite_action'] == "set") || ($_POST['favorite_action'] == "unset")) && ($image_id > 0)) { - if($_POST['favorite_action'] == "set") { - send_event(new FavoriteSetEvent($image_id, $user, true)); - log_debug("favourite", "Favourite set for $image_id", "Favourite added"); - } - else { - send_event(new FavoriteSetEvent($image_id, $user, false)); - log_debug("favourite", "Favourite removed for $image_id", "Favourite removed"); - } - } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$image_id")); - } - } + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("change_favorite") && !$user->is_anonymous() && $user->check_auth_token()) { + $image_id = int_escape($_POST['image_id']); + if ((($_POST['favorite_action'] == "set") || ($_POST['favorite_action'] == "unset")) && ($image_id > 0)) { + if ($_POST['favorite_action'] == "set") { + send_event(new FavoriteSetEvent($image_id, $user, true)); + log_debug("favourite", "Favourite set for $image_id", "Favourite added"); + } else { + send_event(new FavoriteSetEvent($image_id, $user, false)); + log_debug("favourite", "Favourite removed for $image_id", "Favourite removed"); + } + } + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$image_id")); + } + } - public function onUserPageBuilding(UserPageBuildingEvent $event) { - $i_favorites_count = Image::count_images(array("favorited_by={$event->display_user->name}")); - $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; - $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); - $favorites_link = make_link("post/list/favorited_by={$event->display_user->name}/1"); - $event->add_stats("Images favorited: $i_favorites_count, $h_favorites_rate per day"); - } + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + $i_favorites_count = Image::count_images(["favorited_by={$event->display_user->name}"]); + $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; + $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); + $favorites_link = make_link("post/list/favorited_by={$event->display_user->name}/1"); + $event->add_stats("Images favorited: $i_favorites_count, $h_favorites_rate per day"); + } - public function onImageInfoSet(ImageInfoSetEvent $event) { - global $user; - if( - in_array('favorite_action', $_POST) && - (($_POST['favorite_action'] == "set") || ($_POST['favorite_action'] == "unset")) - ) { - send_event(new FavoriteSetEvent($event->image->id, $user, ($_POST['favorite_action'] == "set"))); - } - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + global $user; + if ( + in_array('favorite_action', $_POST) && + (($_POST['favorite_action'] == "set") || ($_POST['favorite_action'] == "unset")) + ) { + send_event(new FavoriteSetEvent($event->image->id, $user, ($_POST['favorite_action'] == "set"))); + } + } - public function onFavoriteSet(FavoriteSetEvent $event) { - global $user; - $this->add_vote($event->image_id, $user->id, $event->do_set); - } + public function onFavoriteSet(FavoriteSetEvent $event) + { + global $user; + $this->add_vote($event->image_id, $user->id, $event->do_set); + } - // FIXME: this should be handled by the foreign key. Check that it - // is, and then remove this - public function onImageDeletion(ImageDeletionEvent $event) { - global $database; - $database->execute("DELETE FROM user_favorites WHERE image_id=:image_id", array("image_id"=>$event->image->id)); - } + // FIXME: this should be handled by the foreign key. Check that it + // is, and then remove this + public function onImageDeletion(ImageDeletionEvent $event) + { + global $database; + $database->execute("DELETE FROM user_favorites WHERE image_id=:image_id", ["image_id"=>$event->image->id]); + } - public function onParseLinkTemplate(ParseLinkTemplateEvent $event) { - $event->replace('$favorites', $event->image->favorites); - } + public function onParseLinkTemplate(ParseLinkTemplateEvent $event) + { + $event->replace('$favorites', $event->image->favorites); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; - $username = url_escape($user->name); - $event->add_link("My Favorites", make_link("post/list/favorited_by=$username/1"), 20); - } + $username = url_escape($user->name); + $event->add_link("My Favorites", make_link("post/list/favorited_by=$username/1"), 20); + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - if(preg_match("/^favorites([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $favorites = $matches[2]; - $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)")); - } - else if(preg_match("/^favorited_by[=|:](.*)$/i", $event->term, $matches)) { - $user = User::by_name($matches[1]); - if(!is_null($user)) { - $user_id = $user->id; - } - else { - $user_id = -1; - } + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + if (preg_match("/^favorites([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $favorites = $matches[2]; + $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)")); + } elseif (preg_match("/^favorited_by[=|:](.*)$/i", $event->term, $matches)) { + $user = User::by_name($matches[1]); + if (!is_null($user)) { + $user_id = $user->id; + } else { + $user_id = -1; + } - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); - } - else if(preg_match("/^favorited_by_userno[=|:](\d+)$/i", $event->term, $matches)) { - $user_id = int_escape($matches[1]); - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); - } - } + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); + } elseif (preg_match("/^favorited_by_userno[=|:](\d+)$/i", $event->term, $matches)) { + $user_id = int_escape($matches[1]); + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); + } + } - private function install() { - global $database; - global $config; + private function install() + { + global $database; + global $config; - if($config->get_int("ext_favorites_version") < 1) { - $database->Execute("ALTER TABLE images ADD COLUMN favorites INTEGER NOT NULL DEFAULT 0"); - $database->Execute("CREATE INDEX images__favorites ON images(favorites)"); - $database->create_table("user_favorites", " + if ($config->get_int("ext_favorites_version") < 1) { + $database->Execute("ALTER TABLE images ADD COLUMN favorites INTEGER NOT NULL DEFAULT 0"); + $database->Execute("CREATE INDEX images__favorites ON images(favorites)"); + $database->create_table("user_favorites", " image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, created_at SCORE_DATETIME NOT NULL, @@ -160,47 +172,52 @@ class Favorites extends Extension { FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX user_favorites_image_id_idx ON user_favorites(image_id)", array()); - $config->set_int("ext_favorites_version", 2); - } + $database->execute("CREATE INDEX user_favorites_image_id_idx ON user_favorites(image_id)", []); + $config->set_int("ext_favorites_version", 2); + } - if($config->get_int("ext_favorites_version") < 2) { - log_info("favorites", "Cleaning user favourites"); - $database->Execute("DELETE FROM user_favorites WHERE user_id NOT IN (SELECT id FROM users)"); - $database->Execute("DELETE FROM user_favorites WHERE image_id NOT IN (SELECT id FROM images)"); + if ($config->get_int("ext_favorites_version") < 2) { + log_info("favorites", "Cleaning user favourites"); + $database->Execute("DELETE FROM user_favorites WHERE user_id NOT IN (SELECT id FROM users)"); + $database->Execute("DELETE FROM user_favorites WHERE image_id NOT IN (SELECT id FROM images)"); - log_info("favorites", "Adding foreign keys to user favourites"); - $database->Execute("ALTER TABLE user_favorites ADD FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;"); - $database->Execute("ALTER TABLE user_favorites ADD FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE;"); - $config->set_int("ext_favorites_version", 2); - } - } + log_info("favorites", "Adding foreign keys to user favourites"); + $database->Execute("ALTER TABLE user_favorites ADD FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;"); + $database->Execute("ALTER TABLE user_favorites ADD FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE;"); + $config->set_int("ext_favorites_version", 2); + } + } - private function add_vote(int $image_id, int $user_id, bool $do_set) { - global $database; - if ($do_set) { - $database->Execute( - "INSERT INTO user_favorites(image_id, user_id, created_at) VALUES(:image_id, :user_id, NOW())", - array("image_id"=>$image_id, "user_id"=>$user_id)); - } else { - $database->Execute( - "DELETE FROM user_favorites WHERE image_id = :image_id AND user_id = :user_id", - array("image_id"=>$image_id, "user_id"=>$user_id)); - } - $database->Execute( - "UPDATE images SET favorites=(SELECT COUNT(*) FROM user_favorites WHERE image_id=:image_id) WHERE id=:user_id", - array("image_id"=>$image_id, "user_id"=>$user_id)); - } + private function add_vote(int $image_id, int $user_id, bool $do_set) + { + global $database; + if ($do_set) { + $database->Execute( + "INSERT INTO user_favorites(image_id, user_id, created_at) VALUES(:image_id, :user_id, NOW())", + ["image_id"=>$image_id, "user_id"=>$user_id] + ); + } else { + $database->Execute( + "DELETE FROM user_favorites WHERE image_id = :image_id AND user_id = :user_id", + ["image_id"=>$image_id, "user_id"=>$user_id] + ); + } + $database->Execute( + "UPDATE images SET favorites=(SELECT COUNT(*) FROM user_favorites WHERE image_id=:image_id) WHERE id=:user_id", + ["image_id"=>$image_id, "user_id"=>$user_id] + ); + } - /** - * #return string[] - */ - private function list_persons_who_have_favorited(Image $image): array { - global $database; + /** + * #return string[] + */ + private function list_persons_who_have_favorited(Image $image): array + { + global $database; - return $database->get_col( - "SELECT name FROM users WHERE id IN (SELECT user_id FROM user_favorites WHERE image_id = :image_id) ORDER BY name", - array("image_id"=>$image->id)); - } + return $database->get_col( + "SELECT name FROM users WHERE id IN (SELECT user_id FROM user_favorites WHERE image_id = :image_id) ORDER BY name", + ["image_id"=>$image->id] + ); + } } - diff --git a/ext/favorites/test.php b/ext/favorites/test.php index cb6c09c7..59c97fcc 100644 --- a/ext/favorites/test.php +++ b/ext/favorites/test.php @@ -1,29 +1,30 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); +class FavoritesTest extends ShimmiePHPUnitTestCase +{ + public function testFavorites() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: test"); - $this->assert_no_text("Favorited By"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: test"); + $this->assert_no_text("Favorited By"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->click("Favorite"); - $this->assert_text("Favorited By"); + $this->click("Favorite"); + $this->assert_text("Favorited By"); - $this->get_page("post/list/favorited_by=test/1"); - $this->assert_title("Image $image_id: test"); - $this->assert_text("Favorited By"); + $this->get_page("post/list/favorited_by=test/1"); + $this->assert_title("Image $image_id: test"); + $this->assert_text("Favorited By"); - $this->get_page("user/test"); - $this->assert_text("Images favorited: 1"); - $this->click("Images favorited"); - $this->assert_title("Image $image_id: test"); + $this->get_page("user/test"); + $this->assert_text("Images favorited: 1"); + $this->click("Images favorited"); + $this->assert_title("Image $image_id: test"); - $this->click("Un-Favorite"); - $this->assert_no_text("Favorited By"); - } + $this->click("Un-Favorite"); + $this->assert_no_text("Favorited By"); + } } - diff --git a/ext/favorites/theme.php b/ext/favorites/theme.php index ae502ab2..89509ce2 100644 --- a/ext/favorites/theme.php +++ b/ext/favorites/theme.php @@ -1,11 +1,13 @@ id); - $name = $is_favorited ? "unset" : "set"; - $label = $is_favorited ? "Un-Favorite" : "Favorite"; - $html = " +class FavoritesTheme extends Themelet +{ + public function get_voter_html(Image $image, $is_favorited) + { + $i_image_id = int_escape($image->id); + $name = $is_favorited ? "unset" : "set"; + $label = $is_favorited ? "Un-Favorite" : "Favorite"; + $html = " ".make_form(make_link("change_favorite"))." @@ -13,24 +15,23 @@ class FavoritesTheme extends Themelet { "; - return $html; - } + return $html; + } - public function display_people($username_array) { - global $page; + public function display_people($username_array) + { + global $page; - $i_favorites = count($username_array); - $html = "$i_favorites people:"; + $i_favorites = count($username_array); + $html = "$i_favorites people:"; - reset($username_array); // rewind to first element in array. - - foreach($username_array as $row) { - $username = html_escape($row); - $html .= "
    $username"; - } + reset($username_array); // rewind to first element in array. + + foreach ($username_array as $row) { + $username = html_escape($row); + $html .= "
    $username"; + } - $page->add_block(new Block("Favorited By", $html, "left", 25)); - } + $page->add_block(new Block("Favorited By", $html, "left", 25)); + } } - - diff --git a/ext/featured/main.php b/ext/featured/main.php index 59a3745a..c58be8b4 100644 --- a/ext/featured/main.php +++ b/ext/featured/main.php @@ -19,71 +19,75 @@ * every couple of hours. */ -class Featured extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int('featured_id', 0); - } +class Featured extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int('featured_id', 0); + } - public function onPageRequest(PageRequestEvent $event) { - global $config, $page, $user; - if($event->page_matches("featured_image")) { - if($event->get_arg(0) == "set" && $user->check_auth_token()) { - if($user->can("edit_feature") && isset($_POST['image_id'])) { - $id = int_escape($_POST['image_id']); - if($id > 0) { - $config->set_int("featured_id", $id); - log_info("featured", "Featured image set to $id", "Featured image set"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$id")); - } - } - } - if($event->get_arg(0) == "download") { - $image = Image::by_id($config->get_int("featured_id")); - if(!is_null($image)) { - $page->set_mode("data"); - $page->set_type($image->get_mime_type()); - $page->set_data(file_get_contents($image->get_image_filename())); - } - } - if($event->get_arg(0) == "view") { - $image = Image::by_id($config->get_int("featured_id")); - if(!is_null($image)) { - send_event(new DisplayingImageEvent($image)); - } - } - } - } + public function onPageRequest(PageRequestEvent $event) + { + global $config, $page, $user; + if ($event->page_matches("featured_image")) { + if ($event->get_arg(0) == "set" && $user->check_auth_token()) { + if ($user->can("edit_feature") && isset($_POST['image_id'])) { + $id = int_escape($_POST['image_id']); + if ($id > 0) { + $config->set_int("featured_id", $id); + log_info("featured", "Featured image set to $id", "Featured image set"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$id")); + } + } + } + if ($event->get_arg(0) == "download") { + $image = Image::by_id($config->get_int("featured_id")); + if (!is_null($image)) { + $page->set_mode("data"); + $page->set_type($image->get_mime_type()); + $page->set_data(file_get_contents($image->get_image_filename())); + } + } + if ($event->get_arg(0) == "view") { + $image = Image::by_id($config->get_int("featured_id")); + if (!is_null($image)) { + send_event(new DisplayingImageEvent($image)); + } + } + } + } - public function onPostListBuilding(PostListBuildingEvent $event) { - global $config, $database, $page, $user; - $fid = $config->get_int("featured_id"); - if($fid > 0) { - $image = $database->cache->get("featured_image_object:$fid"); - if($image === false) { - $image = Image::by_id($fid); - if($image) { // make sure the object is fully populated before saving - $image->get_tag_array(); - } - $database->cache->set("featured_image_object:$fid", $image, 600); - } - if(!is_null($image)) { - if(ext_is_live("Ratings")) { - if(strpos(Ratings::get_user_privs($user), $image->rating) === FALSE) { - return; - } - } - $this->theme->display_featured($page, $image); - } - } - } + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $config, $database, $page, $user; + $fid = $config->get_int("featured_id"); + if ($fid > 0) { + $image = $database->cache->get("featured_image_object:$fid"); + if ($image === false) { + $image = Image::by_id($fid); + if ($image) { // make sure the object is fully populated before saving + $image->get_tag_array(); + } + $database->cache->set("featured_image_object:$fid", $image, 600); + } + if (!is_null($image)) { + if (ext_is_live("Ratings")) { + if (strpos(Ratings::get_user_privs($user), $image->rating) === false) { + return; + } + } + $this->theme->display_featured($page, $image); + } + } + } - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $user; - if($user->can("edit_feature")) { - $event->add_part($this->theme->get_buttons_html($event->image->id)); - } - } + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $user; + if ($user->can("edit_feature")) { + $event->add_part($this->theme->get_buttons_html($event->image->id)); + } + } } - diff --git a/ext/featured/test.php b/ext/featured/test.php index 74aa5678..45800e3b 100644 --- a/ext/featured/test.php +++ b/ext/featured/test.php @@ -1,35 +1,36 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); +class FeaturedTest extends ShimmiePHPUnitTestCase +{ + public function testFeatured() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - # FIXME: test that regular users can't feature things + # FIXME: test that regular users can't feature things - $this->log_in_as_admin(); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pbx"); + $this->log_in_as_admin(); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pbx"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->click("Feature This"); - $this->get_page("post/list"); - $this->assert_text("Featured Image"); + $this->click("Feature This"); + $this->get_page("post/list"); + $this->assert_text("Featured Image"); - # FIXME: test changing from one feature to another + # FIXME: test changing from one feature to another - $this->get_page("featured_image/download"); - $this->assert_response(200); + $this->get_page("featured_image/download"); + $this->assert_response(200); - $this->get_page("featured_image/view"); - $this->assert_response(200); + $this->get_page("featured_image/view"); + $this->assert_response(200); - $this->delete_image($image_id); - $this->log_out(); + $this->delete_image($image_id); + $this->log_out(); - # after deletion, there should be no feature - $this->get_page("post/list"); - $this->assert_no_text("Featured Image"); - } + # after deletion, there should be no feature + $this->get_page("post/list"); + $this->assert_no_text("Featured Image"); + } } - diff --git a/ext/featured/theme.php b/ext/featured/theme.php index 1017fd34..b601a6b7 100644 --- a/ext/featured/theme.php +++ b/ext/featured/theme.php @@ -1,33 +1,36 @@ add_block(new Block("Featured Image", $this->build_featured_html($image), "left", 3)); - } +class FeaturedTheme extends Themelet +{ + public function display_featured(Page $page, Image $image): void + { + $page->add_block(new Block("Featured Image", $this->build_featured_html($image), "left", 3)); + } - public function get_buttons_html(int $image_id): string { - global $user; - return " + public function get_buttons_html(int $image_id): string + { + global $user; + return " ".make_form(make_link("featured_image/set"))." ".$user->get_auth_html()." "; - } + } - public function build_featured_html(Image $image, ?string $query=null): string { - $i_id = int_escape($image->id); - $h_view_link = make_link("post/view/$i_id", $query); - $h_thumb_link = $image->get_thumb_link(); - $h_tip = html_escape($image->get_tooltip()); - $tsize = get_thumbnail_size($image->width, $image->height); + public function build_featured_html(Image $image, ?string $query=null): string + { + $i_id = int_escape($image->id); + $h_view_link = make_link("post/view/$i_id", $query); + $h_thumb_link = $image->get_thumb_link(); + $h_tip = html_escape($image->get_tooltip()); + $tsize = get_thumbnail_size($image->width, $image->height); - return " + return " {$h_tip} "; - } + } } - diff --git a/ext/forum/main.php b/ext/forum/main.php index ab235b9a..95d79908 100644 --- a/ext/forum/main.php +++ b/ext/forum/main.php @@ -15,14 +15,16 @@ Todo: *Smiley filter, word filter, etc should work with our extension */ -class Forum extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; +class Forum extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - // shortcut to latest + // shortcut to latest - if ($config->get_int("forum_version") < 1) { - $database->create_table("forum_threads", " + if ($config->get_int("forum_version") < 1) { + $database->create_table("forum_threads", " id SCORE_AIPK, sticky SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, title VARCHAR(255) NOT NULL, @@ -31,9 +33,9 @@ class Forum extends Extension { uptodate SCORE_DATETIME NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT "); - $database->execute("CREATE INDEX forum_threads_date_idx ON forum_threads(date)", array()); - - $database->create_table("forum_posts", " + $database->execute("CREATE INDEX forum_threads_date_idx ON forum_threads(date)", []); + + $database->create_table("forum_posts", " id SCORE_AIPK, thread_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -42,367 +44,362 @@ class Forum extends Extension { FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT, FOREIGN KEY (thread_id) REFERENCES forum_threads (id) ON UPDATE CASCADE ON DELETE CASCADE "); - $database->execute("CREATE INDEX forum_posts_date_idx ON forum_posts(date)", array()); + $database->execute("CREATE INDEX forum_posts_date_idx ON forum_posts(date)", []); - $config->set_int("forum_version", 2); - $config->set_int("forumTitleSubString", 25); - $config->set_int("forumThreadsPerPage", 15); - $config->set_int("forumPostsPerPage", 15); + $config->set_int("forum_version", 2); + $config->set_int("forumTitleSubString", 25); + $config->set_int("forumThreadsPerPage", 15); + $config->set_int("forumPostsPerPage", 15); - $config->set_int("forumMaxCharsPerPost", 512); + $config->set_int("forumMaxCharsPerPost", 512); - log_info("forum", "extension installed"); - } - if ($config->get_int("forum_version") < 2) { - $database->execute("ALTER TABLE forum_threads ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT"); - $database->execute("ALTER TABLE forum_posts ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT"); - $config->set_int("forum_version", 2); - } - } - - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Forum"); - $sb->add_int_option("forumTitleSubString", "Title max long: "); - $sb->add_int_option("forumThreadsPerPage", "
    Threads per page: "); - $sb->add_int_option("forumPostsPerPage", "
    Posts per page: "); - - $sb->add_int_option("forumMaxCharsPerPost", "
    Max chars per post: "); - $event->panel->add_block($sb); - } - - public function onUserPageBuilding(UserPageBuildingEvent $event) { - global $database; - - $threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=?", array($event->display_user->id)); - $posts_count = $database->get_one("SELECT COUNT(*) FROM forum_posts WHERE user_id=?", array($event->display_user->id)); - + log_info("forum", "extension installed"); + } + if ($config->get_int("forum_version") < 2) { + $database->execute("ALTER TABLE forum_threads ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT"); + $database->execute("ALTER TABLE forum_posts ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT"); + $config->set_int("forum_version", 2); + } + } + + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Forum"); + $sb->add_int_option("forumTitleSubString", "Title max long: "); + $sb->add_int_option("forumThreadsPerPage", "
    Threads per page: "); + $sb->add_int_option("forumPostsPerPage", "
    Posts per page: "); + + $sb->add_int_option("forumMaxCharsPerPost", "
    Max chars per post: "); + $event->panel->add_block($sb); + } + + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + global $database; + + $threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=?", [$event->display_user->id]); + $posts_count = $database->get_one("SELECT COUNT(*) FROM forum_posts WHERE user_id=?", [$event->display_user->id]); + $days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; - + $threads_rate = sprintf("%.1f", ($threads_count / $days_old)); - $posts_rate = sprintf("%.1f", ($posts_count / $days_old)); - - $event->add_stats("Forum threads: $threads_count, $threads_rate per day"); + $posts_rate = sprintf("%.1f", ($posts_count / $days_old)); + + $event->add_stats("Forum threads: $threads_count, $threads_rate per day"); $event->add_stats("Forum posts: $posts_count, $posts_rate per day"); - } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; + 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); + 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; - } + 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->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; - } + 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; - } - } - } + 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)); + 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 = ?", [$threadID]); - return ceil($result["count"] / $config->get_int("forumPostsPerPage")); - } + return ceil($result["count"] / $config->get_int("forumPostsPerPage")); + } - private function sanity_check_new_thread() - { - $errors = null; - if (!array_key_exists("title", $_POST)) - { - $errors .= "
    No title supplied.
    "; - } - else if (strlen($_POST["title"]) == 0) - { - $errors .= "
    You cannot have an empty title.
    "; - } - else if (strlen(html_escape($_POST["title"])) > 255) - { - $errors .= "
    Your title is too long.
    "; - } + private function sanity_check_new_thread() + { + $errors = null; + if (!array_key_exists("title", $_POST)) { + $errors .= "
    No title supplied.
    "; + } elseif (strlen($_POST["title"]) == 0) { + $errors .= "
    You cannot have an empty title.
    "; + } elseif (strlen(html_escape($_POST["title"])) > 255) { + $errors .= "
    Your title is too long.
    "; + } - if (!array_key_exists("message", $_POST)) - { - $errors .= "
    No message supplied.
    "; - } - else if (strlen($_POST["message"]) == 0) - { - $errors .= "
    You cannot have an empty message.
    "; - } + if (!array_key_exists("message", $_POST)) { + $errors .= "
    No message supplied.
    "; + } elseif (strlen($_POST["message"]) == 0) { + $errors .= "
    You cannot have an empty message.
    "; + } - return array($errors); - } + return [$errors]; + } - private function sanity_check_new_post() - { - $errors = null; - if (!array_key_exists("threadID", $_POST)) - { - $errors = "
    No thread ID supplied.
    "; - } - else if (strlen($_POST["threadID"]) == 0) - { - $errors = "
    No thread ID supplied.
    "; - } - else if (is_numeric($_POST["threadID"])) + private function sanity_check_new_post() + { + $errors = null; + if (!array_key_exists("threadID", $_POST)) { + $errors = "
    No thread ID supplied.
    "; + } elseif (strlen($_POST["threadID"]) == 0) { + $errors = "
    No thread ID supplied.
    "; + } elseif (is_numeric($_POST["threadID"])) { + if (!array_key_exists("message", $_POST)) { + $errors .= "
    No message supplied.
    "; + } elseif (strlen($_POST["message"]) == 0) { + $errors .= "
    You cannot have an empty message.
    "; + } + } - if (!array_key_exists("message", $_POST)) - { - $errors .= "
    No message supplied.
    "; - } - else if (strlen($_POST["message"]) == 0) - { - $errors .= "
    You cannot have an empty message.
    "; - } + return [$errors]; + } - return array($errors); - } + private function sanity_check_viewed_thread(int $threadID) + { + $errors = null; + if (!$this->threadExists($threadID)) { + $errors = "
    Inexistent thread.
    "; + } + return [$errors]; + } - private function sanity_check_viewed_thread(int $threadID) - { - $errors = null; - if (!$this->threadExists($threadID)) - { - $errors = "
    Inexistent thread.
    "; - } - return array($errors); - } + private function get_thread_title(int $threadID) + { + global $database; + $result = $database->get_row("SELECT t.title FROM forum_threads AS t WHERE t.id = ? ", [$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); - private function get_thread_title(int $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; + } elseif ($pageNumber <= 0) { + $pageNumber = 0; + } elseif ($pageNumber >= $totalPages) { + $pageNumber = $totalPages - 1; + } else { + $pageNumber--; + } - 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", + ["limit"=>$threadsPerPage, "offset"=>$pageNumber * $threadsPerPage] + ); - $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); + } - $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 = ?", [$threadID]) / $postsPerPage); + $threadTitle = $this->get_thread_title($threadID); - 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; + } elseif ($pageNumber <= 0) { + $pageNumber = 0; + } elseif ($pageNumber >= $totalPages) { + $pageNumber = $totalPages - 1; + } else { + $pageNumber--; + } - 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", + ["thread_id"=>$threadID, "offset"=>$pageNumber * $postsPerPage, "limit"=>$postsPerPage] + ); + $this->theme->display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber + 1, $totalPages); + } - $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"; - 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"; + } - if($sticky == ""){ - $sticky = "N"; - } - - global $database; - $database->execute(" + global $database; + $database->execute( + " INSERT INTO forum_threads (title, sticky, user_id, date, uptodate) VALUES (?, ?, ?, now(), now())", - array($title, $sticky, $user->id)); + [$title, $sticky, $user->id] + ); - $threadID = $database->get_last_insert_id("forum_threads_id_seq"); + $threadID = $database->get_last_insert_id("forum_threads_id_seq"); - log_info("forum", "Thread {$threadID} created by {$user->name}"); + log_info("forum", "Thread {$threadID} created by {$user->name}"); - return $threadID; - } + return $threadID; + } - private function save_new_post(int $threadID, User $user) - { - global $config; - $userID = $user->id; - $message = html_escape($_POST["message"]); + private function save_new_post(int $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); + $max_characters = $config->get_int('forumMaxCharsPerPost'); + $message = substr($message, 0, $max_characters); - global $database; - $database->execute("INSERT INTO forum_posts + global $database; + $database->execute("INSERT INTO forum_posts (thread_id, user_id, date, message) VALUES - (?, ?, now(), ?)" - , array($threadID, $userID, $message)); + (?, ?, now(), ?)", [$threadID, $userID, $message]); - $postID = $database->get_last_insert_id("forum_posts_id_seq"); + $postID = $database->get_last_insert_id("forum_posts_id_seq"); - log_info("forum", "Post {$postID} created by {$user->name}"); + log_info("forum", "Post {$postID} created by {$user->name}"); - $database->execute("UPDATE forum_threads SET uptodate=now() WHERE id=?", array ($threadID)); - } + $database->execute("UPDATE forum_threads SET uptodate=now() WHERE id=?", [$threadID]); + } - private function retrieve_posts(int $threadID, int $pageNumber) - { - global $database, $config; - $postsPerPage = $config->get_int('forumPostsPerPage', 15); + private function retrieve_posts(int $threadID, int $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)); - } + 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 ", + ["thread_id"=>$threadID, "offset"=>($pageNumber - 1) * $postsPerPage, "limit"=>$postsPerPage] + ); + } - private function delete_thread(int $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_thread(int $threadID) + { + global $database; + $database->execute("DELETE FROM forum_threads WHERE id = ?", [$threadID]); + $database->execute("DELETE FROM forum_posts WHERE thread_id = ?", [$threadID]); + } - private function delete_post(int $postID) - { - global $database; - $database->execute("DELETE FROM forum_posts WHERE id = ?", array($postID)); - } + private function delete_post(int $postID) + { + global $database; + $database->execute("DELETE FROM forum_posts WHERE id = ?", [$postID]); + } - private function threadExists(int $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; - } - } + private function threadExists(int $threadID) + { + global $database; + $result=$database->get_one("SELECT EXISTS (SELECT * FROM forum_threads WHERE id= ?)", [$threadID]); + if ($result==1) { + return true; + } else { + return false; + } + } } diff --git a/ext/forum/theme.php b/ext/forum/theme.php index 74d7c5df..de72e63e 100644 --- a/ext/forum/theme.php +++ b/ext/forum/theme.php @@ -1,17 +1,18 @@ make_thread_list($threads, $showAdminOptions); + } - $page->set_title(html_escape("Forum")); - $page->set_heading(html_escape("Forum")); + $page->set_title(html_escape("Forum")); + $page->set_heading(html_escape("Forum")); $page->add_block(new Block("Forum", $html, "main", 10)); - + $this->display_paginator($page, "forum/index", null, $pageNumber, $totalPages); } @@ -19,55 +20,57 @@ class ForumTheme extends Themelet { public function display_new_thread_composer(Page $page, $threadText = null, $threadTitle = null) { - global $config, $user; - $max_characters = $config->get_int('forumMaxCharsPerPost'); - $html = make_form(make_link("forum/create")); + global $config, $user; + $max_characters = $config->get_int('forumMaxCharsPerPost'); + $html = make_form(make_link("forum/create")); - if (!is_null($threadTitle)) - $threadTitle = html_escape($threadTitle); + if (!is_null($threadTitle)) { + $threadTitle = html_escape($threadTitle); + } - if(!is_null($threadText)) - $threadText = html_escape($threadText); - - $html .= " + if (!is_null($threadText)) { + $threadText = html_escape($threadText); + } + + $html .= " "; - if($user->is_admin()){ - $html .= ""; - } - $html .= " + if ($user->is_admin()) { + $html .= ""; + } + $html .= "
    Title:
    Message:
    Max characters alowed: $max_characters.
    "; $blockTitle = "Write a new thread"; - $page->set_title(html_escape($blockTitle)); - $page->set_heading(html_escape($blockTitle)); + $page->set_title(html_escape($blockTitle)); + $page->set_heading(html_escape($blockTitle)); $page->add_block(new Block($blockTitle, $html, "main", 120)); } - - - + + + public function display_new_post_composer(Page $page, $threadID) { - global $config; - - $max_characters = $config->get_int('forumMaxCharsPerPost'); - - $html = make_form(make_link("forum/answer")); + global $config; + + $max_characters = $config->get_int('forumMaxCharsPerPost'); + + $html = make_form(make_link("forum/answer")); $html .= ''; - - $html .= " + + $html .= " "; - - $html .= " + + $html .= "
    Message:
    Max characters alowed: $max_characters.
    "; @@ -78,60 +81,59 @@ class ForumTheme extends Themelet { - public function display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber, $totalPages) + public function display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber, $totalPages) { - global $config, $page/*, $user*/; - - $posts_per_page = $config->get_int('forumPostsPerPage'); - + global $config, $page/*, $user*/; + + $posts_per_page = $config->get_int('forumPostsPerPage'); + $current_post = 0; $html = - "

    ". - "". - "". + "

    ". + "
    ". + "". "". "". - ""; - - foreach ($posts as $post) - { - $current_post++; + ""; + + foreach ($posts as $post) { + $current_post++; $message = $post["message"]; $tfe = new TextFormattingEvent($message); send_event($tfe); $message = $tfe->formatted; - - $message = str_replace('\n\r', '
    ', $message); + + $message = str_replace('\n\r', '
    ', $message); $message = str_replace('\r\n', '
    ', $message); $message = str_replace('\n', '
    ', $message); $message = str_replace('\r', '
    ', $message); - - $message = stripslashes($message); - + + $message = stripslashes($message); + $user = "".$post["user_name"].""; $poster = User::by_name($post["user_name"]); - $gravatar = $poster->get_avatar_html(); + $gravatar = $poster->get_avatar_html(); - $rank = "{$post["user_class"]}"; - - $postID = $post['id']; - - //if($user->is_admin()){ - //$delete_link = "Delete"; - //} else { - //$delete_link = ""; - //} - - if($showAdminOptions){ - $delete_link = "Delete"; - }else{ - $delete_link = ""; - } + $rank = "{$post["user_class"]}"; + + $postID = $post['id']; + + //if($user->is_admin()){ + //$delete_link = "Delete"; + //} else { + //$delete_link = ""; + //} + + if ($showAdminOptions) { + $delete_link = "Delete"; + } else { + $delete_link = ""; + } - $post_number = (($pageNumber-1)*$posts_per_page)+$current_post; + $post_number = (($pageNumber-1)*$posts_per_page)+$current_post; $html .= " @@ -149,20 +151,18 @@ class ForumTheme extends Themelet { "; - } - + $html .= "
    UserMessage
    "; $this->display_paginator($page, "forum/view/".$threadID, null, $pageNumber, $totalPages); - $page->set_title(html_escape($threadTitle)); - $page->set_heading(html_escape($threadTitle)); + $page->set_title(html_escape($threadTitle)); + $page->set_heading(html_escape($threadTitle)); $page->add_block(new Block($threadTitle, $html, "main", 20)); - } - - + + public function add_actions_block(Page $page, $threadID) { @@ -179,11 +179,10 @@ class ForumTheme extends Themelet { "". "Title". "Author". - "Updated". + "Updated". "Responses"; - if($showAdminOptions) - { + if ($showAdminOptions) { $html .= "Actions"; } @@ -191,35 +190,34 @@ class ForumTheme extends Themelet { $current_post = 0; - foreach($threads as $thread) - { + foreach ($threads as $thread) { $oe = ($current_post++ % 2 == 0) ? "even" : "odd"; - - global $config; - $titleSubString = $config->get_int('forumTitleSubString'); - - if ($titleSubString < strlen($thread["title"])) - { - $title = substr($thread["title"], 0, $titleSubString); - $title = $title."..."; - } else { - $title = $thread["title"]; - } - - if($thread["sticky"] == "Y"){ - $sticky = "Sticky: "; - } else { - $sticky = ""; - } + + global $config; + $titleSubString = $config->get_int('forumTitleSubString'); + + if ($titleSubString < strlen($thread["title"])) { + $title = substr($thread["title"], 0, $titleSubString); + $title = $title."..."; + } else { + $title = $thread["title"]; + } + + if ($thread["sticky"] == "Y") { + $sticky = "Sticky: "; + } else { + $sticky = ""; + } $html .= "". ''.$sticky.''.$title."". - ''.$thread["user_name"]."". - "".autodate($thread["uptodate"])."". + ''.$thread["user_name"]."". + "".autodate($thread["uptodate"])."". "".$thread["response_count"].""; - if ($showAdminOptions) + if ($showAdminOptions) { $html .= 'Delete'; + } $html .= ""; } @@ -229,4 +227,3 @@ class ForumTheme extends Themelet { return $html; } } - diff --git a/ext/google_analytics/main.php b/ext/google_analytics/main.php index 3f0f8608..892e4890 100644 --- a/ext/google_analytics/main.php +++ b/ext/google_analytics/main.php @@ -8,22 +8,25 @@ * Documentation: * User has to enter their Google Analytics ID in the Board Config to use this extention. */ -class google_analytics extends Extension { - # Add analytics to config - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Google Analytics"); - $sb->add_text_option("google_analytics_id", "Analytics ID: "); - $sb->add_label("
    (eg. UA-xxxxxxxx-x)"); - $event->panel->add_block($sb); - } +class google_analytics extends Extension +{ + # Add analytics to config + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Google Analytics"); + $sb->add_text_option("google_analytics_id", "Analytics ID: "); + $sb->add_label("
    (eg. UA-xxxxxxxx-x)"); + $event->panel->add_block($sb); + } - # Load Analytics tracking code on page request - public function onPageRequest(PageRequestEvent $event) { - global $config, $page; + # Load Analytics tracking code on page request + public function onPageRequest(PageRequestEvent $event) + { + global $config, $page; - $google_analytics_id = $config->get_string('google_analytics_id',''); - if (stristr($google_analytics_id, "UA-")) { - $page->add_html_header(""); - } } + } } - diff --git a/ext/handle_404/main.php b/ext/handle_404/main.php index 5da9dfc2..4bc31dfd 100644 --- a/ext/handle_404/main.php +++ b/ext/handle_404/main.php @@ -8,29 +8,36 @@ * Description: If no other extension puts anything onto the page, show 404 */ -class Handle404 extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $config, $page; - // hax. - if($page->mode == "page" && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) { - $h_pagename = html_escape(implode('/', $event->args)); - log_debug("handle_404", "Hit 404: $h_pagename"); - $page->set_code(404); - $page->set_title("404"); - $page->set_heading("404 - No Handler Found"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Explanation", "No handler could be found for the page '$h_pagename'")); - } - } +class Handle404 extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $config, $page; + // hax. + if ($page->mode == "page" && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) { + $h_pagename = html_escape(implode('/', $event->args)); + log_debug("handle_404", "Hit 404: $h_pagename"); + $page->set_code(404); + $page->set_title("404"); + $page->set_heading("404 - No Handler Found"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Explanation", "No handler could be found for the page '$h_pagename'")); + } + } - private function count_main($blocks) { - $n = 0; - foreach($blocks as $block) { - if($block->section == "main" && $block->is_content) $n++; // more hax. - } - return $n; - } + private function count_main($blocks) + { + $n = 0; + foreach ($blocks as $block) { + if ($block->section == "main" && $block->is_content) { + $n++; + } // more hax. + } + return $n; + } - public function get_priority(): int {return 99;} + public function get_priority(): int + { + return 99; + } } - diff --git a/ext/handle_404/test.php b/ext/handle_404/test.php index f02548a9..e8bb27be 100644 --- a/ext/handle_404/test.php +++ b/ext/handle_404/test.php @@ -1,11 +1,12 @@ get_page('not/a/page'); - // most descriptive error first - $this->assert_text("No handler could be found for the page 'not/a/page'"); - $this->assert_title('404'); - $this->assert_response(404); - } +class Handle404Test extends ShimmiePHPUnitTestCase +{ + public function test404Handler() + { + $this->get_page('not/a/page'); + // most descriptive error first + $this->assert_text("No handler could be found for the page 'not/a/page'"); + $this->assert_title('404'); + $this->assert_response(404); + } } - diff --git a/ext/handle_archive/main.php b/ext/handle_archive/main.php index 346f062e..1da522e0 100644 --- a/ext/handle_archive/main.php +++ b/ext/handle_archive/main.php @@ -10,43 +10,48 @@ *
    7-zip: 7zr x -o"%d" "%f" */ -class ArchiveFileHandler extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string('archive_extract_command', 'unzip -d "%d" "%f"'); - } +class ArchiveFileHandler extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string('archive_extract_command', 'unzip -d "%d" "%f"'); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Archive Handler Options"); - $sb->add_text_option("archive_tmp_dir", "Temporary folder: "); - $sb->add_text_option("archive_extract_command", "
    Extraction command: "); - $sb->add_label("
    %f for archive, %d for temporary directory"); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Archive Handler Options"); + $sb->add_text_option("archive_tmp_dir", "Temporary folder: "); + $sb->add_text_option("archive_extract_command", "
    Extraction command: "); + $sb->add_label("
    %f for archive, %d for temporary directory"); + $event->panel->add_block($sb); + } - public function onDataUpload(DataUploadEvent $event) { - if($this->supported_ext($event->type)) { - global $config; - $tmp = sys_get_temp_dir(); - $tmpdir = "$tmp/shimmie-archive-{$event->hash}"; - $cmd = $config->get_string('archive_extract_command'); - $cmd = str_replace('%f', $event->tmpname, $cmd); - $cmd = str_replace('%d', $tmpdir, $cmd); - exec($cmd); - $results = add_dir($tmpdir); - if(count($results) > 0) { - // Not all themes have the add_status() method, so need to check before calling. - if (method_exists($this->theme, "add_status")) { - $this->theme->add_status("Adding files", $results); - } - } - deltree($tmpdir); - $event->image_id = -2; // default -1 = upload wasn't handled - } - } + public function onDataUpload(DataUploadEvent $event) + { + if ($this->supported_ext($event->type)) { + global $config; + $tmp = sys_get_temp_dir(); + $tmpdir = "$tmp/shimmie-archive-{$event->hash}"; + $cmd = $config->get_string('archive_extract_command'); + $cmd = str_replace('%f', $event->tmpname, $cmd); + $cmd = str_replace('%d', $tmpdir, $cmd); + exec($cmd); + $results = add_dir($tmpdir); + if (count($results) > 0) { + // Not all themes have the add_status() method, so need to check before calling. + if (method_exists($this->theme, "add_status")) { + $this->theme->add_status("Adding files", $results); + } + } + deltree($tmpdir); + $event->image_id = -2; // default -1 = upload wasn't handled + } + } - private function supported_ext($ext) { - $exts = array("zip"); - return in_array(strtolower($ext), $exts); - } + private function supported_ext($ext) + { + $exts = ["zip"]; + return in_array(strtolower($ext), $exts); + } } diff --git a/ext/handle_flash/main.php b/ext/handle_flash/main.php index 2e076739..c1ef4bdb 100644 --- a/ext/handle_flash/main.php +++ b/ext/handle_flash/main.php @@ -6,45 +6,55 @@ * Description: Handle Flash files. (No thumbnail is generated for flash files) */ -class FlashFileHandler extends DataHandlerExtension { - protected function create_thumb(string $hash): bool { - copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); - return true; - } +class FlashFileHandler extends DataHandlerExtension +{ + protected function create_thumb(string $hash): bool + { + copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); + return true; + } - protected function supported_ext(string $ext): bool { - $exts = array("swf"); - return in_array(strtolower($ext), $exts); - } + protected function supported_ext(string $ext): bool + { + $exts = ["swf"]; + return in_array(strtolower($ext), $exts); + } - protected function create_image_from_data(string $filename, array $metadata) { - $image = new Image(); + protected function create_image_from_data(string $filename, array $metadata) + { + $image = new Image(); - $image->filesize = $metadata['size']; - $image->hash = $metadata['hash']; - $image->filename = $metadata['filename']; - $image->ext = $metadata['extension']; - $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); - $image->source = $metadata['source']; + $image->filesize = $metadata['size']; + $image->hash = $metadata['hash']; + $image->filename = $metadata['filename']; + $image->ext = $metadata['extension']; + $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); + $image->source = $metadata['source']; - $info = getimagesize($filename); - if(!$info) return null; + $info = getimagesize($filename); + if (!$info) { + return null; + } - $image->width = $info[0]; - $image->height = $info[1]; + $image->width = $info[0]; + $image->height = $info[1]; - return $image; - } + return $image; + } - protected function check_contents(string $tmpname): bool { - if (!file_exists($tmpname)) return false; + protected function check_contents(string $tmpname): bool + { + if (!file_exists($tmpname)) { + return false; + } - $fp = fopen($tmpname, "r"); - $head = fread($fp, 3); - fclose($fp); - if (!in_array($head, array("CWS", "FWS"))) return false; + $fp = fopen($tmpname, "r"); + $head = fread($fp, 3); + fclose($fp); + if (!in_array($head, ["CWS", "FWS"])) { + return false; + } - return true; - } + return true; + } } - diff --git a/ext/handle_flash/theme.php b/ext/handle_flash/theme.php index e4557088..3d5683d1 100644 --- a/ext/handle_flash/theme.php +++ b/ext/handle_flash/theme.php @@ -1,10 +1,12 @@ get_image_link(); - // FIXME: object and embed have "height" and "width" - $html = " +class FlashFileHandlerTheme extends Themelet +{ + public function display_image(Page $page, Image $image) + { + $ilink = $image->get_image_link(); + // FIXME: object and embed have "height" and "width" + $html = " "; - $page->add_block(new Block("Flash Animation", $html, "main", 10)); - } + $page->add_block(new Block("Flash Animation", $html, "main", 10)); + } } - diff --git a/ext/handle_ico/main.php b/ext/handle_ico/main.php index 43d7e144..504b09e1 100644 --- a/ext/handle_ico/main.php +++ b/ext/handle_ico/main.php @@ -5,93 +5,101 @@ * Description: Handle windows icons */ -class IcoFileHandler extends Extension { - public function onDataUpload(DataUploadEvent $event) { - if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { - $hash = $event->hash; - $ha = substr($hash, 0, 2); - move_upload_to_archive($event); - send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); - $image = $this->create_image_from_data("images/$ha/$hash", $event->metadata); - if(is_null($image)) { - throw new UploadException("Icon handler failed to create image object from data"); - } - $iae = new ImageAdditionEvent($image); - send_event($iae); - $event->image_id = $iae->image->id; - } - } +class IcoFileHandler extends Extension +{ + public function onDataUpload(DataUploadEvent $event) + { + if ($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { + $hash = $event->hash; + $ha = substr($hash, 0, 2); + move_upload_to_archive($event); + send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); + $image = $this->create_image_from_data("images/$ha/$hash", $event->metadata); + if (is_null($image)) { + throw new UploadException("Icon handler failed to create image object from data"); + } + $iae = new ImageAdditionEvent($image); + send_event($iae); + $event->image_id = $iae->image->id; + } + } - public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { - if($this->supported_ext($event->type)) { - $this->create_thumb($event->hash); - } - } + public function onThumbnailGeneration(ThumbnailGenerationEvent $event) + { + if ($this->supported_ext($event->type)) { + $this->create_thumb($event->hash); + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $page; - if($this->supported_ext($event->image->ext)) { - $this->theme->display_image($page, $event->image); - } - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $page; + if ($this->supported_ext($event->image->ext)) { + $this->theme->display_image($page, $event->image); + } + } - private function supported_ext(string $ext): bool { - $exts = array("ico", "ani", "cur"); - return in_array(strtolower($ext), $exts); - } + private function supported_ext(string $ext): bool + { + $exts = ["ico", "ani", "cur"]; + return in_array(strtolower($ext), $exts); + } - private function create_image_from_data(string $filename, array $metadata) { - $image = new Image(); + private function create_image_from_data(string $filename, array $metadata) + { + $image = new Image(); - $fp = fopen($filename, "r"); - $header = unpack("Snull/Stype/Scount", fread($fp, 6)); + $fp = fopen($filename, "r"); + $header = unpack("Snull/Stype/Scount", fread($fp, 6)); - $subheader = unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", fread($fp, 16)); - fclose($fp); + $subheader = unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", fread($fp, 16)); + fclose($fp); - $width = $subheader['width']; - $height = $subheader['height']; - $image->width = $width == 0 ? 256 : $width; - $image->height = $height == 0 ? 256 : $height; + $width = $subheader['width']; + $height = $subheader['height']; + $image->width = $width == 0 ? 256 : $width; + $image->height = $height == 0 ? 256 : $height; - $image->filesize = $metadata['size']; - $image->hash = $metadata['hash']; - $image->filename = $metadata['filename']; - $image->ext = $metadata['extension']; - $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); - $image->source = $metadata['source']; + $image->filesize = $metadata['size']; + $image->hash = $metadata['hash']; + $image->filename = $metadata['filename']; + $image->ext = $metadata['extension']; + $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); + $image->source = $metadata['source']; - return $image; - } + return $image; + } - private function check_contents(string $file): bool { - if(!file_exists($file)) return false; - $fp = fopen($file, "r"); - $header = unpack("Snull/Stype/Scount", fread($fp, 6)); - fclose($fp); - return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1)); - } + private function check_contents(string $file): bool + { + if (!file_exists($file)) { + return false; + } + $fp = fopen($file, "r"); + $header = unpack("Snull/Stype/Scount", fread($fp, 6)); + fclose($fp); + return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1)); + } - private function create_thumb(string $hash): bool { - global $config; + private function create_thumb(string $hash): bool + { + global $config; - $inname = warehouse_path("images", $hash); - $outname = warehouse_path("thumbs", $hash); + $inname = warehouse_path("images", $hash); + $outname = warehouse_path("thumbs", $hash); - $w = $config->get_int("thumb_width"); - $h = $config->get_int("thumb_height"); - $q = $config->get_int("thumb_quality"); - $mem = $config->get_int("thumb_mem_limit") / 1024 / 1024; // IM takes memory in MB + $w = $config->get_int("thumb_width"); + $h = $config->get_int("thumb_height"); + $q = $config->get_int("thumb_quality"); + $mem = $config->get_int("thumb_mem_limit") / 1024 / 1024; // IM takes memory in MB - if($config->get_bool("ico_convert")) { - // "-limit memory $mem" broken? - exec("convert {$inname}[0] -geometry {$w}x{$h} -quality {$q} jpg:$outname"); - } - else { - copy($inname, $outname); - } + if ($config->get_bool("ico_convert")) { + // "-limit memory $mem" broken? + exec("convert {$inname}[0] -geometry {$w}x{$h} -quality {$q} jpg:$outname"); + } else { + copy($inname, $outname); + } - return true; - } + return true; + } } - diff --git a/ext/handle_ico/test.php b/ext/handle_ico/test.php index 2d6946eb..0d58666b 100644 --- a/ext/handle_ico/test.php +++ b/ext/handle_ico/test.php @@ -1,12 +1,13 @@ log_in_as_user(); - $image_id = $this->post_image("ext/handle_static/static/favicon.ico", "shimmie favicon"); - $this->get_page("post/view/$image_id"); // test for no crash +class IcoHandlerTest extends ShimmiePHPUnitTestCase +{ + public function testIcoHander() + { + $this->log_in_as_user(); + $image_id = $this->post_image("ext/handle_static/static/favicon.ico", "shimmie favicon"); + $this->get_page("post/view/$image_id"); // test for no crash - # FIXME: test that the thumb works - # FIXME: test that it gets displayed properly - } + # FIXME: test that the thumb works + # FIXME: test that it gets displayed properly + } } - diff --git a/ext/handle_ico/theme.php b/ext/handle_ico/theme.php index 36daa9c2..522512e0 100644 --- a/ext/handle_ico/theme.php +++ b/ext/handle_ico/theme.php @@ -1,13 +1,14 @@ get_image_link(); - $html = " +class IcoFileHandlerTheme extends Themelet +{ + public function display_image(Page $page, Image $image) + { + $ilink = $image->get_image_link(); + $html = " main image "; - $page->add_block(new Block("Image", $html, "main", 10)); - } + $page->add_block(new Block("Image", $html, "main", 10)); + } } - diff --git a/ext/handle_mp3/main.php b/ext/handle_mp3/main.php index 9d2c8f33..a3e3dc9c 100644 --- a/ext/handle_mp3/main.php +++ b/ext/handle_mp3/main.php @@ -5,46 +5,51 @@ * Description: Handle MP3 files */ -class MP3FileHandler extends DataHandlerExtension { - protected function create_thumb(string $hash): bool { - copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash)); - return true; - } +class MP3FileHandler extends DataHandlerExtension +{ + protected function create_thumb(string $hash): bool + { + copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash)); + return true; + } - protected function supported_ext(string $ext): bool { - $exts = array("mp3"); - return in_array(strtolower($ext), $exts); - } + protected function supported_ext(string $ext): bool + { + $exts = ["mp3"]; + return in_array(strtolower($ext), $exts); + } - protected function create_image_from_data(string $filename, array $metadata) { - $image = new Image(); + protected function create_image_from_data(string $filename, array $metadata) + { + $image = new Image(); - //NOTE: No need to set width/height as we don't use it. - $image->width = 1; - $image->height = 1; + //NOTE: No need to set width/height as we don't use it. + $image->width = 1; + $image->height = 1; - $image->filesize = $metadata['size']; - $image->hash = $metadata['hash']; + $image->filesize = $metadata['size']; + $image->hash = $metadata['hash']; - //Filename is renamed to "artist - title.mp3" when the user requests download by using the download attribute & jsmediatags.js - $image->filename = $metadata['filename']; + //Filename is renamed to "artist - title.mp3" when the user requests download by using the download attribute & jsmediatags.js + $image->filename = $metadata['filename']; - $image->ext = $metadata['extension']; - $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); - $image->source = $metadata['source']; + $image->ext = $metadata['extension']; + $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); + $image->source = $metadata['source']; - return $image; - } + return $image; + } - protected function check_contents(string $tmpname): bool { - $success = FALSE; + protected function check_contents(string $tmpname): bool + { + $success = false; - if (file_exists($tmpname)) { - $mimeType = getMimeType($tmpname); + if (file_exists($tmpname)) { + $mimeType = getMimeType($tmpname); - $success = ($mimeType == 'audio/mpeg'); - } + $success = ($mimeType == 'audio/mpeg'); + } - return $success; - } + return $success; + } } diff --git a/ext/handle_mp3/theme.php b/ext/handle_mp3/theme.php index 95868018..0b382b74 100644 --- a/ext/handle_mp3/theme.php +++ b/ext/handle_mp3/theme.php @@ -1,11 +1,13 @@ get_image_link(); - $fname = url_escape($image->filename); //Most of the time this will be the title/artist of the song. - $html = " +class MP3FileHandlerTheme extends Themelet +{ + public function display_image(Page $page, Image $image) + { + $data_href = get_base_href(); + $ilink = $image->get_image_link(); + $fname = url_escape($image->filename); //Most of the time this will be the title/artist of the song. + $html = "
    "; - } + } } - diff --git a/ext/image/main.php b/ext/image/main.php index 5801b4f3..116ae5db 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -12,190 +12,193 @@ /** * A class to handle adding / getting / removing image files from the disk. */ -class ImageIO extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int('thumb_width', 192); - $config->set_default_int('thumb_height', 192); - $config->set_default_int('thumb_quality', 75); - $config->set_default_int('thumb_mem_limit', parse_shorthand_int('8MB')); - $config->set_default_string('thumb_convert_path', 'convert'); +class ImageIO extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int('thumb_width', 192); + $config->set_default_int('thumb_height', 192); + $config->set_default_int('thumb_quality', 75); + $config->set_default_int('thumb_mem_limit', parse_shorthand_int('8MB')); + $config->set_default_string('thumb_convert_path', 'convert'); - if(function_exists("exif_read_data")) { - $config->set_default_bool('image_show_meta', false); - } - $config->set_default_string('image_ilink', ''); - $config->set_default_string('image_tlink', ''); - $config->set_default_string('image_tip', '$tags // $size // $filesize'); - $config->set_default_string('upload_collision_handler', 'error'); - $config->set_default_int('image_expires', (60*60*24*31) ); // defaults to one month - } + if (function_exists("exif_read_data")) { + $config->set_default_bool('image_show_meta', false); + } + $config->set_default_string('image_ilink', ''); + $config->set_default_string('image_tlink', ''); + $config->set_default_string('image_tip', '$tags // $size // $filesize'); + $config->set_default_string('upload_collision_handler', 'error'); + $config->set_default_int('image_expires', (60*60*24*31)); // defaults to one month + } - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("image/delete")) { - global $page, $user; - if($user->can("delete_image") && isset($_POST['image_id']) && $user->check_auth_token()) { - $image = Image::by_id($_POST['image_id']); - if($image) { - send_event(new ImageDeletionEvent($image)); - $page->set_mode("redirect"); - if(isset($_SERVER['HTTP_REFERER']) && !strstr($_SERVER['HTTP_REFERER'], 'post/view')) { - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - else { - $page->set_redirect(make_link("post/list")); - } - } - } - } - else if($event->page_matches("image/replace")) { - global $page, $user; - if($user->can("replace_image") && isset($_POST['image_id']) && $user->check_auth_token()) { - $image = Image::by_id($_POST['image_id']); - if($image) { - $page->set_mode("redirect"); - $page->set_redirect(make_link('upload/replace/'.$image->id)); - } else { - /* Invalid image ID */ - throw new ImageReplaceException("Image to replace does not exist."); - } - } - } - else if($event->page_matches("image")) { - $num = int_escape($event->get_arg(0)); - $this->send_file($num, "image"); - } - else if($event->page_matches("thumb")) { - $num = int_escape($event->get_arg(0)); - $this->send_file($num, "thumb"); - } - } + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("image/delete")) { + global $page, $user; + if ($user->can("delete_image") && isset($_POST['image_id']) && $user->check_auth_token()) { + $image = Image::by_id($_POST['image_id']); + if ($image) { + send_event(new ImageDeletionEvent($image)); + $page->set_mode("redirect"); + if (isset($_SERVER['HTTP_REFERER']) && !strstr($_SERVER['HTTP_REFERER'], 'post/view')) { + $page->set_redirect($_SERVER['HTTP_REFERER']); + } else { + $page->set_redirect(make_link("post/list")); + } + } + } + } elseif ($event->page_matches("image/replace")) { + global $page, $user; + if ($user->can("replace_image") && isset($_POST['image_id']) && $user->check_auth_token()) { + $image = Image::by_id($_POST['image_id']); + if ($image) { + $page->set_mode("redirect"); + $page->set_redirect(make_link('upload/replace/'.$image->id)); + } else { + /* Invalid image ID */ + throw new ImageReplaceException("Image to replace does not exist."); + } + } + } elseif ($event->page_matches("image")) { + $num = int_escape($event->get_arg(0)); + $this->send_file($num, "image"); + } elseif ($event->page_matches("thumb")) { + $num = int_escape($event->get_arg(0)); + $this->send_file($num, "thumb"); + } + } - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $user; - - if($user->can("delete_image")) { - $event->add_part($this->theme->get_deleter_html($event->image->id)); - } - /* In the future, could perhaps allow users to replace images that they own as well... */ - if ($user->can("replace_image")) { - $event->add_part($this->theme->get_replace_html($event->image->id)); - } - } + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $user; + + if ($user->can("delete_image")) { + $event->add_part($this->theme->get_deleter_html($event->image->id)); + } + /* In the future, could perhaps allow users to replace images that they own as well... */ + if ($user->can("replace_image")) { + $event->add_part($this->theme->get_replace_html($event->image->id)); + } + } - public function onImageAddition(ImageAdditionEvent $event) { - try { - $this->add_image($event->image); - } - catch(ImageAdditionException $e) { - throw new UploadException($e->error); - } - } + public function onImageAddition(ImageAdditionEvent $event) + { + try { + $this->add_image($event->image); + } catch (ImageAdditionException $e) { + throw new UploadException($e->error); + } + } - public function onImageDeletion(ImageDeletionEvent $event) { - $event->image->delete(); - } + public function onImageDeletion(ImageDeletionEvent $event) + { + $event->image->delete(); + } - public function onImageReplace(ImageReplaceEvent $event) { - try { - $this->replace_image($event->id, $event->image); - } - catch(ImageReplaceException $e) { - throw new UploadException($e->error); - } - } - - public function onUserPageBuilding(UserPageBuildingEvent $event) { - $u_id = url_escape($event->display_user->id); - $i_image_count = Image::count_images(array("user_id={$event->display_user->id}")); - $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; - $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); - $images_link = make_link("post/list/user_id=$u_id/1"); - $event->add_stats("Images uploaded: $i_image_count, $h_image_rate per day"); - } + public function onImageReplace(ImageReplaceEvent $event) + { + try { + $this->replace_image($event->id, $event->image); + } catch (ImageReplaceException $e) { + throw new UploadException($e->error); + } + } + + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + $u_id = url_escape($event->display_user->id); + $i_image_count = Image::count_images(["user_id={$event->display_user->id}"]); + $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; + $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); + $images_link = make_link("post/list/user_id=$u_id/1"); + $event->add_stats("Images uploaded: $i_image_count, $h_image_rate per day"); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - global $config; + public function onSetupBuilding(SetupBuildingEvent $event) + { + global $config; - $sb = new SetupBlock("Image Options"); - $sb->position = 30; - // advanced only - //$sb->add_text_option("image_ilink", "Image link: "); - //$sb->add_text_option("image_tlink", "
    Thumbnail link: "); - $sb->add_text_option("image_tip", "Image tooltip: "); - $sb->add_choice_option("upload_collision_handler", array('Error'=>'error', 'Merge'=>'merge'), "
    Upload collision handler: "); - if(function_exists("exif_read_data")) { - $sb->add_bool_option("image_show_meta", "
    Show metadata: "); - } + $sb = new SetupBlock("Image Options"); + $sb->position = 30; + // advanced only + //$sb->add_text_option("image_ilink", "Image link: "); + //$sb->add_text_option("image_tlink", "
    Thumbnail link: "); + $sb->add_text_option("image_tip", "Image tooltip: "); + $sb->add_choice_option("upload_collision_handler", ['Error'=>'error', 'Merge'=>'merge'], "
    Upload collision handler: "); + if (function_exists("exif_read_data")) { + $sb->add_bool_option("image_show_meta", "
    Show metadata: "); + } - $event->panel->add_block($sb); + $event->panel->add_block($sb); - $thumbers = array(); - $thumbers['Built-in GD'] = "gd"; - $thumbers['ImageMagick'] = "convert"; + $thumbers = []; + $thumbers['Built-in GD'] = "gd"; + $thumbers['ImageMagick'] = "convert"; - $sb = new SetupBlock("Thumbnailing"); - $sb->add_choice_option("thumb_engine", $thumbers, "Engine: "); + $sb = new SetupBlock("Thumbnailing"); + $sb->add_choice_option("thumb_engine", $thumbers, "Engine: "); - $sb->add_label("
    Size "); - $sb->add_int_option("thumb_width"); - $sb->add_label(" x "); - $sb->add_int_option("thumb_height"); - $sb->add_label(" px at "); - $sb->add_int_option("thumb_quality"); - $sb->add_label(" % quality "); - - if($config->get_string("thumb_engine") == "convert") { - $sb->add_label("
    ImageMagick Binary: "); - $sb->add_text_option("thumb_convert_path"); - } + $sb->add_label("
    Size "); + $sb->add_int_option("thumb_width"); + $sb->add_label(" x "); + $sb->add_int_option("thumb_height"); + $sb->add_label(" px at "); + $sb->add_int_option("thumb_quality"); + $sb->add_label(" % quality "); + + if ($config->get_string("thumb_engine") == "convert") { + $sb->add_label("
    ImageMagick Binary: "); + $sb->add_text_option("thumb_convert_path"); + } - if($config->get_string("thumb_engine") == "gd") { - $sb->add_shorthand_int_option("thumb_mem_limit", "
    Max memory use: "); - } + if ($config->get_string("thumb_engine") == "gd") { + $sb->add_shorthand_int_option("thumb_mem_limit", "
    Max memory use: "); + } - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } -// add image {{{ - private function add_image(Image $image) { - global $user, $database, $config; + // add image {{{ + private function add_image(Image $image) + { + global $user, $database, $config; - /* - * Validate things - */ - if(strlen(trim($image->source)) == 0) { - $image->source = null; - } + /* + * Validate things + */ + if (strlen(trim($image->source)) == 0) { + $image->source = null; + } - /* - * Check for an existing image - */ - $existing = Image::by_hash($image->hash); - if(!is_null($existing)) { - $handler = $config->get_string("upload_collision_handler"); - if($handler == "merge" || isset($_GET['update'])) { - $merged = array_merge($image->get_tag_array(), $existing->get_tag_array()); - send_event(new TagSetEvent($existing, $merged)); - if(isset($_GET['rating']) && isset($_GET['update']) && ext_is_live("Ratings")){ - send_event(new RatingSetEvent($existing, $_GET['rating'])); - } - if(isset($_GET['source']) && isset($_GET['update'])){ - send_event(new SourceSetEvent($existing, $_GET['source'])); - } - return null; - } - else { - $error = "Image {$existing->id} ". - "already has hash {$image->hash}:

    ".$this->theme->build_thumb_html($existing); - throw new ImageAdditionException($error); - } - } + /* + * Check for an existing image + */ + $existing = Image::by_hash($image->hash); + if (!is_null($existing)) { + $handler = $config->get_string("upload_collision_handler"); + if ($handler == "merge" || isset($_GET['update'])) { + $merged = array_merge($image->get_tag_array(), $existing->get_tag_array()); + send_event(new TagSetEvent($existing, $merged)); + if (isset($_GET['rating']) && isset($_GET['update']) && ext_is_live("Ratings")) { + send_event(new RatingSetEvent($existing, $_GET['rating'])); + } + if (isset($_GET['source']) && isset($_GET['update'])) { + send_event(new SourceSetEvent($existing, $_GET['source'])); + } + return null; + } else { + $error = "Image {$existing->id} ". + "already has hash {$image->hash}:

    ".$this->theme->build_thumb_html($existing); + throw new ImageAdditionException($error); + } + } - // actually insert the info - $database->Execute( - "INSERT INTO images( + // actually insert the info + $database->Execute( + "INSERT INTO images( owner_id, owner_ip, filename, filesize, hash, ext, width, height, posted, source ) @@ -203,123 +206,120 @@ class ImageIO extends Extension { :owner_id, :owner_ip, :filename, :filesize, :hash, :ext, :width, :height, now(), :source )", - array( - "owner_id"=>$user->id, "owner_ip"=>$_SERVER['REMOTE_ADDR'], "filename"=>substr($image->filename, 0, 60), "filesize"=>$image->filesize, - "hash"=>$image->hash, "ext"=>strtolower($image->ext), "width"=>$image->width, "height"=>$image->height, "source"=>$image->source - ) - ); - $image->id = $database->get_last_insert_id('images_id_seq'); + [ + "owner_id"=>$user->id, "owner_ip"=>$_SERVER['REMOTE_ADDR'], "filename"=>substr($image->filename, 0, 60), "filesize"=>$image->filesize, + "hash"=>$image->hash, "ext"=>strtolower($image->ext), "width"=>$image->width, "height"=>$image->height, "source"=>$image->source + ] + ); + $image->id = $database->get_last_insert_id('images_id_seq'); - log_info("image", "Uploaded Image #{$image->id} ({$image->hash})"); + log_info("image", "Uploaded Image #{$image->id} ({$image->hash})"); - # at this point in time, the image's tags haven't really been set, - # and so, having $image->tag_array set to something is a lie (but - # a useful one, as we want to know what the tags are /supposed/ to - # be). Here we correct the lie, by first nullifying the wrong tags - # then using the standard mechanism to set them properly. - $tags_to_set = $image->get_tag_array(); - $image->tag_array = array(); - send_event(new TagSetEvent($image, $tags_to_set)); + # at this point in time, the image's tags haven't really been set, + # and so, having $image->tag_array set to something is a lie (but + # a useful one, as we want to know what the tags are /supposed/ to + # be). Here we correct the lie, by first nullifying the wrong tags + # then using the standard mechanism to set them properly. + $tags_to_set = $image->get_tag_array(); + $image->tag_array = []; + send_event(new TagSetEvent($image, $tags_to_set)); - if($image->source !== null) { - log_info("core-image", "Source for Image #{$image->id} set to: {$image->source}"); - } - } -// }}} end add + if ($image->source !== null) { + log_info("core-image", "Source for Image #{$image->id} set to: {$image->source}"); + } + } + // }}} end add -// fetch image {{{ - private function send_file(int $image_id, string $type) { - global $config; - $image = Image::by_id($image_id); + // fetch image {{{ + private function send_file(int $image_id, string $type) + { + global $config; + $image = Image::by_id($image_id); - global $page; - if(!is_null($image)) { - $page->set_mode("data"); - if($type == "thumb") { - $page->set_type("image/jpeg"); - $file = $image->get_thumb_filename(); - } - else { - $page->set_type($image->get_mime_type()); - $file = $image->get_image_filename(); - } + global $page; + if (!is_null($image)) { + $page->set_mode("data"); + if ($type == "thumb") { + $page->set_type("image/jpeg"); + $file = $image->get_thumb_filename(); + } else { + $page->set_type($image->get_mime_type()); + $file = $image->get_image_filename(); + } - if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { - $if_modified_since = preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]); - } - else { - $if_modified_since = ""; - } - $gmdate_mod = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'; + if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { + $if_modified_since = preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]); + } else { + $if_modified_since = ""; + } + $gmdate_mod = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'; - if($if_modified_since == $gmdate_mod) { - $page->set_code(304); - $page->set_data(""); - } - else { - $page->add_http_header("Last-Modified: $gmdate_mod"); - $page->set_data(file_get_contents($file)); - - if ( $config->get_int("image_expires") ) { - $expires = date(DATE_RFC1123, time() + $config->get_int("image_expires")); - } else { - $expires = 'Fri, 2 Sep 2101 12:42:42 GMT'; // War was beginning - } - $page->add_http_header('Expires: '.$expires); - } - } - else { - $page->set_title("Not Found"); - $page->set_heading("Not Found"); - $page->add_block(new Block("Navigation", "Index", "left", 0)); - $page->add_block(new Block("Image not in database", - "The requested image was not found in the database")); - } - } -// }}} end fetch + if ($if_modified_since == $gmdate_mod) { + $page->set_code(304); + $page->set_data(""); + } else { + $page->add_http_header("Last-Modified: $gmdate_mod"); + $page->set_data(file_get_contents($file)); + + if ($config->get_int("image_expires")) { + $expires = date(DATE_RFC1123, time() + $config->get_int("image_expires")); + } else { + $expires = 'Fri, 2 Sep 2101 12:42:42 GMT'; // War was beginning + } + $page->add_http_header('Expires: '.$expires); + } + } else { + $page->set_title("Not Found"); + $page->set_heading("Not Found"); + $page->add_block(new Block("Navigation", "Index", "left", 0)); + $page->add_block(new Block( + "Image not in database", + "The requested image was not found in the database" + )); + } + } + // }}} end fetch -// replace image {{{ - private function replace_image(int $id, Image $image) { - global $database; + // replace image {{{ + private function replace_image(int $id, Image $image) + { + global $database; - /* Check to make sure the image exists. */ - $existing = Image::by_id($id); - - if(is_null($existing)) { - throw new ImageReplaceException("Image to replace does not exist!"); - } - - if(strlen(trim($image->source)) == 0) { - $image->source = $existing->get_source(); - } - - /* - This step could be optional, ie: perhaps move the image somewhere - and have it stored in a 'replaced images' list that could be - inspected later by an admin? - */ - log_debug("image", "Removing image with hash ".$existing->hash); - $existing->remove_image_only(); // Actually delete the old image file from disk - - // Update the data in the database. - $database->Execute( - "UPDATE images SET + /* Check to make sure the image exists. */ + $existing = Image::by_id($id); + + if (is_null($existing)) { + throw new ImageReplaceException("Image to replace does not exist!"); + } + + if (strlen(trim($image->source)) == 0) { + $image->source = $existing->get_source(); + } + + /* + This step could be optional, ie: perhaps move the image somewhere + and have it stored in a 'replaced images' list that could be + inspected later by an admin? + */ + log_debug("image", "Removing image with hash ".$existing->hash); + $existing->remove_image_only(); // Actually delete the old image file from disk + + // Update the data in the database. + $database->Execute( + "UPDATE images SET filename = :filename, filesize = :filesize, hash = :hash, ext = :ext, width = :width, height = :height, source = :source WHERE id = :id ", - array( - "filename"=>$image->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, - "ext"=>strtolower($image->ext), "width"=>$image->width, "height"=>$image->height, "source"=>$image->source, - "id"=>$id - ) - ); - - log_info("image", "Replaced Image #{$id} with ({$image->hash})"); - } -// }}} end replace - + [ + "filename"=>$image->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, + "ext"=>strtolower($image->ext), "width"=>$image->width, "height"=>$image->height, "source"=>$image->source, + "id"=>$id + ] + ); + log_info("image", "Replaced Image #{$id} with ({$image->hash})"); + } + // }}} end replace } // end of class ImageIO - diff --git a/ext/image/test.php b/ext/image/test.php index d5034175..a22dfca0 100644 --- a/ext/image/test.php +++ b/ext/image/test.php @@ -1,18 +1,20 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); +class ImageIOTest extends ShimmiePHPUnitTestCase +{ + public function testUserStats() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); - // broken with sqlite? - //$this->get_page("user/test"); - //$this->assert_text("Images uploaded: 1"); + // broken with sqlite? + //$this->get_page("user/test"); + //$this->assert_text("Images uploaded: 1"); - //$this->click("Images uploaded"); - //$this->assert_title("Image $image_id: test"); + //$this->click("Images uploaded"); + //$this->assert_title("Image $image_id: test"); - # test that serving manually doesn't cause errors - $this->get_page("image/$image_id/moo.jpg"); - $this->get_page("thumb/$image_id/moo.jpg"); - } + # test that serving manually doesn't cause errors + $this->get_page("image/$image_id/moo.jpg"); + $this->get_page("thumb/$image_id/moo.jpg"); + } } diff --git a/ext/image/theme.php b/ext/image/theme.php index 2112d15f..b20e0164 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -1,29 +1,31 @@ "; - - return $html; - } + + return $html; + } - /** - * Display link to replace the image - */ - public function get_replace_html(int $image_id): string { - $html = make_form(make_link("image/replace"))." + /** + * Display link to replace the image + */ + public function get_replace_html(int $image_id): string + { + $html = make_form(make_link("image/replace"))." "; - return $html; - } + return $html; + } } - diff --git a/ext/image_hash_ban/main.php b/ext/image_hash_ban/main.php index 60dd4cb5..6589ee16 100644 --- a/ext/image_hash_ban/main.php +++ b/ext/image_hash_ban/main.php @@ -10,140 +10,152 @@ */ // RemoveImageHashBanEvent {{{ -class RemoveImageHashBanEvent extends Event { - public $hash; +class RemoveImageHashBanEvent extends Event +{ + public $hash; - public function __construct(string $hash) { - $this->hash = $hash; - } + public function __construct(string $hash) + { + $this->hash = $hash; + } } // }}} // AddImageHashBanEvent {{{ -class AddImageHashBanEvent extends Event { - public $hash; - public $reason; +class AddImageHashBanEvent extends Event +{ + public $hash; + public $reason; - public function __construct(string $hash, string $reason) { - $this->hash = $hash; - $this->reason = $reason; - } + public function __construct(string $hash, string $reason) + { + $this->hash = $hash; + $this->reason = $reason; + } } // }}} -class ImageBan extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; - if($config->get_int("ext_imageban_version") < 1) { - $database->create_table("image_bans", " +class ImageBan extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; + if ($config->get_int("ext_imageban_version") < 1) { + $database->create_table("image_bans", " id SCORE_AIPK, hash CHAR(32) NOT NULL, date SCORE_DATETIME DEFAULT SCORE_NOW, reason TEXT NOT NULL "); - $config->set_int("ext_imageban_version", 1); - } - } + $config->set_int("ext_imageban_version", 1); + } + } - public function onDataUpload(DataUploadEvent $event) { - global $database; - $row = $database->get_row("SELECT * FROM image_bans WHERE hash = :hash", array("hash"=>$event->hash)); - if($row) { - log_info("image_hash_ban", "Attempted to upload a blocked image ({$event->hash} - {$row['reason']})"); - throw new UploadException("Image ".html_escape($row["hash"])." has been banned, reason: ".format_text($row["reason"])); - } - } + public function onDataUpload(DataUploadEvent $event) + { + global $database; + $row = $database->get_row("SELECT * FROM image_bans WHERE hash = :hash", ["hash"=>$event->hash]); + if ($row) { + log_info("image_hash_ban", "Attempted to upload a blocked image ({$event->hash} - {$row['reason']})"); + throw new UploadException("Image ".html_escape($row["hash"])." has been banned, reason: ".format_text($row["reason"])); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page, $user; - if($event->page_matches("image_hash_ban")) { - if($user->can("ban_image")) { - if($event->get_arg(0) == "add") { - $image = isset($_POST['image_id']) ? Image::by_id(int_escape($_POST['image_id'])) : null; - $hash = isset($_POST["hash"]) ? $_POST["hash"] : $image->hash; - $reason = isset($_POST['reason']) ? $_POST['reason'] : "DNP"; + if ($event->page_matches("image_hash_ban")) { + if ($user->can("ban_image")) { + if ($event->get_arg(0) == "add") { + $image = isset($_POST['image_id']) ? Image::by_id(int_escape($_POST['image_id'])) : null; + $hash = isset($_POST["hash"]) ? $_POST["hash"] : $image->hash; + $reason = isset($_POST['reason']) ? $_POST['reason'] : "DNP"; - if($hash) { - send_event(new AddImageHashBanEvent($hash, $reason)); - flash_message("Image ban added"); + if ($hash) { + send_event(new AddImageHashBanEvent($hash, $reason)); + flash_message("Image ban added"); - if($image) { - send_event(new ImageDeletionEvent($image)); - flash_message("Image deleted"); - } + if ($image) { + send_event(new ImageDeletionEvent($image)); + flash_message("Image deleted"); + } - $page->set_mode("redirect"); - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - } - else if($event->get_arg(0) == "remove") { - if(isset($_POST['hash'])) { - send_event(new RemoveImageHashBanEvent($_POST['hash'])); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER['HTTP_REFERER']); + } + } elseif ($event->get_arg(0) == "remove") { + if (isset($_POST['hash'])) { + send_event(new RemoveImageHashBanEvent($_POST['hash'])); - flash_message("Image ban removed"); - $page->set_mode("redirect"); - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - } - else if($event->get_arg(0) == "list") { - $page_num = 0; - if($event->count_args() == 2) { - $page_num = int_escape($event->get_arg(1)); - } - $page_size = 100; - $page_count = ceil($database->get_one("SELECT COUNT(id) FROM image_bans")/$page_size); - $this->theme->display_Image_hash_Bans($page, $page_num, $page_count, $this->get_image_hash_bans($page_num, $page_size)); - } - } - } - } + flash_message("Image ban removed"); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER['HTTP_REFERER']); + } + } elseif ($event->get_arg(0) == "list") { + $page_num = 0; + if ($event->count_args() == 2) { + $page_num = int_escape($event->get_arg(1)); + } + $page_size = 100; + $page_count = ceil($database->get_one("SELECT COUNT(id) FROM image_bans")/$page_size); + $this->theme->display_Image_hash_Bans($page, $page_num, $page_count, $this->get_image_hash_bans($page_num, $page_size)); + } + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("ban_image")) { - $event->add_link("Image Bans", make_link("image_hash_ban/list/1")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("ban_image")) { + $event->add_link("Image Bans", make_link("image_hash_ban/list/1")); + } + } - public function onAddImageHashBan(AddImageHashBanEvent $event) { - global $database; - $database->Execute( - "INSERT INTO image_bans (hash, reason, date) VALUES (?, ?, now())", - array($event->hash, $event->reason)); - log_info("image_hash_ban", "Banned hash {$event->hash} because '{$event->reason}'"); - } + public function onAddImageHashBan(AddImageHashBanEvent $event) + { + global $database; + $database->Execute( + "INSERT INTO image_bans (hash, reason, date) VALUES (?, ?, now())", + [$event->hash, $event->reason] + ); + log_info("image_hash_ban", "Banned hash {$event->hash} because '{$event->reason}'"); + } - public function onRemoveImageHashBan(RemoveImageHashBanEvent $event) { - global $database; - $database->Execute("DELETE FROM image_bans WHERE hash = ?", array($event->hash)); - } + public function onRemoveImageHashBan(RemoveImageHashBanEvent $event) + { + global $database; + $database->Execute("DELETE FROM image_bans WHERE hash = ?", [$event->hash]); + } - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $user; - if($user->can("ban_image")) { - $event->add_part($this->theme->get_buttons_html($event->image)); - } - } + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $user; + if ($user->can("ban_image")) { + $event->add_part($this->theme->get_buttons_html($event->image)); + } + } - // DB funness + // DB funness - public function get_image_hash_bans(int $page, int $size=100): array { - global $database; + public function get_image_hash_bans(int $page, int $size=100): array + { + global $database; - // FIXME: many - $size_i = int_escape($size); - $offset_i = int_escape($page-1)*$size_i; - $where = array("(1=1)"); - $args = array(); - if(!empty($_GET['hash'])) { - $where[] = 'hash = ?'; - $args[] = $_GET['hash']; - } - if(!empty($_GET['reason'])) { - $where[] = 'reason SCORE_ILIKE ?'; - $args[] = "%".$_GET['reason']."%"; - } - $where = implode(" AND ", $where); - $bans = $database->get_all($database->scoreql_to_sql(" + // FIXME: many + $size_i = int_escape($size); + $offset_i = int_escape($page-1)*$size_i; + $where = ["(1=1)"]; + $args = []; + if (!empty($_GET['hash'])) { + $where[] = 'hash = ?'; + $args[] = $_GET['hash']; + } + if (!empty($_GET['reason'])) { + $where[] = 'reason SCORE_ILIKE ?'; + $args[] = "%".$_GET['reason']."%"; + } + $where = implode(" AND ", $where); + $bans = $database->get_all($database->scoreql_to_sql(" SELECT * FROM image_bans WHERE $where @@ -151,11 +163,16 @@ class ImageBan extends Extension { LIMIT $size_i OFFSET $offset_i "), $args); - if($bans) {return $bans;} - else {return array();} - } + if ($bans) { + return $bans; + } else { + return []; + } + } - // in before resolution limit plugin - public function get_priority(): int {return 30;} + // in before resolution limit plugin + public function get_priority(): int + { + return 30; + } } - diff --git a/ext/image_hash_ban/test.php b/ext/image_hash_ban/test.php index 4e22fe71..178dc50d 100644 --- a/ext/image_hash_ban/test.php +++ b/ext/image_hash_ban/test.php @@ -1,33 +1,34 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->log_out(); +class HashBanTest extends ShimmiePHPUnitTestCase +{ + public function testBan() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->log_out(); - $this->log_in_as_admin(); - $this->get_page("post/view/$image_id"); + $this->log_in_as_admin(); + $this->get_page("post/view/$image_id"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->click("Ban and Delete"); - $this->log_out(); + $this->click("Ban and Delete"); + $this->log_out(); - $this->log_in_as_user(); - $this->get_page("post/view/$image_id"); - $this->assert_response(404); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_response(404); + $this->log_in_as_user(); + $this->get_page("post/view/$image_id"); + $this->assert_response(404); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_response(404); - $this->log_in_as_admin(); - $this->get_page("image_hash_ban/list/1"); - $this->click("Remove"); + $this->log_in_as_admin(); + $this->get_page("image_hash_ban/list/1"); + $this->click("Remove"); - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_response(200); - } + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_response(200); + } } - diff --git a/ext/image_hash_ban/theme.php b/ext/image_hash_ban/theme.php index 0c759a4a..53bf6139 100644 --- a/ext/image_hash_ban/theme.php +++ b/ext/image_hash_ban/theme.php @@ -10,20 +10,22 @@ * October 21, 2007 */ -class ImageBanTheme extends Themelet { - /* - * Show all the bans - * - * $bans = an array of ( - * 'hash' => the banned hash - * 'reason' => why the hash was banned - * 'date' => when the ban started - * ) - */ - public function display_image_hash_bans(Page $page, $page_number, $page_count, $bans) { - $h_bans = ""; - foreach($bans as $ban) { - $h_bans .= " +class ImageBanTheme extends Themelet +{ + /* + * Show all the bans + * + * $bans = an array of ( + * 'hash' => the banned hash + * 'reason' => why the hash was banned + * 'date' => when the ban started + * ) + */ + public function display_image_hash_bans(Page $page, $page_number, $page_count, $bans) + { + $h_bans = ""; + foreach ($bans as $ban) { + $h_bans .= " ".make_form(make_link("image_hash_ban/remove"))." {$ban['hash']} @@ -35,8 +37,8 @@ class ImageBanTheme extends Themelet { "; - } - $html = " + } + $html = " @@ -59,29 +61,30 @@ class ImageBanTheme extends Themelet {
    HashReasonAction
    "; - $prev = $page_number - 1; - $next = $page_number + 1; + $prev = $page_number - 1; + $next = $page_number + 1; - $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; - $h_index = "Index"; - $h_next = ($page_number >= $page_count) ? "Next" : "Next"; + $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; + $h_index = "Index"; + $h_next = ($page_number >= $page_count) ? "Next" : "Next"; - $nav = "$h_prev | $h_index | $h_next"; + $nav = "$h_prev | $h_index | $h_next"; - $page->set_title("Image Bans"); - $page->set_heading("Image Bans"); - $page->add_block(new Block("Edit Image Bans", $html)); - $page->add_block(new Block("Navigation", $nav, "left", 0)); - $this->display_paginator($page, "image_hash_ban/list", null, $page_number, $page_count); - } + $page->set_title("Image Bans"); + $page->set_heading("Image Bans"); + $page->add_block(new Block("Edit Image Bans", $html)); + $page->add_block(new Block("Navigation", $nav, "left", 0)); + $this->display_paginator($page, "image_hash_ban/list", null, $page_number, $page_count); + } - /* - * Display a link to delete an image - * - * $image_id = the image to delete - */ - public function get_buttons_html(Image $image) { - $html = " + /* + * Display a link to delete an image + * + * $image_id = the image to delete + */ + public function get_buttons_html(Image $image) + { + $html = " ".make_form(make_link("image_hash_ban/add"))." @@ -89,7 +92,6 @@ class ImageBanTheme extends Themelet { "; - return $html; - } + return $html; + } } - diff --git a/ext/image_view_counter/main.php b/ext/image_view_counter/main.php index 175ddd35..c996fa5a 100644 --- a/ext/image_view_counter/main.php +++ b/ext/image_view_counter/main.php @@ -8,124 +8,137 @@ * Documentation: * Whenever anyone views an image, a view will be added to that image. * This extension will also track any username & the IP adress. - * This is done to prevent duplicate views. + * This is done to prevent duplicate views. * A person can only count as a view again 1 hour after viewing the image initially. */ -class ImageViewCounter extends Extension { - private $view_interval = 3600; # allows views to be added each hour +class ImageViewCounter extends Extension +{ + private $view_interval = 3600; # allows views to be added each hour - # Add Setup Block with options for view counter - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Image View Counter"); - $sb->add_bool_option("image_viewcounter_adminonly", "Display view counter only to admin"); + # Add Setup Block with options for view counter + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Image View Counter"); + $sb->add_bool_option("image_viewcounter_adminonly", "Display view counter only to admin"); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - # Adds view to database if needed - public function onDisplayingImage(DisplayingImageEvent $event) { - $imgid = $event->image->id; // determines image id - $this->addview($imgid); // adds a view - } + # Adds view to database if needed + public function onDisplayingImage(DisplayingImageEvent $event) + { + $imgid = $event->image->id; // determines image id + $this->addview($imgid); // adds a view + } - # display views to user or admin below image if allowed - public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { - global $user, $config; + # display views to user or admin below image if allowed + public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) + { + global $user, $config; - $adminonly = $config->get_bool("image_viewcounter_adminonly"); // todo - if ($adminonly == false || ($adminonly && $user->is_admin())) - $event->add_part( - "Views:". - $this->get_view_count($event->image->id) . - "", 38); - } + $adminonly = $config->get_bool("image_viewcounter_adminonly"); // todo + if ($adminonly == false || ($adminonly && $user->is_admin())) { + $event->add_part( + "Views:". + $this->get_view_count($event->image->id) . + "", + 38 + ); + } + } - # Installs DB table - public function onInitExt(InitExtEvent $event) { - global $database, $config; + # Installs DB table + public function onInitExt(InitExtEvent $event) + { + global $database, $config; - // if the sql table doesn't exist yet, create it - if($config->get_bool("image_viewcounter_installed") == false) { //todo - $database->create_table("image_views"," + // if the sql table doesn't exist yet, create it + if ($config->get_bool("image_viewcounter_installed") == false) { //todo + $database->create_table("image_views", " id SCORE_AIPK, image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, timestamp INTEGER NOT NULL, ipaddress SCORE_INET NOT NULL"); - $config->set_bool("image_viewcounter_installed", true); - } - } + $config->set_bool("image_viewcounter_installed", true); + } + } - /** - * Adds a view to the item if needed - */ - private function addview(int $imgid) - { - global $database, $user; + /** + * Adds a view to the item if needed + */ + private function addview(int $imgid) + { + global $database, $user; - // don't add view if person already viewed recently - if ($this->can_add_view($imgid) == false) return; + // don't add view if person already viewed recently + if ($this->can_add_view($imgid) == false) { + return; + } - // Add view for current IP - $database->execute( - " + // Add view for current IP + $database->execute( + " INSERT INTO image_views (image_id, user_id, timestamp, ipaddress) VALUES (:image_id, :user_id, :timestamp, :ipaddress) ", - array( - "image_id" => $imgid, - "user_id" => $user->id, - "timestamp" => time(), - "ipaddress" => $_SERVER['REMOTE_ADDR'], - ) - ); - } + [ + "image_id" => $imgid, + "user_id" => $user->id, + "timestamp" => time(), + "ipaddress" => $_SERVER['REMOTE_ADDR'], + ] + ); + } - /** - * Returns true if this IP hasn't recently viewed this image - */ - private function can_add_view(int $imgid) - { - global $database; + /** + * Returns true if this IP hasn't recently viewed this image + */ + private function can_add_view(int $imgid) + { + global $database; - // counts views from current IP in the last hour - $recent_from_ip = (int)$database->get_one( - " + // counts views from current IP in the last hour + $recent_from_ip = (int)$database->get_one( + " SELECT COUNT(*) FROM image_views WHERE ipaddress=:ipaddress AND timestamp >:lasthour AND image_id =:image_id ", - array( - "ipaddress" => $_SERVER['REMOTE_ADDR'], - "lasthour" => time() - $this->view_interval, - "image_id" => $imgid - ) - ); + [ + "ipaddress" => $_SERVER['REMOTE_ADDR'], + "lasthour" => time() - $this->view_interval, + "image_id" => $imgid + ] + ); - // if no views were found with the set criteria, return true - if($recent_from_ip == 0) return true; - else return false; - } + // if no views were found with the set criteria, return true + if ($recent_from_ip == 0) { + return true; + } else { + return false; + } + } - /** - * Returns the int of the view count from the given image id - */ - private function get_view_count(int $imgid = 0) - { - global $database; + /** + * Returns the int of the view count from the given image id + */ + private function get_view_count(int $imgid = 0) + { + global $database; - if ($imgid == 0) // return view count of all images - $view_count = (int)$database->get_one( - "SELECT COUNT(*) FROM image_views" - ); - else // return view count of specified image - $view_count = (int)$database->get_one( - "SELECT COUNT(*) FROM image_views WHERE image_id =:image_id", - array("image_id" => $imgid) - ); + if ($imgid == 0) { // return view count of all images + $view_count = (int)$database->get_one( + "SELECT COUNT(*) FROM image_views" + ); + } else { // return view count of specified image + $view_count = (int)$database->get_one( + "SELECT COUNT(*) FROM image_views WHERE image_id =:image_id", + ["image_id" => $imgid] + ); + } - // returns the count as int - return $view_count; - } + // returns the count as int + return $view_count; + } } - diff --git a/ext/index/main.php b/ext/index/main.php index d6a2c920..91b6c5d1 100644 --- a/ext/index/main.php +++ b/ext/index/main.php @@ -158,158 +158,170 @@ * SearchTermParseEvent: * Signal that a search term needs parsing */ -class SearchTermParseEvent extends Event { - /** @var null|string */ - public $term = null; - /** @var string[] */ - public $context = array(); - /** @var \Querylet[] */ - public $querylets = array(); +class SearchTermParseEvent extends Event +{ + /** @var null|string */ + public $term = null; + /** @var string[] */ + public $context = []; + /** @var \Querylet[] */ + public $querylets = []; - public function __construct(string $term=null, array $context=array()) { - $this->term = $term; - $this->context = $context; - } + public function __construct(string $term=null, array $context=[]) + { + $this->term = $term; + $this->context = $context; + } - public function is_querylet_set(): bool { - return (count($this->querylets) > 0); - } + public function is_querylet_set(): bool + { + return (count($this->querylets) > 0); + } - public function get_querylets(): array { - return $this->querylets; - } + public function get_querylets(): array + { + return $this->querylets; + } - public function add_querylet(Querylet $q) { - $this->querylets[] = $q; - } + public function add_querylet(Querylet $q) + { + $this->querylets[] = $q; + } } -class SearchTermParseException extends SCoreException { +class SearchTermParseException extends SCoreException +{ } -class PostListBuildingEvent extends Event { - /** @var array */ - public $search_terms = array(); +class PostListBuildingEvent extends Event +{ + /** @var array */ + public $search_terms = []; - /** @var array */ - public $parts = array(); + /** @var array */ + public $parts = []; - /** - * #param string[] $search - */ - public function __construct(array $search) { - $this->search_terms = $search; - } + /** + * #param string[] $search + */ + public function __construct(array $search) + { + $this->search_terms = $search; + } - public function add_control(string $html, int $position=50) { - while(isset($this->parts[$position])) $position++; - $this->parts[$position] = $html; - } + public function add_control(string $html, int $position=50) + { + while (isset($this->parts[$position])) { + $position++; + } + $this->parts[$position] = $html; + } } -class Index extends Extension { +class Index extends Extension +{ /** @var int */ - private $stpen = 0; // search term parse event number + private $stpen = 0; // search term parse event number - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int("index_images", 24); - $config->set_default_bool("index_tips", true); - $config->set_default_string("index_order", "id DESC"); - } + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int("index_images", 24); + $config->set_default_bool("index_tips", true); + $config->set_default_string("index_order", "id DESC"); + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page; - if($event->page_matches("post/list")) { - if(isset($_GET['search'])) { - // implode(explode()) to resolve aliases and sanitise - $search = url_escape(Tag::implode(Tag::explode($_GET['search'], false))); - if(empty($search)) { - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/list/1")); - } - else { - $page->set_mode("redirect"); - $page->set_redirect(make_link('post/list/'.$search.'/1')); - } - return; - } + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page; + if ($event->page_matches("post/list")) { + if (isset($_GET['search'])) { + // implode(explode()) to resolve aliases and sanitise + $search = url_escape(Tag::implode(Tag::explode($_GET['search'], false))); + if (empty($search)) { + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/list/1")); + } else { + $page->set_mode("redirect"); + $page->set_redirect(make_link('post/list/'.$search.'/1')); + } + return; + } - $search_terms = $event->get_search_terms(); - $page_number = $event->get_page_number(); - $page_size = $event->get_page_size(); + $search_terms = $event->get_search_terms(); + $page_number = $event->get_page_number(); + $page_size = $event->get_page_size(); - $count_search_terms = count($search_terms); + $count_search_terms = count($search_terms); - try { - #log_debug("index", "Search for ".Tag::implode($search_terms), false, array("terms"=>$search_terms)); - $total_pages = Image::count_pages($search_terms); - if(SPEED_HAX && $count_search_terms === 0 && ($page_number < 10)) { // extra caching for the first few post/list pages - $images = $database->cache->get("post-list:$page_number"); - if(!$images) { - $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); - $database->cache->set("post-list:$page_number", $images, 60); - } - } - else { - $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); - } - } - catch(SearchTermParseException $stpe) { - // FIXME: display the error somewhere - $total_pages = 0; - $images = array(); - } + try { + #log_debug("index", "Search for ".Tag::implode($search_terms), false, array("terms"=>$search_terms)); + $total_pages = Image::count_pages($search_terms); + if (SPEED_HAX && $count_search_terms === 0 && ($page_number < 10)) { // extra caching for the first few post/list pages + $images = $database->cache->get("post-list:$page_number"); + if (!$images) { + $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); + $database->cache->set("post-list:$page_number", $images, 60); + } + } else { + $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); + } + } catch (SearchTermParseException $stpe) { + // FIXME: display the error somewhere + $total_pages = 0; + $images = []; + } - $count_images = count($images); + $count_images = count($images); - if($count_search_terms === 0 && $count_images === 0 && $page_number === 1) { - $this->theme->display_intro($page); - send_event(new PostListBuildingEvent($search_terms)); - } - else if($count_search_terms > 0 && $count_images === 1 && $page_number === 1) { - $page->set_mode("redirect"); - $page->set_redirect(make_link('post/view/'.$images[0]->id)); - } - else { - $plbe = new PostListBuildingEvent($search_terms); - send_event($plbe); + if ($count_search_terms === 0 && $count_images === 0 && $page_number === 1) { + $this->theme->display_intro($page); + send_event(new PostListBuildingEvent($search_terms)); + } elseif ($count_search_terms > 0 && $count_images === 1 && $page_number === 1) { + $page->set_mode("redirect"); + $page->set_redirect(make_link('post/view/'.$images[0]->id)); + } else { + $plbe = new PostListBuildingEvent($search_terms); + send_event($plbe); - $this->theme->set_page($page_number, $total_pages, $search_terms); - $this->theme->display_page($page, $images); - if(count($plbe->parts) > 0) { - $this->theme->display_admin_block($plbe->parts); - } - } - } - } + $this->theme->set_page($page_number, $total_pages, $search_terms); + $this->theme->display_page($page, $images); + if (count($plbe->parts) > 0) { + $this->theme->display_admin_block($plbe->parts); + } + } + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Index Options"); - $sb->position = 20; + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Index Options"); + $sb->position = 20; - $sb->add_label("Show "); - $sb->add_int_option("index_images"); - $sb->add_label(" images on the post list"); + $sb->add_label("Show "); + $sb->add_int_option("index_images"); + $sb->add_label(" images on the post list"); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - public function onImageInfoSet(ImageInfoSetEvent $event) { - global $database; - if(SPEED_HAX) { - $database->cache->delete("thumb-block:{$event->image->id}"); - } - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + global $database; + if (SPEED_HAX) { + $database->cache->delete("thumb-block:{$event->image->id}"); + } + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - // check for tags first as tag based searches are more common. - if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $count = $matches[2]; - $event->add_querylet( - new Querylet("EXISTS ( + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + // check for tags first as tag based searches are more common. + if (preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $count = $matches[2]; + $event->add_querylet( + new Querylet("EXISTS ( SELECT 1 FROM image_tags it LEFT JOIN tags t ON it.tag_id = t.id @@ -317,78 +329,65 @@ class Index extends Extension { GROUP BY image_id HAVING COUNT(*) $cmp $count )") - ); - } - else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) { - $cmp = preg_replace('/^:/', '=', $matches[1]); - $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); - $event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args)); - } - else if(preg_match("/^(filesize|id)([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+[kmg]?b?)$/i", $event->term, $matches)) { - $col = $matches[1]; - $cmp = ltrim($matches[2], ":") ?: "="; - $val = parse_shorthand_int($matches[3]); - $event->add_querylet(new Querylet("images.$col $cmp :val{$this->stpen}", array("val{$this->stpen}"=>$val))); - } - else if(preg_match("/^(hash|md5)[=|:]([0-9a-fA-F]*)$/i", $event->term, $matches)) { - $hash = strtolower($matches[2]); - $event->add_querylet(new Querylet('images.hash = :hash', array("hash" => $hash))); - } - else if(preg_match("/^(phash)[=|:]([0-9a-fA-F]*)$/i", $event->term, $matches)) { - $phash = strtolower($matches[2]); - $event->add_querylet(new Querylet('images.phash = :phash', array("phash" => $phash))); - } - else if(preg_match("/^(filetype|ext)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) { - $ext = strtolower($matches[2]); - $event->add_querylet(new Querylet('images.ext = :ext', array("ext" => $ext))); - } - else if(preg_match("/^(filename|name)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) { - $filename = strtolower($matches[2]); - $event->add_querylet(new Querylet("images.filename LIKE :filename{$this->stpen}", array("filename{$this->stpen}"=>"%$filename%"))); - } - else if(preg_match("/^(source)[=|:](.*)$/i", $event->term, $matches)) { - $source = strtolower($matches[2]); + ); + } elseif (preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) { + $cmp = preg_replace('/^:/', '=', $matches[1]); + $args = ["width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])]; + $event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args)); + } elseif (preg_match("/^(filesize|id)([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+[kmg]?b?)$/i", $event->term, $matches)) { + $col = $matches[1]; + $cmp = ltrim($matches[2], ":") ?: "="; + $val = parse_shorthand_int($matches[3]); + $event->add_querylet(new Querylet("images.$col $cmp :val{$this->stpen}", ["val{$this->stpen}"=>$val])); + } elseif (preg_match("/^(hash|md5)[=|:]([0-9a-fA-F]*)$/i", $event->term, $matches)) { + $hash = strtolower($matches[2]); + $event->add_querylet(new Querylet('images.hash = :hash', ["hash" => $hash])); + } elseif (preg_match("/^(phash)[=|:]([0-9a-fA-F]*)$/i", $event->term, $matches)) { + $phash = strtolower($matches[2]); + $event->add_querylet(new Querylet('images.phash = :phash', ["phash" => $phash])); + } elseif (preg_match("/^(filetype|ext)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) { + $ext = strtolower($matches[2]); + $event->add_querylet(new Querylet('images.ext = :ext', ["ext" => $ext])); + } elseif (preg_match("/^(filename|name)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) { + $filename = strtolower($matches[2]); + $event->add_querylet(new Querylet("images.filename LIKE :filename{$this->stpen}", ["filename{$this->stpen}"=>"%$filename%"])); + } elseif (preg_match("/^(source)[=|:](.*)$/i", $event->term, $matches)) { + $source = strtolower($matches[2]); - if(preg_match("/^(any|none)$/i", $source)){ - $not = ($source == "any" ? "NOT" : ""); - $event->add_querylet(new Querylet("images.source IS $not NULL")); - }else{ - $event->add_querylet(new Querylet('images.source LIKE :src', array("src"=>"%$source%"))); - } - } - else if(preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $val = $matches[2]; - $event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", array("posted{$this->stpen}"=>$val))); - } - else if(preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); - $event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args)); - } - else if(preg_match("/^width([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $event->add_querylet(new Querylet("width $cmp :width{$this->stpen}", array("width{$this->stpen}"=>int_escape($matches[2])))); - } - else if(preg_match("/^height([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $event->add_querylet(new Querylet("height $cmp :height{$this->stpen}",array("height{$this->stpen}"=>int_escape($matches[2])))); - } - else if(preg_match("/^order[=|:](id|width|height|filesize|filename)[_]?(desc|asc)?$/i", $event->term, $matches)){ - $ord = strtolower($matches[1]); - $default_order_for_column = preg_match("/^(id|filename)$/", $matches[1]) ? "ASC" : "DESC"; - $sort = isset($matches[2]) ? strtoupper($matches[2]) : $default_order_for_column; - Image::$order_sql = "images.$ord $sort"; - $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag - } - else if(preg_match("/^order[=|:]random[_]([0-9]{1,4})$/i", $event->term, $matches)){ - //order[=|:]random requires a seed to avoid duplicates - //since the tag can't be changed during the parseevent, we instead generate the seed during submit using js - $seed = $matches[1]; - Image::$order_sql = "RAND($seed)"; - $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag - } + if (preg_match("/^(any|none)$/i", $source)) { + $not = ($source == "any" ? "NOT" : ""); + $event->add_querylet(new Querylet("images.source IS $not NULL")); + } else { + $event->add_querylet(new Querylet('images.source LIKE :src', ["src"=>"%$source%"])); + } + } elseif (preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $val = $matches[2]; + $event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", ["posted{$this->stpen}"=>$val])); + } elseif (preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $args = ["width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])]; + $event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args)); + } elseif (preg_match("/^width([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $event->add_querylet(new Querylet("width $cmp :width{$this->stpen}", ["width{$this->stpen}"=>int_escape($matches[2])])); + } elseif (preg_match("/^height([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $event->add_querylet(new Querylet("height $cmp :height{$this->stpen}", ["height{$this->stpen}"=>int_escape($matches[2])])); + } elseif (preg_match("/^order[=|:](id|width|height|filesize|filename)[_]?(desc|asc)?$/i", $event->term, $matches)) { + $ord = strtolower($matches[1]); + $default_order_for_column = preg_match("/^(id|filename)$/", $matches[1]) ? "ASC" : "DESC"; + $sort = isset($matches[2]) ? strtoupper($matches[2]) : $default_order_for_column; + Image::$order_sql = "images.$ord $sort"; + $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag + } elseif (preg_match("/^order[=|:]random[_]([0-9]{1,4})$/i", $event->term, $matches)) { + //order[=|:]random requires a seed to avoid duplicates + //since the tag can't be changed during the parseevent, we instead generate the seed during submit using js + $seed = $matches[1]; + Image::$order_sql = "RAND($seed)"; + $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag + } - $this->stpen++; - } + $this->stpen++; + } } diff --git a/ext/index/test.php b/ext/index/test.php index 111c6161..e9debe74 100644 --- a/ext/index/test.php +++ b/ext/index/test.php @@ -1,204 +1,219 @@ log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "thing computer screenshot pbx phone"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop"); - $this->log_out(); +class IndexTest extends ShimmiePHPUnitTestCase +{ + private function upload() + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "thing computer screenshot pbx phone"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop"); + $this->log_out(); - # make sure both uploads were ok - $this->assertTrue($image_id_1 > 0); - $this->assertTrue($image_id_2 > 0); + # make sure both uploads were ok + $this->assertTrue($image_id_1 > 0); + $this->assertTrue($image_id_2 > 0); - return array($image_id_1, $image_id_2); - } + return [$image_id_1, $image_id_2]; + } - public function testIndexPage() { - $this->get_page('post/list'); - $this->assert_title("Welcome to Shimmie"); - $this->assert_no_text("Prev | Index | Next"); + public function testIndexPage() + { + $this->get_page('post/list'); + $this->assert_title("Welcome to Shimmie"); + $this->assert_no_text("Prev | Index | Next"); - $this->log_in_as_user(); - $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - $this->log_out(); + $this->log_in_as_user(); + $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + $this->log_out(); - $this->get_page('post/list'); - $this->assert_title("Shimmie"); - // FIXME - //$this->assert_text("Prev | Index | Next"); + $this->get_page('post/list'); + $this->assert_title("Shimmie"); + // FIXME + //$this->assert_text("Prev | Index | Next"); - $this->get_page('post/list/-1'); - $this->assert_title("Shimmie"); + $this->get_page('post/list/-1'); + $this->assert_title("Shimmie"); - $this->get_page('post/list/0'); - $this->assert_title("Shimmie"); + $this->get_page('post/list/0'); + $this->assert_title("Shimmie"); - $this->get_page('post/list/1'); - $this->assert_title("Shimmie"); + $this->get_page('post/list/1'); + $this->assert_title("Shimmie"); - $this->get_page('post/list/99999'); - $this->assert_response(404); - } + $this->get_page('post/list/99999'); + $this->assert_response(404); + } - /* * * * * * * * * * * - * Tag Search * - * * * * * * * * * * */ - public function testTagSearchNoResults() { - $image_ids = $this->upload(); + /* * * * * * * * * * * + * Tag Search * + * * * * * * * * * * */ + public function testTagSearchNoResults() + { + $image_ids = $this->upload(); - $this->get_page('post/list/maumaumau/1'); - $this->assert_response(404); - } + $this->get_page('post/list/maumaumau/1'); + $this->assert_response(404); + } - public function testTagSearchOneResult() { - $image_ids = $this->upload(); + public function testTagSearchOneResult() + { + $image_ids = $this->upload(); - $this->get_page("post/list/pbx/1"); - $this->assert_response(302); - } + $this->get_page("post/list/pbx/1"); + $this->assert_response(302); + } - public function testTagSearchManyResults() { - $image_ids = $this->upload(); + public function testTagSearchManyResults() + { + $image_ids = $this->upload(); - $this->get_page('post/list/computer/1'); - $this->assert_response(200); - $this->assert_title("computer"); - } + $this->get_page('post/list/computer/1'); + $this->assert_response(200); + $this->assert_title("computer"); + } - /* * * * * * * * * * * - * Multi-Tag Search * - * * * * * * * * * * */ - public function testMultiTagSearchNoResults() { - $image_ids = $this->upload(); + /* * * * * * * * * * * + * Multi-Tag Search * + * * * * * * * * * * */ + public function testMultiTagSearchNoResults() + { + $image_ids = $this->upload(); - # multiple tags, one of which doesn't exist - # (test the "one tag doesn't exist = no hits" path) - $this->get_page('post/list/computer asdfasdfwaffle/1'); - $this->assert_response(404); - } + # multiple tags, one of which doesn't exist + # (test the "one tag doesn't exist = no hits" path) + $this->get_page('post/list/computer asdfasdfwaffle/1'); + $this->assert_response(404); + } - public function testMultiTagSearchOneResult() { - $image_ids = $this->upload(); + public function testMultiTagSearchOneResult() + { + $image_ids = $this->upload(); - $this->get_page('post/list/computer screenshot/1'); - $this->assert_response(302); - } + $this->get_page('post/list/computer screenshot/1'); + $this->assert_response(302); + } - public function testMultiTagSearchManyResults() { - $image_ids = $this->upload(); + public function testMultiTagSearchManyResults() + { + $image_ids = $this->upload(); - $this->get_page('post/list/computer thing/1'); - $this->assert_response(200); - } + $this->get_page('post/list/computer thing/1'); + $this->assert_response(200); + } - /* * * * * * * * * * * - * Meta Search * - * * * * * * * * * * */ - public function testMetaSearchNoResults() { - $this->get_page('post/list/hash=1234567890/1'); - $this->assert_response(404); - } + /* * * * * * * * * * * + * Meta Search * + * * * * * * * * * * */ + public function testMetaSearchNoResults() + { + $this->get_page('post/list/hash=1234567890/1'); + $this->assert_response(404); + } - public function testMetaSearchOneResult() { - $image_ids = $this->upload(); + public function testMetaSearchOneResult() + { + $image_ids = $this->upload(); - $this->get_page("post/list/hash=feb01bab5698a11dd87416724c7a89e3/1"); - $this->assert_response(302); + $this->get_page("post/list/hash=feb01bab5698a11dd87416724c7a89e3/1"); + $this->assert_response(302); - $this->get_page("post/list/md5=feb01bab5698a11dd87416724c7a89e3/1"); - $this->assert_response(302); + $this->get_page("post/list/md5=feb01bab5698a11dd87416724c7a89e3/1"); + $this->assert_response(302); - $this->get_page("post/list/id={$image_ids[1]}/1"); - $this->assert_response(302); + $this->get_page("post/list/id={$image_ids[1]}/1"); + $this->assert_response(302); - $this->get_page("post/list/filename=screenshot/1"); - $this->assert_response(302); + $this->get_page("post/list/filename=screenshot/1"); + $this->assert_response(302); + } - } + public function testMetaSearchManyResults() + { + $image_ids = $this->upload(); - public function testMetaSearchManyResults() { - $image_ids = $this->upload(); + $this->get_page('post/list/size=640x480/1'); + $this->assert_response(200); - $this->get_page('post/list/size=640x480/1'); - $this->assert_response(200); + $this->get_page("post/list/tags=5/1"); + $this->assert_response(200); - $this->get_page("post/list/tags=5/1"); - $this->assert_response(200); + $this->get_page("post/list/ext=jpg/1"); + $this->assert_response(200); + } - $this->get_page("post/list/ext=jpg/1"); - $this->assert_response(200); - } + /* * * * * * * * * * * + * Wildcards * + * * * * * * * * * * */ + public function testWildSearchNoResults() + { + $image_ids = $this->upload(); - /* * * * * * * * * * * - * Wildcards * - * * * * * * * * * * */ - public function testWildSearchNoResults() { - $image_ids = $this->upload(); + $this->get_page("post/list/asdfasdf*/1"); + $this->assert_response(404); + } - $this->get_page("post/list/asdfasdf*/1"); - $this->assert_response(404); - } + public function testWildSearchOneResult() + { + $image_ids = $this->upload(); - public function testWildSearchOneResult() { - $image_ids = $this->upload(); + global $database; + $db = $database->get_driver_name(); + if ($db == "pgsql" || $db == "sqlite") { + $this->markTestIncomplete(); + } - global $database; - $db = $database->get_driver_name(); - if($db == "pgsql" || $db == "sqlite") { - $this->markTestIncomplete(); - } + // Only the first image matches both the wildcard and the tag. + // This checks for https://github.com/shish/shimmie2/issues/547 + // (comp* is expanded to "computer computing", then we searched + // for images which match two or more of the tags in + // "computer computing screenshot") + $this->get_page("post/list/comp* screenshot/1"); + $this->assert_response(302); + } - // Only the first image matches both the wildcard and the tag. - // This checks for https://github.com/shish/shimmie2/issues/547 - // (comp* is expanded to "computer computing", then we searched - // for images which match two or more of the tags in - // "computer computing screenshot") - $this->get_page("post/list/comp* screenshot/1"); - $this->assert_response(302); - } + public function testWildSearchManyResults() + { + $image_ids = $this->upload(); - public function testWildSearchManyResults() { - $image_ids = $this->upload(); - - // two images match comp* - one matches it once, - // one matches it twice - $this->get_page("post/list/comp*/1"); - $this->assert_response(200); - } + // two images match comp* - one matches it once, + // one matches it twice + $this->get_page("post/list/comp*/1"); + $this->assert_response(200); + } - /* * * * * * * * * * * - * Mixed * - * * * * * * * * * * */ - public function testMixedSearchTagMeta() { - $image_ids = $this->upload(); + /* * * * * * * * * * * + * Mixed * + * * * * * * * * * * */ + public function testMixedSearchTagMeta() + { + $image_ids = $this->upload(); - # multiple tags, many results - $this->get_page('post/list/computer size=640x480/1'); - $this->assert_response(200); - } - // tag + negative - // wildcards + ??? + # multiple tags, many results + $this->get_page('post/list/computer size=640x480/1'); + $this->assert_response(200); + } + // tag + negative + // wildcards + ??? - /* * * * * * * * * * * - * Other * - * - negative tags * - * - wildcards * - * * * * * * * * * * */ - public function testOther() { - $this->markTestIncomplete(); + /* * * * * * * * * * * + * Other * + * - negative tags * + * - wildcards * + * * * * * * * * * * */ + public function testOther() + { + $this->markTestIncomplete(); - # negative tag, should have one result - $this->get_page('post/list/computer -pbx/1'); - $this->assert_response(302); + # negative tag, should have one result + $this->get_page('post/list/computer -pbx/1'); + $this->assert_response(302); - # negative tag alone, should work - # FIXME: known broken in mysql - //$this->get_page('post/list/-pbx/1'); - //$this->assert_response(302); + # negative tag alone, should work + # FIXME: known broken in mysql + //$this->get_page('post/list/-pbx/1'); + //$this->assert_response(302); - # test various search methods - $this->get_page("post/list/bedroo*/1"); - $this->assert_response(302); - } + # test various search methods + $this->get_page("post/list/bedroo*/1"); + $this->assert_response(302); + } } - diff --git a/ext/index/theme.php b/ext/index/theme.php index 4161cf3b..66195087 100644 --- a/ext/index/theme.php +++ b/ext/index/theme.php @@ -1,16 +1,21 @@ page_number = $page_number; - $this->total_pages = $total_pages; - $this->search_terms = $search_terms; - } + public function set_page(int $page_number, int $total_pages, array $search_terms) + { + $this->page_number = $page_number; + $this->total_pages = $total_pages; + $this->search_terms = $search_terms; + } - public function display_intro(Page $page) { - $text = " + public function display_intro(Page $page) + { + $text = "

    The first thing you'll probably want to do is create a new account; note that the first account you create will by default be marked as the board's @@ -22,55 +27,57 @@ and of course start organising your images :-)

    This message will go away once your first image is uploaded~

    "; - $page->set_title("Welcome to Shimmie ".VERSION); - $page->set_heading("Welcome to Shimmie"); - $page->add_block(new Block("Installation Succeeded!", $text, "main", 0)); - } + $page->set_title("Welcome to Shimmie ".VERSION); + $page->set_heading("Welcome to Shimmie"); + $page->add_block(new Block("Installation Succeeded!", $text, "main", 0)); + } - /** - * #param Image[] $images - */ - public function display_page(Page $page, array $images) { - $this->display_page_header($page, $images); + /** + * #param Image[] $images + */ + public function display_page(Page $page, array $images) + { + $this->display_page_header($page, $images); - $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); - $page->add_block(new Block("Navigation", $nav, "left", 0)); + $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); + $page->add_block(new Block("Navigation", $nav, "left", 0)); - if(count($images) > 0) { - $this->display_page_images($page, $images); - } - else { - $this->display_error(404, "No Images Found", "No images were found to match the search criteria"); - } - } + if (count($images) > 0) { + $this->display_page_images($page, $images); + } else { + $this->display_error(404, "No Images Found", "No images were found to match the search criteria"); + } + } - /** - * #param string[] $parts - */ - public function display_admin_block(array $parts) { - global $page; - $page->add_block(new Block("List Controls", join("
    ", $parts), "left", 50)); - } + /** + * #param string[] $parts + */ + public function display_admin_block(array $parts) + { + global $page; + $page->add_block(new Block("List Controls", join("
    ", $parts), "left", 50)); + } - /** - * #param string[] $search_terms - */ - protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string { - $prev = $page_number - 1; - $next = $page_number + 1; + /** + * #param string[] $search_terms + */ + protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string + { + $prev = $page_number - 1; + $next = $page_number + 1; - $u_tags = url_escape(Tag::implode($search_terms)); - $query = empty($u_tags) ? "" : '/'.$u_tags; + $u_tags = url_escape(Tag::implode($search_terms)); + $query = empty($u_tags) ? "" : '/'.$u_tags; - $h_prev = ($page_number <= 1) ? "Prev" : 'Prev'; - $h_index = "Index"; - $h_next = ($page_number >= $total_pages) ? "Next" : 'Next'; + $h_prev = ($page_number <= 1) ? "Prev" : 'Prev'; + $h_index = "Index"; + $h_next = ($page_number >= $total_pages) ? "Next" : 'Next'; - $h_search_string = html_escape(Tag::implode($search_terms)); - $h_search_link = make_link(); - $h_search = " + $h_search_string = html_escape(Tag::implode($search_terms)); + $h_search_link = make_link(); + $h_search = "

    @@ -78,61 +85,63 @@ and of course start organising your images :-)
    "; - return $h_prev.' | '.$h_index.' | '.$h_next.'
    '.$h_search; - } + return $h_prev.' | '.$h_index.' | '.$h_next.'
    '.$h_search; + } - /** - * #param Image[] $images - */ - protected function build_table(array $images, string $query): string { - $h_query = html_escape($query); - $table = "
    "; - foreach($images as $image) { - $table .= $this->build_thumb_html($image); - } - $table .= "
    "; - return $table; - } + /** + * #param Image[] $images + */ + protected function build_table(array $images, string $query): string + { + $h_query = html_escape($query); + $table = "
    "; + foreach ($images as $image) { + $table .= $this->build_thumb_html($image); + } + $table .= "
    "; + return $table; + } - /** - * #param Image[] $images - */ - protected function display_page_header(Page $page, array $images) { - global $config; + /** + * #param Image[] $images + */ + protected function display_page_header(Page $page, array $images) + { + global $config; - if (count($this->search_terms) == 0) { - $page_title = $config->get_string('title'); - } else { - $search_string = implode(' ', $this->search_terms); - $page_title = html_escape($search_string); - if (count($images) > 0) { - $page->set_subheading("Page {$this->page_number} / {$this->total_pages}"); - } - } - if ($this->page_number > 1 || count($this->search_terms) > 0) { - // $page_title .= " / $page_number"; - } + if (count($this->search_terms) == 0) { + $page_title = $config->get_string('title'); + } else { + $search_string = implode(' ', $this->search_terms); + $page_title = html_escape($search_string); + if (count($images) > 0) { + $page->set_subheading("Page {$this->page_number} / {$this->total_pages}"); + } + } + if ($this->page_number > 1 || count($this->search_terms) > 0) { + // $page_title .= " / $page_number"; + } - $page->set_title($page_title); - $page->set_heading($page_title); - } + $page->set_title($page_title); + $page->set_heading($page_title); + } - /** - * #param Image[] $images - */ - protected function display_page_images(Page $page, array $images) { - if (count($this->search_terms) > 0) { - if($this->page_number > 3) { - // only index the first pages of each term - $page->add_html_header(''); - } - $query = url_escape(implode(' ', $this->search_terms)); - $page->add_block(new Block("Images", $this->build_table($images, "#search=$query"), "main", 10, "image-list")); - $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages, TRUE); - } else { - $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10, "image-list")); - $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages, TRUE); - } - } + /** + * #param Image[] $images + */ + protected function display_page_images(Page $page, array $images) + { + if (count($this->search_terms) > 0) { + if ($this->page_number > 3) { + // only index the first pages of each term + $page->add_html_header(''); + } + $query = url_escape(implode(' ', $this->search_terms)); + $page->add_block(new Block("Images", $this->build_table($images, "#search=$query"), "main", 10, "image-list")); + $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages, true); + } else { + $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10, "image-list")); + $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages, true); + } + } } - diff --git a/ext/ipban/main.php b/ext/ipban/main.php index bb95ff98..659246f9 100644 --- a/ext/ipban/main.php +++ b/ext/ipban/main.php @@ -7,124 +7,141 @@ * Description: Ban IP addresses * Documentation: * Adding a Ban - *
    IP: Can be a single IP (eg. 123.234.210.21), or a CIDR block (eg. 152.23.43.0/24) - *
    Reason: Any text, for the admin to remember why the ban was put in place + *
    IP: Can be a single IP (eg. 123.234.210.21), or a CIDR block (eg. 152.23.43.0/24) + *
    Reason: Any text, for the admin to remember why the ban was put in place *
    Until: Either a date in YYYY-MM-DD format, or an offset like "3 days" */ // RemoveIPBanEvent {{{ -class RemoveIPBanEvent extends Event { - public $id; +class RemoveIPBanEvent extends Event +{ + public $id; - public function __construct(int $id) { - $this->id = $id; - } + public function __construct(int $id) + { + $this->id = $id; + } } // }}} // AddIPBanEvent {{{ -class AddIPBanEvent extends Event { - public $ip; - public $reason; - public $end; +class AddIPBanEvent extends Event +{ + public $ip; + public $reason; + public $end; - public function __construct(string $ip, string $reason, string $end) { - $this->ip = trim($ip); - $this->reason = trim($reason); - $this->end = trim($end); - } + public function __construct(string $ip, string $reason, string $end) + { + $this->ip = trim($ip); + $this->reason = trim($reason); + $this->end = trim($end); + } } // }}} -class IPBan extends Extension { - public function get_priority(): int {return 10;} +class IPBan extends Extension +{ + public function get_priority(): int + { + return 10; + } - public function onInitExt(InitExtEvent $event) { - global $config; - if($config->get_int("ext_ipban_version") < 8) { - $this->install(); - } - $config->set_default_string("ipban_message", -'

    IP $IP has been banned until $DATE by $ADMIN because of $REASON + public function onInitExt(InitExtEvent $event) + { + global $config; + if ($config->get_int("ext_ipban_version") < 8) { + $this->install(); + } + $config->set_default_string( + "ipban_message", + '

    IP $IP has been banned until $DATE by $ADMIN because of $REASON

    If you couldn\'t possibly be guilty of what you\'re banned for, the person we banned probably had a dynamic IP address and so do you.

    See http://whatismyipaddress.com/dynamic-static for more information. -

    $CONTACT'); - $this->check_ip_ban(); - } +

    $CONTACT' + ); + $this->check_ip_ban(); + } - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("ip_ban")) { - global $page, $user; - if($user->can("ban_ip")) { - if($event->get_arg(0) == "add" && $user->check_auth_token()) { - if(isset($_POST['ip']) && isset($_POST['reason']) && isset($_POST['end'])) { - if(empty($_POST['end'])) $end = null; - else $end = $_POST['end']; - send_event(new AddIPBanEvent($_POST['ip'], $_POST['reason'], $end)); + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("ip_ban")) { + global $page, $user; + if ($user->can("ban_ip")) { + if ($event->get_arg(0) == "add" && $user->check_auth_token()) { + if (isset($_POST['ip']) && isset($_POST['reason']) && isset($_POST['end'])) { + if (empty($_POST['end'])) { + $end = null; + } else { + $end = $_POST['end']; + } + send_event(new AddIPBanEvent($_POST['ip'], $_POST['reason'], $end)); - flash_message("Ban for {$_POST['ip']} added"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("ip_ban/list")); - } - } - else if($event->get_arg(0) == "remove" && $user->check_auth_token()) { - if(isset($_POST['id'])) { - send_event(new RemoveIPBanEvent($_POST['id'])); + flash_message("Ban for {$_POST['ip']} added"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("ip_ban/list")); + } + } elseif ($event->get_arg(0) == "remove" && $user->check_auth_token()) { + if (isset($_POST['id'])) { + send_event(new RemoveIPBanEvent($_POST['id'])); - flash_message("Ban removed"); - $page->set_mode("redirect"); - $page->set_redirect(make_link("ip_ban/list")); - } - } - else if($event->get_arg(0) == "list") { - $bans = (isset($_GET["all"])) ? $this->get_bans() : $this->get_active_bans(); - $this->theme->display_bans($page, $bans); - } - } - else { - $this->theme->display_permission_denied(); - } - } - } + flash_message("Ban removed"); + $page->set_mode("redirect"); + $page->set_redirect(make_link("ip_ban/list")); + } + } elseif ($event->get_arg(0) == "list") { + $bans = (isset($_GET["all"])) ? $this->get_bans() : $this->get_active_bans(); + $this->theme->display_bans($page, $bans); + } + } else { + $this->theme->display_permission_denied(); + } + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("IP Ban"); - $sb->add_longtext_option("ipban_message", 'Message to show to banned users:
    (with $IP, $DATE, $ADMIN, $REASON, and $CONTACT)'); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("IP Ban"); + $sb->add_longtext_option("ipban_message", 'Message to show to banned users:
    (with $IP, $DATE, $ADMIN, $REASON, and $CONTACT)'); + $event->panel->add_block($sb); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("ban_ip")) { - $event->add_link("IP Bans", make_link("ip_ban/list")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("ban_ip")) { + $event->add_link("IP Bans", make_link("ip_ban/list")); + } + } - public function onAddIPBan(AddIPBanEvent $event) { - global $user, $database; - $sql = "INSERT INTO bans (ip, reason, end_timestamp, banner_id) VALUES (:ip, :reason, :end, :admin_id)"; - $database->Execute($sql, array("ip"=>$event->ip, "reason"=>$event->reason, "end"=>strtotime($event->end), "admin_id"=>$user->id)); - $database->cache->delete("ip_bans_sorted"); - log_info("ipban", "Banned {$event->ip} because '{$event->reason}' until {$event->end}"); - } + public function onAddIPBan(AddIPBanEvent $event) + { + global $user, $database; + $sql = "INSERT INTO bans (ip, reason, end_timestamp, banner_id) VALUES (:ip, :reason, :end, :admin_id)"; + $database->Execute($sql, ["ip"=>$event->ip, "reason"=>$event->reason, "end"=>strtotime($event->end), "admin_id"=>$user->id]); + $database->cache->delete("ip_bans_sorted"); + log_info("ipban", "Banned {$event->ip} because '{$event->reason}' until {$event->end}"); + } - public function onRemoveIPBan(RemoveIPBanEvent $event) { - global $database; - $ban = $database->get_row("SELECT * FROM bans WHERE id = :id", array("id"=>$event->id)); - if($ban) { - $database->Execute("DELETE FROM bans WHERE id = :id", array("id"=>$event->id)); - $database->cache->delete("ip_bans_sorted"); - log_info("ipban", "Removed {$ban['ip']}'s ban"); - } - } + public function onRemoveIPBan(RemoveIPBanEvent $event) + { + global $database; + $ban = $database->get_row("SELECT * FROM bans WHERE id = :id", ["id"=>$event->id]); + if ($ban) { + $database->Execute("DELETE FROM bans WHERE id = :id", ["id"=>$event->id]); + $database->cache->delete("ip_bans_sorted"); + log_info("ipban", "Removed {$ban['ip']}'s ban"); + } + } -// installer {{{ - protected function install() { - global $database; - global $config; + // installer {{{ + protected function install() + { + global $database; + global $config; - // shortcut to latest - if($config->get_int("ext_ipban_version") < 1) { - $database->create_table("bans", " + // shortcut to latest + if ($config->get_int("ext_ipban_version") < 1) { + $database->create_table("bans", " id SCORE_AIPK, banner_id INTEGER NOT NULL, ip SCORE_INET NOT NULL, @@ -133,14 +150,14 @@ class IPBan extends Extension { added SCORE_DATETIME NOT NULL DEFAULT SCORE_NOW, FOREIGN KEY (banner_id) REFERENCES users(id) ON DELETE CASCADE, "); - $database->execute("CREATE INDEX bans__end_timestamp ON bans(end_timestamp)"); - $config->set_int("ext_ipban_version", 8); - } + $database->execute("CREATE INDEX bans__end_timestamp ON bans(end_timestamp)"); + $config->set_int("ext_ipban_version", 8); + } - // === + // === - if($config->get_int("ext_ipban_version") < 1) { - $database->Execute("CREATE TABLE bans ( + if ($config->get_int("ext_ipban_version") < 1) { + $database->Execute("CREATE TABLE bans ( id int(11) NOT NULL auto_increment, ip char(15) default NULL, date SCORE_DATETIME default NULL, @@ -148,160 +165,170 @@ class IPBan extends Extension { reason varchar(255) default NULL, PRIMARY KEY (id) )"); - $config->set_int("ext_ipban_version", 1); - } + $config->set_int("ext_ipban_version", 1); + } - if($config->get_int("ext_ipban_version") == 1) { - $database->execute("ALTER TABLE bans ADD COLUMN banner_id INTEGER NOT NULL AFTER id"); - $config->set_int("ext_ipban_version", 2); - } + if ($config->get_int("ext_ipban_version") == 1) { + $database->execute("ALTER TABLE bans ADD COLUMN banner_id INTEGER NOT NULL AFTER id"); + $config->set_int("ext_ipban_version", 2); + } - if($config->get_int("ext_ipban_version") == 2) { - $database->execute("ALTER TABLE bans DROP COLUMN date"); - $database->execute("ALTER TABLE bans CHANGE ip ip CHAR(20) NOT NULL"); - $database->execute("ALTER TABLE bans CHANGE reason reason TEXT NOT NULL"); - $database->execute("CREATE INDEX bans__end ON bans(end)"); - $config->set_int("ext_ipban_version", 3); - } + if ($config->get_int("ext_ipban_version") == 2) { + $database->execute("ALTER TABLE bans DROP COLUMN date"); + $database->execute("ALTER TABLE bans CHANGE ip ip CHAR(20) NOT NULL"); + $database->execute("ALTER TABLE bans CHANGE reason reason TEXT NOT NULL"); + $database->execute("CREATE INDEX bans__end ON bans(end)"); + $config->set_int("ext_ipban_version", 3); + } - if($config->get_int("ext_ipban_version") == 3) { - $database->execute("ALTER TABLE bans CHANGE end old_end DATE NOT NULL"); - $database->execute("ALTER TABLE bans ADD COLUMN end INTEGER"); - $database->execute("UPDATE bans SET end = UNIX_TIMESTAMP(old_end)"); - $database->execute("ALTER TABLE bans DROP COLUMN old_end"); - $database->execute("CREATE INDEX bans__end ON bans(end)"); - $config->set_int("ext_ipban_version", 4); - } + if ($config->get_int("ext_ipban_version") == 3) { + $database->execute("ALTER TABLE bans CHANGE end old_end DATE NOT NULL"); + $database->execute("ALTER TABLE bans ADD COLUMN end INTEGER"); + $database->execute("UPDATE bans SET end = UNIX_TIMESTAMP(old_end)"); + $database->execute("ALTER TABLE bans DROP COLUMN old_end"); + $database->execute("CREATE INDEX bans__end ON bans(end)"); + $config->set_int("ext_ipban_version", 4); + } - if($config->get_int("ext_ipban_version") == 4) { - $database->execute("ALTER TABLE bans CHANGE end end_timestamp INTEGER"); - $config->set_int("ext_ipban_version", 5); - } + if ($config->get_int("ext_ipban_version") == 4) { + $database->execute("ALTER TABLE bans CHANGE end end_timestamp INTEGER"); + $config->set_int("ext_ipban_version", 5); + } - if($config->get_int("ext_ipban_version") == 5) { - $database->execute("ALTER TABLE bans CHANGE ip ip VARCHAR(15)"); - $config->set_int("ext_ipban_version", 6); - } + if ($config->get_int("ext_ipban_version") == 5) { + $database->execute("ALTER TABLE bans CHANGE ip ip VARCHAR(15)"); + $config->set_int("ext_ipban_version", 6); + } - if($config->get_int("ext_ipban_version") == 6) { - $database->Execute("ALTER TABLE bans ADD FOREIGN KEY (banner_id) REFERENCES users(id) ON DELETE CASCADE"); - $config->set_int("ext_ipban_version", 7); - } + if ($config->get_int("ext_ipban_version") == 6) { + $database->Execute("ALTER TABLE bans ADD FOREIGN KEY (banner_id) REFERENCES users(id) ON DELETE CASCADE"); + $config->set_int("ext_ipban_version", 7); + } - if($config->get_int("ext_ipban_version") == 7) { - $database->execute($database->scoreql_to_sql("ALTER TABLE bans CHANGE ip ip SCORE_INET")); - $database->execute($database->scoreql_to_sql("ALTER TABLE bans ADD COLUMN added SCORE_DATETIME NOT NULL DEFAULT SCORE_NOW")); - $config->set_int("ext_ipban_version", 8); - } - } -// }}} -// deal with banned person {{{ - private function check_ip_ban() { - $remote = $_SERVER['REMOTE_ADDR']; - $bans = $this->get_active_bans_sorted(); + if ($config->get_int("ext_ipban_version") == 7) { + $database->execute($database->scoreql_to_sql("ALTER TABLE bans CHANGE ip ip SCORE_INET")); + $database->execute($database->scoreql_to_sql("ALTER TABLE bans ADD COLUMN added SCORE_DATETIME NOT NULL DEFAULT SCORE_NOW")); + $config->set_int("ext_ipban_version", 8); + } + } + // }}} + // deal with banned person {{{ + private function check_ip_ban() + { + $remote = $_SERVER['REMOTE_ADDR']; + $bans = $this->get_active_bans_sorted(); - // bans[0] = IPs - if(isset($bans[0][$remote])) { - $this->block($remote); // never returns - } + // bans[0] = IPs + if (isset($bans[0][$remote])) { + $this->block($remote); // never returns + } - // bans[1] = CIDR nets - foreach($bans[1] as $ip => $true) { - if(ip_in_range($remote, $ip)) { - $this->block($remote); // never returns - } - } - } + // bans[1] = CIDR nets + foreach ($bans[1] as $ip => $true) { + if (ip_in_range($remote, $ip)) { + $this->block($remote); // never returns + } + } + } - private function block(string $remote) { - global $config, $database; + private function block(string $remote) + { + global $config, $database; - $prefix = ($database->get_driver_name() == "sqlite" ? "bans." : ""); + $prefix = ($database->get_driver_name() == "sqlite" ? "bans." : ""); - $bans = $this->get_active_bans(); + $bans = $this->get_active_bans(); - foreach($bans as $row) { - $ip = $row[$prefix."ip"]; - if( - (strstr($ip, '/') && ip_in_range($remote, $ip)) || - ($ip == $remote) - ) { - $reason = $row[$prefix.'reason']; - $admin = User::by_id($row[$prefix.'banner_id']); - $date = date("Y-m-d", $row[$prefix.'end_timestamp']); - $msg = $config->get_string("ipban_message"); - $msg = str_replace('$IP', $ip, $msg); - $msg = str_replace('$DATE', $date, $msg); - $msg = str_replace('$ADMIN', $admin->name, $msg); - $msg = str_replace('$REASON', $reason, $msg); - $contact_link = contact_link(); - if(!empty($contact_link)) { - $msg = str_replace('$CONTACT', "Contact the staff (be sure to include this message)", $msg); - } - else { - $msg = str_replace('$CONTACT', "", $msg); - } - header("HTTP/1.0 403 Forbidden"); - print "$msg"; + foreach ($bans as $row) { + $ip = $row[$prefix."ip"]; + if ( + (strstr($ip, '/') && ip_in_range($remote, $ip)) || + ($ip == $remote) + ) { + $reason = $row[$prefix.'reason']; + $admin = User::by_id($row[$prefix.'banner_id']); + $date = date("Y-m-d", $row[$prefix.'end_timestamp']); + $msg = $config->get_string("ipban_message"); + $msg = str_replace('$IP', $ip, $msg); + $msg = str_replace('$DATE', $date, $msg); + $msg = str_replace('$ADMIN', $admin->name, $msg); + $msg = str_replace('$REASON', $reason, $msg); + $contact_link = contact_link(); + if (!empty($contact_link)) { + $msg = str_replace('$CONTACT', "Contact the staff (be sure to include this message)", $msg); + } else { + $msg = str_replace('$CONTACT', "", $msg); + } + header("HTTP/1.0 403 Forbidden"); + print "$msg"; - exit; - } - } - log_error("ipban", "block($remote) called but no bans matched"); - exit; - } -// }}} -// database {{{ - private function get_bans() { - global $database; - $bans = $database->get_all(" + exit; + } + } + log_error("ipban", "block($remote) called but no bans matched"); + exit; + } + // }}} + // database {{{ + private function get_bans() + { + global $database; + $bans = $database->get_all(" SELECT bans.*, users.name as banner_name FROM bans JOIN users ON banner_id = users.id ORDER BY added, end_timestamp, bans.id "); - if($bans) {return $bans;} - else {return array();} - } + if ($bans) { + return $bans; + } else { + return []; + } + } - private function get_active_bans() { - global $database; + private function get_active_bans() + { + global $database; - $bans = $database->get_all(" + $bans = $database->get_all(" SELECT bans.*, users.name as banner_name FROM bans JOIN users ON banner_id = users.id WHERE (end_timestamp > :end_timestamp) OR (end_timestamp IS NULL) ORDER BY end_timestamp, bans.id - ", array("end_timestamp"=>time())); + ", ["end_timestamp"=>time()]); - if($bans) {return $bans;} - else {return array();} - } + if ($bans) { + return $bans; + } else { + return []; + } + } - // returns [ips, nets] - private function get_active_bans_sorted() { - global $database; + // returns [ips, nets] + private function get_active_bans_sorted() + { + global $database; - $cached = $database->cache->get("ip_bans_sorted"); - if($cached) return $cached; + $cached = $database->cache->get("ip_bans_sorted"); + if ($cached) { + return $cached; + } - $bans = $this->get_active_bans(); - $ips = array(); # "0.0.0.0" => false); - $nets = array(); # "0.0.0.0/32" => false); - foreach($bans as $row) { - if(strstr($row['ip'], '/')) { - $nets[$row['ip']] = true; - } - else { - $ips[$row['ip']] = true; - } - } + $bans = $this->get_active_bans(); + $ips = []; # "0.0.0.0" => false); + $nets = []; # "0.0.0.0/32" => false); + foreach ($bans as $row) { + if (strstr($row['ip'], '/')) { + $nets[$row['ip']] = true; + } else { + $ips[$row['ip']] = true; + } + } - $sorted = array($ips, $nets); - $database->cache->set("ip_bans_sorted", $sorted, 600); - return $sorted; - } -// }}} + $sorted = [$ips, $nets]; + $database->cache->set("ip_bans_sorted", $sorted, 600); + return $sorted; + } + // }}} } - diff --git a/ext/ipban/test.php b/ext/ipban/test.php index ec0dfe0b..12816dab 100644 --- a/ext/ipban/test.php +++ b/ext/ipban/test.php @@ -1,29 +1,30 @@ get_page('ip_ban/list'); - $this->assert_response(403); - $this->assert_title("Permission Denied"); +class IPBanTest extends ShimmiePHPUnitTestCase +{ + public function testIPBan() + { + $this->get_page('ip_ban/list'); + $this->assert_response(403); + $this->assert_title("Permission Denied"); - $this->log_in_as_admin(); + $this->log_in_as_admin(); - $this->get_page('ip_ban/list'); - $this->assert_no_text("42.42.42.42"); + $this->get_page('ip_ban/list'); + $this->assert_no_text("42.42.42.42"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field('ip', '42.42.42.42'); - $this->set_field('reason', 'unit testing'); - $this->set_field('end', '1 week'); - $this->click("Ban"); + $this->set_field('ip', '42.42.42.42'); + $this->set_field('reason', 'unit testing'); + $this->set_field('end', '1 week'); + $this->click("Ban"); - $this->assert_text("42.42.42.42"); - $this->click("Remove"); // FIXME: remove which ban? :S - $this->assert_no_text("42.42.42.42"); + $this->assert_text("42.42.42.42"); + $this->click("Remove"); // FIXME: remove which ban? :S + $this->assert_no_text("42.42.42.42"); - $this->get_page('ip_ban/list?all=on'); // just test it doesn't crash for now + $this->get_page('ip_ban/list?all=on'); // just test it doesn't crash for now - # FIXME: test that the IP is actually banned - } + # FIXME: test that the IP is actually banned + } } - diff --git a/ext/ipban/theme.php b/ext/ipban/theme.php index a2f14f21..6529c51f 100644 --- a/ext/ipban/theme.php +++ b/ext/ipban/theme.php @@ -1,23 +1,25 @@ the banned IP - * 'reason' => why the IP was banned - * 'date' => when the ban started - * 'end' => when the ban will end - * ) - */ - public function display_bans(Page $page, $bans) { - global $database, $user; - $h_bans = ""; - $prefix = ($database->get_driver_name() == "sqlite" ? "bans." : ""); - foreach($bans as $ban) { - $end_human = date('Y-m-d', $ban[$prefix.'end_timestamp']); - $h_bans .= " +class IPBanTheme extends Themelet +{ + /* + * Show all the bans + * + * $bans = an array of ( + * 'ip' => the banned IP + * 'reason' => why the IP was banned + * 'date' => when the ban started + * 'end' => when the ban will end + * ) + */ + public function display_bans(Page $page, $bans) + { + global $database, $user; + $h_bans = ""; + $prefix = ($database->get_driver_name() == "sqlite" ? "bans." : ""); + foreach ($bans as $ban) { + $end_human = date('Y-m-d', $ban[$prefix.'end_timestamp']); + $h_bans .= " {$ban[$prefix.'ip']} {$ban[$prefix.'reason']} @@ -32,8 +34,8 @@ class IPBanTheme extends Themelet { "; - } - $html = " + } + $html = " Show All

    @@ -50,10 +52,9 @@ class IPBanTheme extends Themelet {
    IPReasonByFromUntilAction
    "; - $page->set_title("IP Bans"); - $page->set_heading("IP Bans"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Edit IP Bans", $html)); - } + $page->set_title("IP Bans"); + $page->set_heading("IP Bans"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Edit IP Bans", $html)); + } } - diff --git a/ext/link_image/main.php b/ext/link_image/main.php index 859d510f..39c94c38 100644 --- a/ext/link_image/main.php +++ b/ext/link_image/main.php @@ -4,34 +4,38 @@ * Author: Artanis * Description: Show various forms of link to each image, for copy & paste */ -class LinkImage extends Extension { - public function onDisplayingImage(DisplayingImageEvent $event) { - global $page; - $this->theme->links_block($page, $this->data($event->image)); - } +class LinkImage extends Extension +{ + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $page; + $this->theme->links_block($page, $this->data($event->image)); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Link to Image"); - $sb->add_text_option("ext_link-img_text-link_format", "Text Link Format: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Link to Image"); + $sb->add_text_option("ext_link-img_text-link_format", "Text Link Format: "); + $event->panel->add_block($sb); + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string("ext_link-img_text-link_format", '$title - $id ($ext $size $filesize)'); - } + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string("ext_link-img_text-link_format", '$title - $id ($ext $size $filesize)'); + } - private function data(Image $image) { - global $config; + private function data(Image $image) + { + global $config; - $text_link = $image->parse_link_template($config->get_string("ext_link-img_text-link_format")); - $text_link = trim($text_link) == "" ? null : $text_link; // null blank setting so the url gets filled in on the text links. + $text_link = $image->parse_link_template($config->get_string("ext_link-img_text-link_format")); + $text_link = trim($text_link) == "" ? null : $text_link; // null blank setting so the url gets filled in on the text links. - return array( - 'thumb_src' => make_http($image->get_thumb_link()), - 'image_src' => make_http($image->get_image_link()), - 'post_link' => make_http(make_link("post/view/{$image->id}")), - 'text_link' => $text_link); - } + return [ + 'thumb_src' => make_http($image->get_thumb_link()), + 'image_src' => make_http($image->get_image_link()), + 'post_link' => make_http(make_link("post/view/{$image->id}")), + 'text_link' => $text_link]; + } } - diff --git a/ext/link_image/test.php b/ext/link_image/test.php index ca8e6f9b..16fa07e8 100644 --- a/ext/link_image/test.php +++ b/ext/link_image/test.php @@ -1,24 +1,25 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pie"); +class LinkImageTest extends ShimmiePHPUnitTestCase +{ + public function testLinkImage() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pie"); - # FIXME - # look in the "plain text link to post" box, follow the link - # in there, see if it takes us to the right page - $this->get_page("post/view/$image_id"); + # FIXME + # look in the "plain text link to post" box, follow the link + # in there, see if it takes us to the right page + $this->get_page("post/view/$image_id"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - // FIXME - $matches = array(); - preg_match("#value='(http://.*(/|%2F)post(/|%2F)view(/|%2F)[0-9]+)'#", $raw, $matches); - $this->assertTrue(count($matches) > 0); - if($matches) { - $this->get($matches[1]); - $this->assert_title("Image $image_id: pie"); - } - } + // FIXME + $matches = []; + preg_match("#value='(http://.*(/|%2F)post(/|%2F)view(/|%2F)[0-9]+)'#", $raw, $matches); + $this->assertTrue(count($matches) > 0); + if ($matches) { + $this->get($matches[1]); + $this->assert_title("Image $image_id: pie"); + } + } } - diff --git a/ext/link_image/theme.php b/ext/link_image/theme.php index 1eb7c48e..baf5c62f 100644 --- a/ext/link_image/theme.php +++ b/ext/link_image/theme.php @@ -1,25 +1,27 @@ add_block( new Block( - "Link to Image", - " + $page->add_block(new Block( + "Link to Image", + " @@ -27,10 +29,10 @@ class LinkImageTheme extends Themelet { HTML
    BBCode ". - $this->link_code("Link",$this->url($post_link, $text_link,"ubb"),"ubb_text-link"). - $this->link_code("Thumb",$this->url($post_link, $this->img($thumb_src,"ubb"),"ubb"),"ubb_thumb-link"). - $this->link_code("Image", $this->img($image_src,"ubb"), "ubb_full-img"). - " + $this->link_code("Link", $this->url($post_link, $text_link, "ubb"), "ubb_text-link"). + $this->link_code("Thumb", $this->url($post_link, $this->img($thumb_src, "ubb"), "ubb"), "ubb_thumb-link"). + $this->link_code("Image", $this->img($image_src, "ubb"), "ubb_full-img"). + "
    ". - $this->link_code("Link", $this->url($post_link, $text_link,"html"), "html_text-link"). - $this->link_code("Thumb", $this->url($post_link,$this->img($thumb_src,"html"),"html"), "html_thumb-link"). - $this->link_code("Image", $this->img($image_src,"html"), "html_full-image"). - " + $this->link_code("Link", $this->url($post_link, $text_link, "html"), "html_text-link"). + $this->link_code("Thumb", $this->url($post_link, $this->img($thumb_src, "html"), "html"), "html_thumb-link"). + $this->link_code("Image", $this->img($image_src, "html"), "html_full-image"). + "
    @@ -38,56 +40,61 @@ class LinkImageTheme extends Themelet { Plain Text ". - $this->link_code("Link",$post_link,"text_post-link"). - $this->link_code("Thumb",$thumb_src,"text_thumb-url"). - $this->link_code("Image",$image_src,"text_image-src"). - " + $this->link_code("Link", $post_link, "text_post-link"). + $this->link_code("Thumb", $thumb_src, "text_thumb-url"). + $this->link_code("Image", $image_src, "text_image-src"). + "
    ", - "main", - 50)); - } + "main", + 50 + )); + } - protected function url (string $url, string $content, string $type) { - if ($content == NULL) {$content=$url;} + protected function url(string $url, string $content, string $type) + { + if ($content == null) { + $content=$url; + } - switch ($type) { - case "html": - $text = "".$content.""; - break; - case "ubb": - $text = "[url=".$url."]".$content."[/url]"; - break; - default: - $text = $url." - ".$content; - } - return $text; - } + switch ($type) { + case "html": + $text = "".$content.""; + break; + case "ubb": + $text = "[url=".$url."]".$content."[/url]"; + break; + default: + $text = $url." - ".$content; + } + return $text; + } - protected function img (string $src, string $type) { - switch ($type) { - case "html": - $text = ""; - break; - case "ubb": - $text = "[img]".$src."[/img]"; - break; - default: - $text = $src; - } - return $text; - } + protected function img(string $src, string $type) + { + switch ($type) { + case "html": + $text = ""; + break; + case "ubb": + $text = "[img]".$src."[/img]"; + break; + default: + $text = $src; + } + return $text; + } - protected function link_code(string $label, string $content, $id=NULL) { - return " + protected function link_code(string $label, string $content, $id=null) + { + return " "; - } + } } - diff --git a/ext/livefeed/main.php b/ext/livefeed/main.php index 79874b45..add2f21b 100644 --- a/ext/livefeed/main.php +++ b/ext/livefeed/main.php @@ -8,60 +8,75 @@ * Documentation: */ -class LiveFeed extends Extension { - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Live Feed"); - $sb->add_text_option("livefeed_host", "IP:port to send events to: "); - $event->panel->add_block($sb); - } +class LiveFeed extends Extension +{ + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Live Feed"); + $sb->add_text_option("livefeed_host", "IP:port to send events to: "); + $event->panel->add_block($sb); + } - public function onUserCreation(UserCreationEvent $event) { - $this->msg("New user created: {$event->username}"); - } + public function onUserCreation(UserCreationEvent $event) + { + $this->msg("New user created: {$event->username}"); + } - public function onImageAddition(ImageAdditionEvent $event) { - global $user; - $this->msg( - make_http(make_link("post/view/".$event->image->id))." - ". - "new post by ".$user->name - ); - } + public function onImageAddition(ImageAdditionEvent $event) + { + global $user; + $this->msg( + make_http(make_link("post/view/".$event->image->id))." - ". + "new post by ".$user->name + ); + } - public function onTagSet(TagSetEvent $event) { - $this->msg( - make_http(make_link("post/view/".$event->image->id))." - ". - "tags set to: ".Tag::implode($event->tags) - ); - } + public function onTagSet(TagSetEvent $event) + { + $this->msg( + make_http(make_link("post/view/".$event->image->id))." - ". + "tags set to: ".Tag::implode($event->tags) + ); + } - public function onCommentPosting(CommentPostingEvent $event) { - global $user; - $this->msg( - make_http(make_link("post/view/".$event->image_id))." - ". - $user->name . ": " . str_replace("\n", " ", $event->comment) - ); - } + public function onCommentPosting(CommentPostingEvent $event) + { + global $user; + $this->msg( + make_http(make_link("post/view/".$event->image_id))." - ". + $user->name . ": " . str_replace("\n", " ", $event->comment) + ); + } - public function onImageInfoSet(ImageInfoSetEvent $event) { -# $this->msg("Image info set"); - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + # $this->msg("Image info set"); + } - public function get_priority(): int {return 99;} + public function get_priority(): int + { + return 99; + } - private function msg(string $data) { - global $config; + private function msg(string $data) + { + global $config; - $host = $config->get_string("livefeed_host", "127.0.0.1:25252"); + $host = $config->get_string("livefeed_host", "127.0.0.1:25252"); - if(!$host) { return; } + if (!$host) { + return; + } try { - $parts = explode(":", $host); + $parts = explode(":", $host); $host = $parts[0]; $port = $parts[1]; $fp = fsockopen("udp://$host", $port, $errno, $errstr); - if (! $fp) { return; } - fwrite($fp, "$data\n"); + if (! $fp) { + return; + } + fwrite($fp, "$data\n"); fclose($fp); } catch (Exception $e) { /* logging errors shouldn't break everything */ diff --git a/ext/log_db/main.php b/ext/log_db/main.php index aef29763..b185c783 100644 --- a/ext/log_db/main.php +++ b/ext/log_db/main.php @@ -7,13 +7,15 @@ * Visibility: admin */ -class LogDatabase extends Extension { - public function onInitExt(InitExtEvent $event) { - global $database; - global $config; +class LogDatabase extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $database; + global $config; - if($config->get_int("ext_log_database_version") < 1) { - $database->create_table("score_log", " + if ($config->get_int("ext_log_database_version") < 1) { + $database->create_table("score_log", " id SCORE_AIPK, date_sent SCORE_DATETIME NOT NULL, section VARCHAR(32) NOT NULL, @@ -22,125 +24,129 @@ class LogDatabase extends Extension { priority INT NOT NULL, message TEXT NOT NULL "); - //INDEX(section) - $config->set_int("ext_log_database_version", 1); - } + //INDEX(section) + $config->set_int("ext_log_database_version", 1); + } - $config->set_default_int("log_db_priority", SCORE_LOG_INFO); - } + $config->set_default_int("log_db_priority", SCORE_LOG_INFO); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Logging (Database)"); - $sb->add_choice_option("log_db_priority", array( - "Debug" => SCORE_LOG_DEBUG, - "Info" => SCORE_LOG_INFO, - "Warning" => SCORE_LOG_WARNING, - "Error" => SCORE_LOG_ERROR, - "Critical" => SCORE_LOG_CRITICAL, - ), "Debug Level: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Logging (Database)"); + $sb->add_choice_option("log_db_priority", [ + "Debug" => SCORE_LOG_DEBUG, + "Info" => SCORE_LOG_INFO, + "Warning" => SCORE_LOG_WARNING, + "Error" => SCORE_LOG_ERROR, + "Critical" => SCORE_LOG_CRITICAL, + ], "Debug Level: "); + $event->panel->add_block($sb); + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $user; - if($event->page_matches("log/view")) { - if($user->can("view_eventlog")) { - $wheres = array(); - $args = array(); - $page_num = int_escape($event->get_arg(0)); - if($page_num <= 0) $page_num = 1; - if(!empty($_GET["time-start"])) { - $wheres[] = "date_sent > :time_start"; - $args["time_start"] = $_GET["time-start"]; - } - if(!empty($_GET["time-end"])) { - $wheres[] = "date_sent < :time_end"; - $args["time_end"] = $_GET["time-end"]; - } - if(!empty($_GET["module"])) { - $wheres[] = "section = :module"; - $args["module"] = $_GET["module"]; - } - if(!empty($_GET["user"])) { - if($database->get_driver_name() == "pgsql") { - if(preg_match("#\d+\.\d+\.\d+\.\d+(/\d+)?#", $_GET["user"])) { - $wheres[] = "(username = :user1 OR text(address) = :user2)"; - $args["user1"] = $_GET["user"]; - $args["user2"] = $_GET["user"] . "/32"; - } - else { - $wheres[] = "lower(username) = lower(:user)"; - $args["user"] = $_GET["user"]; - } - } - else { - $wheres[] = "(username = :user1 OR address = :user2)"; - $args["user1"] = $_GET["user"]; - $args["user2"] = $_GET["user"]; - } - } - if(!empty($_GET["priority"])) { - $wheres[] = "priority >= :priority"; - $args["priority"] = int_escape($_GET["priority"]); - } - else { - $wheres[] = "priority >= :priority"; - $args["priority"] = 20; - } - if(!empty($_GET["message"])) { - $wheres[] = $database->scoreql_to_sql("SCORE_STRNORM(message) LIKE SCORE_STRNORM(:message)"); - $args["message"] = "%" . $_GET["message"] . "%"; - } - $where = ""; - if(count($wheres) > 0) { - $where = "WHERE "; - $where .= join(" AND ", $wheres); - } + public function onPageRequest(PageRequestEvent $event) + { + global $database, $user; + if ($event->page_matches("log/view")) { + if ($user->can("view_eventlog")) { + $wheres = []; + $args = []; + $page_num = int_escape($event->get_arg(0)); + if ($page_num <= 0) { + $page_num = 1; + } + if (!empty($_GET["time-start"])) { + $wheres[] = "date_sent > :time_start"; + $args["time_start"] = $_GET["time-start"]; + } + if (!empty($_GET["time-end"])) { + $wheres[] = "date_sent < :time_end"; + $args["time_end"] = $_GET["time-end"]; + } + if (!empty($_GET["module"])) { + $wheres[] = "section = :module"; + $args["module"] = $_GET["module"]; + } + if (!empty($_GET["user"])) { + if ($database->get_driver_name() == "pgsql") { + if (preg_match("#\d+\.\d+\.\d+\.\d+(/\d+)?#", $_GET["user"])) { + $wheres[] = "(username = :user1 OR text(address) = :user2)"; + $args["user1"] = $_GET["user"]; + $args["user2"] = $_GET["user"] . "/32"; + } else { + $wheres[] = "lower(username) = lower(:user)"; + $args["user"] = $_GET["user"]; + } + } else { + $wheres[] = "(username = :user1 OR address = :user2)"; + $args["user1"] = $_GET["user"]; + $args["user2"] = $_GET["user"]; + } + } + if (!empty($_GET["priority"])) { + $wheres[] = "priority >= :priority"; + $args["priority"] = int_escape($_GET["priority"]); + } else { + $wheres[] = "priority >= :priority"; + $args["priority"] = 20; + } + if (!empty($_GET["message"])) { + $wheres[] = $database->scoreql_to_sql("SCORE_STRNORM(message) LIKE SCORE_STRNORM(:message)"); + $args["message"] = "%" . $_GET["message"] . "%"; + } + $where = ""; + if (count($wheres) > 0) { + $where = "WHERE "; + $where .= join(" AND ", $wheres); + } - $limit = 50; - $offset = ($page_num-1) * $limit; - $page_total = $database->cache->get("event_log_length"); - if(!$page_total) { - $page_total = $database->get_one("SELECT count(*) FROM score_log $where", $args); - // don't cache a length of zero when the extension is first installed - if($page_total > 10) { - $database->cache->set("event_log_length", $page_total, 600); - } - } + $limit = 50; + $offset = ($page_num-1) * $limit; + $page_total = $database->cache->get("event_log_length"); + if (!$page_total) { + $page_total = $database->get_one("SELECT count(*) FROM score_log $where", $args); + // don't cache a length of zero when the extension is first installed + if ($page_total > 10) { + $database->cache->set("event_log_length", $page_total, 600); + } + } - $args["limit"] = $limit; - $args["offset"] = $offset; - $events = $database->get_all("SELECT * FROM score_log $where ORDER BY id DESC LIMIT :limit OFFSET :offset", $args); + $args["limit"] = $limit; + $args["offset"] = $offset; + $events = $database->get_all("SELECT * FROM score_log $where ORDER BY id DESC LIMIT :limit OFFSET :offset", $args); - $this->theme->display_events($events, $page_num, 100); - } - } - } + $this->theme->display_events($events, $page_num, 100); + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("view_eventlog")) { - $event->add_link("Event Log", make_link("log/view")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("view_eventlog")) { + $event->add_link("Event Log", make_link("log/view")); + } + } - public function onLog(LogEvent $event) { - global $config, $database, $user; + public function onLog(LogEvent $event) + { + global $config, $database, $user; - $username = ($user && $user->name) ? $user->name : "null"; + $username = ($user && $user->name) ? $user->name : "null"; - // not installed yet... - if($config->get_int("ext_log_database_version") < 1) return; + // not installed yet... + if ($config->get_int("ext_log_database_version") < 1) { + return; + } - if($event->priority >= $config->get_int("log_db_priority")) { - $database->execute(" + if ($event->priority >= $config->get_int("log_db_priority")) { + $database->execute(" INSERT INTO score_log(date_sent, section, priority, username, address, message) VALUES(now(), :section, :priority, :username, :address, :message) - ", array( - "section"=>$event->section, "priority"=>$event->priority, "username"=>$username, - "address"=>$_SERVER['REMOTE_ADDR'], "message"=>$event->message - )); - } - } + ", [ + "section"=>$event->section, "priority"=>$event->priority, "username"=>$username, + "address"=>$_SERVER['REMOTE_ADDR'], "message"=>$event->message + ]); + } + } } - diff --git a/ext/log_db/test.php b/ext/log_db/test.php index 042a4640..691feedf 100644 --- a/ext/log_db/test.php +++ b/ext/log_db/test.php @@ -1,11 +1,13 @@ log_in_as_admin(); - $this->get_page("log/view"); - $this->get_page("log/view?module=core-image"); - $this->get_page("log/view?time=2012-03-01"); - $this->get_page("log/view?user=demo"); - $this->get_page("log/view?priority=10"); - } +class LogDatabaseTest extends ShimmiePHPUnitTestCase +{ + public function testLog() + { + $this->log_in_as_admin(); + $this->get_page("log/view"); + $this->get_page("log/view?module=core-image"); + $this->get_page("log/view?time=2012-03-01"); + $this->get_page("log/view?user=demo"); + $this->get_page("log/view?priority=10"); + } } diff --git a/ext/log_db/theme.php b/ext/log_db/theme.php index 44c98dbf..8c1356fc 100644 --- a/ext/log_db/theme.php +++ b/ext/log_db/theme.php @@ -1,18 +1,28 @@ .sizedinputs TD INPUT { width: 100%; @@ -42,74 +52,83 @@ class LogDatabaseTheme extends Themelet { \n"; - reset($events); // rewind to first element in array. - - foreach($events as $event) { - $c = $this->pri_to_col($event['priority']); - $table .= ""; - $table .= "".str_replace(" ", " ", substr($event['date_sent'], 0, 19)).""; - $table .= "".$event['section'].""; - if($event['username'] == "Anonymous") { - $table .= "".$event['address'].""; - } - else { - $table .= "". - "".html_escape($event['username'])."". - ""; - } - $table .= "".$this->scan_entities(html_escape($event['message'])).""; - $table .= "\n"; - } - $table .= ""; + reset($events); // rewind to first element in array. + + foreach ($events as $event) { + $c = $this->pri_to_col($event['priority']); + $table .= ""; + $table .= "".str_replace(" ", " ", substr($event['date_sent'], 0, 19)).""; + $table .= "".$event['section'].""; + if ($event['username'] == "Anonymous") { + $table .= "".$event['address'].""; + } else { + $table .= "". + "".html_escape($event['username'])."". + ""; + } + $table .= "".$this->scan_entities(html_escape($event['message'])).""; + $table .= "\n"; + } + $table .= ""; - global $page; - $page->set_title("Event Log"); - $page->set_heading("Event Log"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Events", $table)); - $this->display_paginator($page, "log/view", $this->get_args(), $page_num, $page_total); - } + global $page; + $page->set_title("Event Log"); + $page->set_heading("Event Log"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Events", $table)); + $this->display_paginator($page, "log/view", $this->get_args(), $page_num, $page_total); + } - protected function get_args() { - $args = ""; - // Check if each arg is actually empty and skip it if so - if(strlen($this->ueie("time-start"))) - $args .= $this->ueie("time-start")."&"; - if(strlen($this->ueie("time-end"))) - $args .= $this->ueie("time-end")."&"; - if(strlen($this->ueie("module"))) - $args .= $this->ueie("module")."&"; - if(strlen($this->ueie("user"))) - $args .= $this->ueie("user")."&"; - if(strlen($this->ueie("message"))) - $args .= $this->ueie("message")."&"; - if(strlen($this->ueie("priority"))) - $args .= $this->ueie("priority"); - // If there are no args at all, set $args to null to prevent an unnecessary ? at the end of the paginator url - if(strlen($args) == 0) - $args = null; - return $args; - } + protected function get_args() + { + $args = ""; + // Check if each arg is actually empty and skip it if so + if (strlen($this->ueie("time-start"))) { + $args .= $this->ueie("time-start")."&"; + } + if (strlen($this->ueie("time-end"))) { + $args .= $this->ueie("time-end")."&"; + } + if (strlen($this->ueie("module"))) { + $args .= $this->ueie("module")."&"; + } + if (strlen($this->ueie("user"))) { + $args .= $this->ueie("user")."&"; + } + if (strlen($this->ueie("message"))) { + $args .= $this->ueie("message")."&"; + } + if (strlen($this->ueie("priority"))) { + $args .= $this->ueie("priority"); + } + // If there are no args at all, set $args to null to prevent an unnecessary ? at the end of the paginator url + if (strlen($args) == 0) { + $args = null; + } + return $args; + } - protected function pri_to_col($pri) { - switch($pri) { - case SCORE_LOG_DEBUG: return "#999"; - case SCORE_LOG_INFO: return "#000"; - case SCORE_LOG_WARNING: return "#800"; - case SCORE_LOG_ERROR: return "#C00"; - case SCORE_LOG_CRITICAL: return "#F00"; - default: return ""; - } - } + protected function pri_to_col($pri) + { + switch ($pri) { + case SCORE_LOG_DEBUG: return "#999"; + case SCORE_LOG_INFO: return "#000"; + case SCORE_LOG_WARNING: return "#800"; + case SCORE_LOG_ERROR: return "#C00"; + case SCORE_LOG_CRITICAL: return "#F00"; + default: return ""; + } + } - protected function scan_entities($line) { - $line = preg_replace_callback("/Image #(\d+)/s", array($this, "link_image"), $line); - return $line; - } + protected function scan_entities($line) + { + $line = preg_replace_callback("/Image #(\d+)/s", [$this, "link_image"], $line); + return $line; + } - protected function link_image($id) { - $iid = int_escape($id[1]); - return "Image #$iid"; - } + protected function link_image($id) + { + $iid = int_escape($id[1]); + return "Image #$iid"; + } } - diff --git a/ext/log_logstash/main.php b/ext/log_logstash/main.php index 43517add..af04e2ff 100644 --- a/ext/log_logstash/main.php +++ b/ext/log_logstash/main.php @@ -7,49 +7,55 @@ * Visibility: admin */ -class LogLogstash extends Extension { - - public function onLog(LogEvent $event) { - global $user; +class LogLogstash extends Extension +{ + public function onLog(LogEvent $event) + { + global $user; - try { - $data = array( - "@type" => "shimmie", - "@message" => $event->message, - "@fields" => array( - "username" => ($user && $user->name) ? $user->name : "Anonymous", - "section" => $event->section, - "priority" => $event->priority, - "time" => $event->time, - "args" => $event->args, - ), - #"@request" => $_SERVER, - "@request" => array( - "UID" => get_request_id(), - "REMOTE_ADDR" => $_SERVER['REMOTE_ADDR'], - ), - ); + try { + $data = [ + "@type" => "shimmie", + "@message" => $event->message, + "@fields" => [ + "username" => ($user && $user->name) ? $user->name : "Anonymous", + "section" => $event->section, + "priority" => $event->priority, + "time" => $event->time, + "args" => $event->args, + ], + #"@request" => $_SERVER, + "@request" => [ + "UID" => get_request_id(), + "REMOTE_ADDR" => $_SERVER['REMOTE_ADDR'], + ], + ]; - $this->send_data($data); - } catch (Exception $e) { - } - } + $this->send_data($data); + } catch (Exception $e) { + } + } - private function send_data($data) { - global $config; + private function send_data($data) + { + global $config; - $host = $config->get_string("log_logstash_host"); - if(!$host) { return; } + $host = $config->get_string("log_logstash_host"); + if (!$host) { + return; + } - try { - $parts = explode(":", $host); - $host = $parts[0]; - $port = $parts[1]; - $fp = fsockopen("udp://$host", $port, $errno, $errstr); - if (! $fp) { return; } - fwrite($fp, json_encode($data)); - fclose($fp); - } catch (Exception $e) { - } - } + try { + $parts = explode(":", $host); + $host = $parts[0]; + $port = $parts[1]; + $fp = fsockopen("udp://$host", $port, $errno, $errstr); + if (! $fp) { + return; + } + fwrite($fp, json_encode($data)); + fclose($fp); + } catch (Exception $e) { + } + } } diff --git a/ext/log_net/main.php b/ext/log_net/main.php index f5e07175..ba29c77e 100644 --- a/ext/log_net/main.php +++ b/ext/log_net/main.php @@ -7,43 +7,48 @@ * Visibility: admin */ -class LogNet extends Extension { - private $count = 0; +class LogNet extends Extension +{ + private $count = 0; - public function onLog(LogEvent $event) { - global $user; + public function onLog(LogEvent $event) + { + global $user; - if($event->priority > 10) { - $this->count++; - if($this->count < 10) { - // TODO: colour based on event->priority - $username = ($user && $user->name) ? $user->name : "Anonymous"; - $str = sprintf("%-15s %-10s: %s", $_SERVER['REMOTE_ADDR'], $username, $event->message); - $this->msg($str); - } - else if($this->count == 10) { - $this->msg('suppressing flood, check the web log'); - } - } - } + if ($event->priority > 10) { + $this->count++; + if ($this->count < 10) { + // TODO: colour based on event->priority + $username = ($user && $user->name) ? $user->name : "Anonymous"; + $str = sprintf("%-15s %-10s: %s", $_SERVER['REMOTE_ADDR'], $username, $event->message); + $this->msg($str); + } elseif ($this->count == 10) { + $this->msg('suppressing flood, check the web log'); + } + } + } - private function msg($data) { - global $config; - $host = $config->get_string("log_net_host", "127.0.0.1:35353"); + private function msg($data) + { + global $config; + $host = $config->get_string("log_net_host", "127.0.0.1:35353"); - if(!$host) { return; } + if (!$host) { + return; + } - try { - $parts = explode(":", $host); - $host = $parts[0]; - $port = $parts[1]; - $fp = fsockopen("udp://$host", $port, $errno, $errstr); - if (! $fp) { return; } - fwrite($fp, "$data\n"); - fclose($fp); - } catch (Exception $e) { - /* logging errors shouldn't break everything */ - } - } + try { + $parts = explode(":", $host); + $host = $parts[0]; + $port = $parts[1]; + $fp = fsockopen("udp://$host", $port, $errno, $errstr); + if (! $fp) { + return; + } + fwrite($fp, "$data\n"); + fclose($fp); + } catch (Exception $e) { + /* logging errors shouldn't break everything */ + } + } } - diff --git a/ext/mail/main.php b/ext/mail/main.php index d4b8007f..3e51bcb4 100644 --- a/ext/mail/main.php +++ b/ext/mail/main.php @@ -7,39 +7,43 @@ * Description: Provides an interface for sending and receiving mail. */ -class Mail extends Extension { - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Mailing Options"); - $sb->add_text_option("mail_sub", "Subject prefix: "); - $sb->add_text_option("mail_img", "
    Banner Image URL: "); - $sb->add_text_option("mail_style", "
    Style URL: "); - $sb->add_longtext_option("mail_fot", "
    Footer (Use HTML)"); - $sb->add_label("
    Should measure 550x110px. Use an absolute URL"); - $event->panel->add_block($sb); - } - - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string("mail_sub", $config->get_string("site_title")." - "); - $config->set_default_string("mail_img", make_http("ext/mail/banner.png")); - $config->set_default_string("mail_style", make_http("ext/mail/mail.css")); - $config->set_default_string("mail_fot", "".$config->get_string("site_title").""); - } +class Mail extends Extension +{ + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Mailing Options"); + $sb->add_text_option("mail_sub", "Subject prefix: "); + $sb->add_text_option("mail_img", "
    Banner Image URL: "); + $sb->add_text_option("mail_style", "
    Style URL: "); + $sb->add_longtext_option("mail_fot", "
    Footer (Use HTML)"); + $sb->add_label("
    Should measure 550x110px. Use an absolute URL"); + $event->panel->add_block($sb); + } + + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string("mail_sub", $config->get_string("site_title")." - "); + $config->set_default_string("mail_img", make_http("ext/mail/banner.png")); + $config->set_default_string("mail_style", make_http("ext/mail/mail.css")); + $config->set_default_string("mail_fot", "".$config->get_string("site_title").""); + } } -class MailTest extends Extension { - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("mail/test")) { - global $page; - $page->set_mode("data"); - echo "Alert: uncomment this page's code on /ext/mail/main.php starting on line 33, and change the email address. Make sure you're using a server with a domain, not localhost."; - /* - echo "Preparing to send message:
    "; - echo "created new mail object. sending now... "; - $email = new Email("example@localhost.com", "hello", "hello world", "this is a test message."); - $email->send(); - echo "sent."; - */ - } - } +class MailTest extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("mail/test")) { + global $page; + $page->set_mode("data"); + echo "Alert: uncomment this page's code on /ext/mail/main.php starting on line 33, and change the email address. Make sure you're using a server with a domain, not localhost."; + /* + echo "Preparing to send message:
    "; + echo "created new mail object. sending now... "; + $email = new Email("example@localhost.com", "hello", "hello world", "this is a test message."); + $email->send(); + echo "sent."; + */ + } + } } - diff --git a/ext/mass_tagger/main.php b/ext/mass_tagger/main.php index e46ec63c..648d7b79 100644 --- a/ext/mass_tagger/main.php +++ b/ext/mass_tagger/main.php @@ -12,58 +12,63 @@ * the text field will be added to marked images. */ -class MassTagger extends Extension { - public function onPostListBuilding(PostListBuildingEvent $event) { - global $config, $page, $user; - - if($user->is_admin()) { - $this->theme->display_mass_tagger( $page, $event, $config ); - } - } +class MassTagger extends Extension +{ + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $config, $page, $user; + + if ($user->is_admin()) { + $this->theme->display_mass_tagger($page, $event, $config); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("mass_tagger/tag") && $user->is_admin()) { - if( !isset($_POST['ids']) or !isset($_POST['tag']) ) return; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("mass_tagger/tag") && $user->is_admin()) { + if (!isset($_POST['ids']) or !isset($_POST['tag'])) { + return; + } - $tags = Tag::explode($_POST['tag']); + $tags = Tag::explode($_POST['tag']); - $pos_tag_array = array(); - $neg_tag_array = array(); - foreach($tags as $new_tag) { - if (strpos($new_tag, '-') === 0) - $neg_tag_array[] = substr($new_tag,1); - else - $pos_tag_array[] = $new_tag; - } + $pos_tag_array = []; + $neg_tag_array = []; + foreach ($tags as $new_tag) { + if (strpos($new_tag, '-') === 0) { + $neg_tag_array[] = substr($new_tag, 1); + } else { + $pos_tag_array[] = $new_tag; + } + } - $ids = explode( ':', $_POST['ids'] ); - $ids = array_filter ( $ids , 'is_numeric' ); + $ids = explode(':', $_POST['ids']); + $ids = array_filter($ids, 'is_numeric'); - $images = array_map( "Image::by_id", $ids ); + $images = array_map("Image::by_id", $ids); - if(isset($_POST['setadd']) && $_POST['setadd'] == 'set') { - foreach($images as $image) { - $image->set_tags($tags); - } - } - else { - foreach($images as $image) { - if (!empty($neg_tag_array)) { - $img_tags = array_merge($pos_tag_array, $image->get_tag_array()); - $img_tags = array_diff($img_tags, $neg_tag_array); - $image->set_tags($img_tags); - } - else { - $image->set_tags(array_merge($tags, $image->get_tag_array())); - } - } - } + if (isset($_POST['setadd']) && $_POST['setadd'] == 'set') { + foreach ($images as $image) { + $image->set_tags($tags); + } + } else { + foreach ($images as $image) { + if (!empty($neg_tag_array)) { + $img_tags = array_merge($pos_tag_array, $image->get_tag_array()); + $img_tags = array_diff($img_tags, $neg_tag_array); + $image->set_tags($img_tags); + } else { + $image->set_tags(array_merge($tags, $image->get_tag_array())); + } + } + } - $page->set_mode("redirect"); - if(!isset($_SERVER['HTTP_REFERER'])) $_SERVER['HTTP_REFERER'] = make_link(); - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - } + $page->set_mode("redirect"); + if (!isset($_SERVER['HTTP_REFERER'])) { + $_SERVER['HTTP_REFERER'] = make_link(); + } + $page->set_redirect($_SERVER['HTTP_REFERER']); + } + } } - diff --git a/ext/mass_tagger/theme.php b/ext/mass_tagger/theme.php index cc1783e9..f5894cbb 100644 --- a/ext/mass_tagger/theme.php +++ b/ext/mass_tagger/theme.php @@ -1,9 +1,11 @@

    "; - $block = new Block("Mass Tagger", $body, "left", 50); - $page->add_block( $block ); - } + $block = new Block("Mass Tagger", $body, "left", 50); + $page->add_block($block); + } } - diff --git a/ext/not_a_tag/main.php b/ext/not_a_tag/main.php index dfe6076a..c03b0e81 100644 --- a/ext/not_a_tag/main.php +++ b/ext/not_a_tag/main.php @@ -6,111 +6,123 @@ * License: GPLv2 * Description: Redirect users to the rules if they use bad tags */ -class NotATag extends Extension { - public function get_priority(): int {return 30;} // before ImageUploadEvent and tag_history +class NotATag extends Extension +{ + public function get_priority(): int + { + return 30; + } // before ImageUploadEvent and tag_history - public function onInitExt(InitExtEvent $event) { - global $config, $database; - if($config->get_int("ext_notatag_version") < 1) { - $database->create_table("untags", " + public function onInitExt(InitExtEvent $event) + { + global $config, $database; + if ($config->get_int("ext_notatag_version") < 1) { + $database->create_table("untags", " tag VARCHAR(128) NOT NULL PRIMARY KEY, redirect VARCHAR(255) NOT NULL "); - $config->set_int("ext_notatag_version", 1); - } - } + $config->set_int("ext_notatag_version", 1); + } + } - public function onImageAddition(ImageAdditionEvent $event) { - $this->scan($event->image->get_tag_array()); - } + public function onImageAddition(ImageAdditionEvent $event) + { + $this->scan($event->image->get_tag_array()); + } - public function onTagSet(TagSetEvent $event) { - $this->scan($event->tags); - } + public function onTagSet(TagSetEvent $event) + { + $this->scan($event->tags); + } - /** - * #param string[] $tags_mixed - */ - private function scan(array $tags_mixed) { - global $database; + /** + * #param string[] $tags_mixed + */ + private function scan(array $tags_mixed) + { + global $database; - $tags = array(); - foreach($tags_mixed as $tag) $tags[] = strtolower($tag); + $tags = []; + foreach ($tags_mixed as $tag) { + $tags[] = strtolower($tag); + } - $pairs = $database->get_all("SELECT * FROM untags"); - foreach($pairs as $tag_url) { - $tag = strtolower($tag_url[0]); - $url = $tag_url[1]; - if(in_array($tag, $tags)) { - header("Location: $url"); - exit; # FIXME: need a better way of aborting the tag-set or upload - } - } - } + $pairs = $database->get_all("SELECT * FROM untags"); + foreach ($pairs as $tag_url) { + $tag = strtolower($tag_url[0]); + $url = $tag_url[1]; + if (in_array($tag, $tags)) { + header("Location: $url"); + exit; # FIXME: need a better way of aborting the tag-set or upload + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("ban_image")) { - $event->add_link("UnTags", make_link("untag/list/1")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("ban_image")) { + $event->add_link("UnTags", make_link("untag/list/1")); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page, $user; - if($event->page_matches("untag")) { - if($user->can("ban_image")) { - if($event->get_arg(0) == "add") { - $tag = $_POST["tag"]; - $redirect = isset($_POST['redirect']) ? $_POST['redirect'] : "DNP"; + if ($event->page_matches("untag")) { + if ($user->can("ban_image")) { + if ($event->get_arg(0) == "add") { + $tag = $_POST["tag"]; + $redirect = isset($_POST['redirect']) ? $_POST['redirect'] : "DNP"; - $database->Execute( - "INSERT INTO untags(tag, redirect) VALUES (?, ?)", - array($tag, $redirect)); + $database->Execute( + "INSERT INTO untags(tag, redirect) VALUES (?, ?)", + [$tag, $redirect] + ); - $page->set_mode("redirect"); - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - else if($event->get_arg(0) == "remove") { - if(isset($_POST['tag'])) { - $database->Execute("DELETE FROM untags WHERE tag = ?", array($_POST['tag'])); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER['HTTP_REFERER']); + } elseif ($event->get_arg(0) == "remove") { + if (isset($_POST['tag'])) { + $database->Execute("DELETE FROM untags WHERE tag = ?", [$_POST['tag']]); - flash_message("Image ban removed"); - $page->set_mode("redirect"); - $page->set_redirect($_SERVER['HTTP_REFERER']); - } - } - else if($event->get_arg(0) == "list") { - $page_num = 0; - if($event->count_args() == 2) { - $page_num = int_escape($event->get_arg(1)); - } - $page_size = 100; - $page_count = ceil($database->get_one("SELECT COUNT(tag) FROM untags")/$page_size); - $this->theme->display_untags($page, $page_num, $page_count, $this->get_untags($page_num, $page_size)); - } - } - } - } + flash_message("Image ban removed"); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER['HTTP_REFERER']); + } + } elseif ($event->get_arg(0) == "list") { + $page_num = 0; + if ($event->count_args() == 2) { + $page_num = int_escape($event->get_arg(1)); + } + $page_size = 100; + $page_count = ceil($database->get_one("SELECT COUNT(tag) FROM untags")/$page_size); + $this->theme->display_untags($page, $page_num, $page_count, $this->get_untags($page_num, $page_size)); + } + } + } + } - public function get_untags(int $page, int $size=100): array { - global $database; + public function get_untags(int $page, int $size=100): array + { + global $database; - // FIXME: many - $size_i = int_escape($size); - $offset_i = int_escape($page-1)*$size_i; - $where = array("(1=1)"); - $args = array(); - if(!empty($_GET['tag'])) { - $where[] = 'tag SCORE_ILIKE ?'; - $args[] = "%".$_GET['tag']."%"; - } - if(!empty($_GET['redirect'])) { - $where[] = 'redirect SCORE_ILIKE ?'; - $args[] = "%".$_GET['redirect']."%"; - } - $where = implode(" AND ", $where); - $bans = $database->get_all($database->scoreql_to_sql(" + // FIXME: many + $size_i = int_escape($size); + $offset_i = int_escape($page-1)*$size_i; + $where = ["(1=1)"]; + $args = []; + if (!empty($_GET['tag'])) { + $where[] = 'tag SCORE_ILIKE ?'; + $args[] = "%".$_GET['tag']."%"; + } + if (!empty($_GET['redirect'])) { + $where[] = 'redirect SCORE_ILIKE ?'; + $args[] = "%".$_GET['redirect']."%"; + } + $where = implode(" AND ", $where); + $bans = $database->get_all($database->scoreql_to_sql(" SELECT * FROM untags WHERE $where @@ -118,8 +130,10 @@ class NotATag extends Extension { LIMIT $size_i OFFSET $offset_i "), $args); - if($bans) {return $bans;} - else {return array();} - } + if ($bans) { + return $bans; + } else { + return []; + } + } } - diff --git a/ext/not_a_tag/theme.php b/ext/not_a_tag/theme.php index d3730456..535a1b36 100644 --- a/ext/not_a_tag/theme.php +++ b/ext/not_a_tag/theme.php @@ -1,9 +1,11 @@ ".make_form(make_link("untag/remove"))." {$ban['tag']} @@ -15,8 +17,8 @@ class NotATagTheme extends Themelet { "; - } - $html = " + } + $html = " @@ -39,20 +41,19 @@ class NotATagTheme extends Themelet {
    TagRedirectAction
    "; - $prev = $page_number - 1; - $next = $page_number + 1; + $prev = $page_number - 1; + $next = $page_number + 1; - $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; - $h_index = "Index"; - $h_next = ($page_number >= $page_count) ? "Next" : "Next"; + $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; + $h_index = "Index"; + $h_next = ($page_number >= $page_count) ? "Next" : "Next"; - $nav = "$h_prev | $h_index | $h_next"; + $nav = "$h_prev | $h_index | $h_next"; - $page->set_title("UnTags"); - $page->set_heading("UnTags"); - $page->add_block(new Block("Edit UnTags", $html)); - $page->add_block(new Block("Navigation", $nav, "left", 0)); - $this->display_paginator($page, "untag/list", null, $page_number, $page_count); - } + $page->set_title("UnTags"); + $page->set_heading("UnTags"); + $page->add_block(new Block("Edit UnTags", $html)); + $page->add_block(new Block("Navigation", $nav, "left", 0)); + $this->display_paginator($page, "untag/list", null, $page_number, $page_count); + } } - diff --git a/ext/notes/main.php b/ext/notes/main.php index 27e781ce..14285df2 100644 --- a/ext/notes/main.php +++ b/ext/notes/main.php @@ -7,14 +7,16 @@ * Documentation: */ -class Notes extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; +class Notes extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - // shortcut to latest - if ($config->get_int("ext_notes_version") < 1) { - $database->Execute("ALTER TABLE images ADD COLUMN notes INTEGER NOT NULL DEFAULT 0"); - $database->create_table("notes", " + // shortcut to latest + if ($config->get_int("ext_notes_version") < 1) { + $database->Execute("ALTER TABLE images ADD COLUMN notes INTEGER NOT NULL DEFAULT 0"); + $database->create_table("notes", " id SCORE_AIPK, enable INTEGER NOT NULL, image_id INTEGER NOT NULL, @@ -29,9 +31,9 @@ class Notes extends Extension { FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX notes_image_id_idx ON notes(image_id)", array()); + $database->execute("CREATE INDEX notes_image_id_idx ON notes(image_id)", []); - $database->create_table("note_request", " + $database->create_table("note_request", " id SCORE_AIPK, image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -39,9 +41,9 @@ class Notes extends Extension { FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX note_request_image_id_idx ON note_request(image_id)", array()); + $database->execute("CREATE INDEX note_request_image_id_idx ON note_request(image_id)", []); - $database->create_table("note_histories", " + $database->create_table("note_histories", " id SCORE_AIPK, note_enable INTEGER NOT NULL, note_id INTEGER NOT NULL, @@ -58,469 +60,505 @@ class Notes extends Extension { FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX note_histories_image_id_idx ON note_histories(image_id)", array()); + $database->execute("CREATE INDEX note_histories_image_id_idx ON note_histories(image_id)", []); - $config->set_int("notesNotesPerPage", 20); - $config->set_int("notesRequestsPerPage", 20); - $config->set_int("notesHistoriesPerPage", 20); + $config->set_int("notesNotesPerPage", 20); + $config->set_int("notesRequestsPerPage", 20); + $config->set_int("notesHistoriesPerPage", 20); - $config->set_int("ext_notes_version", 1); - log_info("notes", "extension installed"); - } - } + $config->set_int("ext_notes_version", 1); + log_info("notes", "extension installed"); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("note")) { - switch($event->get_arg(0)) { - case "list": //index - $this->get_notes_list($event); // This should show images like post/list but i don't know how do that. - break; - case "requests": // The same as post/list but only for note_request table. - $this->get_notes_requests($event); // This should show images like post/list but i don't know how do that. - break; - case "search": - if(!$user->is_anonymous()) - $this->theme->search_notes_page($page); - break; - case "updated": //Thinking how to build this function. - $this->get_histories($event); - break; - case "history": //Thinking how to build this function. - $this->get_history($event); - break; - case "revert": - $noteID = $event->get_arg(1); - $reviewID = $event->get_arg(2); - if(!$user->is_anonymous()){ - $this->revert_history($noteID, $reviewID); - } + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("note")) { + switch ($event->get_arg(0)) { + case "list": //index + $this->get_notes_list($event); // This should show images like post/list but i don't know how do that. + break; + case "requests": // The same as post/list but only for note_request table. + $this->get_notes_requests($event); // This should show images like post/list but i don't know how do that. + break; + case "search": + if (!$user->is_anonymous()) { + $this->theme->search_notes_page($page); + } + break; + case "updated": //Thinking how to build this function. + $this->get_histories($event); + break; + case "history": //Thinking how to build this function. + $this->get_history($event); + break; + case "revert": + $noteID = $event->get_arg(1); + $reviewID = $event->get_arg(2); + if (!$user->is_anonymous()) { + $this->revert_history($noteID, $reviewID); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("note/updated")); - break; - case "add_note": - if(!$user->is_anonymous()) - $this->add_new_note(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("note/updated")); + break; + case "add_note": + if (!$user->is_anonymous()) { + $this->add_new_note(); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$_POST["image_id"])); - break; - case "add_request": - if(!$user->is_anonymous()) - $this->add_note_request(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$_POST["image_id"])); + break; + case "add_request": + if (!$user->is_anonymous()) { + $this->add_note_request(); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$_POST["image_id"])); - break; - case "nuke_notes": - if($user->is_admin()) - $this->nuke_notes(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$_POST["image_id"])); + break; + case "nuke_notes": + if ($user->is_admin()) { + $this->nuke_notes(); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$_POST["image_id"])); - break; - case "nuke_requests": - if($user->is_admin()) - $this->nuke_requests(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$_POST["image_id"])); + break; + case "nuke_requests": + if ($user->is_admin()) { + $this->nuke_requests(); + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$_POST["image_id"])); - break; - case "edit_note": - if (!$user->is_anonymous()) { - $this->update_note(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/" . $_POST["image_id"])); - } - break; - case "delete_note": - if ($user->is_admin()) { - $this->delete_note(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$_POST["image_id"])); - } - break; - default: - $page->set_mode("redirect"); - $page->set_redirect(make_link("note/list")); - break; - } - } - } + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$_POST["image_id"])); + break; + case "edit_note": + if (!$user->is_anonymous()) { + $this->update_note(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/" . $_POST["image_id"])); + } + break; + case "delete_note": + if ($user->is_admin()) { + $this->delete_note(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$_POST["image_id"])); + } + break; + default: + $page->set_mode("redirect"); + $page->set_redirect(make_link("note/list")); + break; + } + } + } - /* - * HERE WE LOAD THE NOTES IN THE IMAGE - */ - public function onDisplayingImage(DisplayingImageEvent $event) { - global $page, $user; + /* + * HERE WE LOAD THE NOTES IN THE IMAGE + */ + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $page, $user; - //display form on image event - $notes = $this->get_notes($event->image->id); - $this->theme->display_note_system($page, $event->image->id, $notes, $user->is_admin()); - } + //display form on image event + $notes = $this->get_notes($event->image->id); + $this->theme->display_note_system($page, $event->image->id, $notes, $user->is_admin()); + } - /* - * HERE WE ADD THE BUTTONS ON SIDEBAR - */ - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $user; - if(!$user->is_anonymous()) { - $event->add_part($this->theme->note_button($event->image->id)); - $event->add_part($this->theme->request_button($event->image->id)); - if($user->is_admin()) { - $event->add_part($this->theme->nuke_notes_button($event->image->id)); - $event->add_part($this->theme->nuke_requests_button($event->image->id)); - } - } - } + /* + * HERE WE ADD THE BUTTONS ON SIDEBAR + */ + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $user; + if (!$user->is_anonymous()) { + $event->add_part($this->theme->note_button($event->image->id)); + $event->add_part($this->theme->request_button($event->image->id)); + if ($user->is_admin()) { + $event->add_part($this->theme->nuke_notes_button($event->image->id)); + $event->add_part($this->theme->nuke_requests_button($event->image->id)); + } + } + } - /* - * HERE WE ADD QUERYLETS TO ADD SEARCH SYSTEM - */ - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - if(preg_match("/^note[=|:](.*)$/i", $event->term, $matches)) { - $notes = int_escape($matches[1]); - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)")); - } - else if(preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)%/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $notes = $matches[2]; - $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)")); - } - else if(preg_match("/^notes_by[=|:](.*)$/i", $event->term, $matches)) { - $user = User::by_name($matches[1]); - if(!is_null($user)) { - $user_id = $user->id; - } else { - $user_id = -1; - } + /* + * HERE WE ADD QUERYLETS TO ADD SEARCH SYSTEM + */ + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + if (preg_match("/^note[=|:](.*)$/i", $event->term, $matches)) { + $notes = int_escape($matches[1]); + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)")); + } elseif (preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)%/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $notes = $matches[2]; + $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)")); + } elseif (preg_match("/^notes_by[=|:](.*)$/i", $event->term, $matches)) { + $user = User::by_name($matches[1]); + if (!is_null($user)) { + $user_id = $user->id; + } else { + $user_id = -1; + } - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); - } - else if(preg_match("/^notes_by_userno[=|:](\d+)$/i", $event->term, $matches)) { - $user_id = int_escape($matches[1]); - $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); - } - } + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); + } elseif (preg_match("/^notes_by_userno[=|:](\d+)$/i", $event->term, $matches)) { + $user_id = int_escape($matches[1]); + $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); + } + } - /** - * HERE WE GET ALL NOTES FOR DISPLAYED IMAGE. - */ - private function get_notes(int $imageID): array { - global $database; + /** + * HERE WE GET ALL NOTES FOR DISPLAYED IMAGE. + */ + private function get_notes(int $imageID): array + { + global $database; - return $database->get_all( - "SELECT * ". - "FROM notes ". - "WHERE enable = ? AND image_id = ? ". - "ORDER BY date ASC", - array('1', $imageID)); - } + return $database->get_all( + "SELECT * ". + "FROM notes ". + "WHERE enable = ? AND image_id = ? ". + "ORDER BY date ASC", + ['1', $imageID] + ); + } - /* - * HERE WE ADD A NOTE TO DATABASE - */ - private function add_new_note() { - global $database, $user; + /* + * HERE WE ADD A NOTE TO DATABASE + */ + private function add_new_note() + { + global $database, $user; - $imageID = int_escape($_POST["image_id"]); - $user_id = $user->id; - $noteX1 = int_escape($_POST["note_x1"]); - $noteY1 = int_escape($_POST["note_y1"]); - $noteHeight = int_escape($_POST["note_height"]); - $noteWidth = int_escape($_POST["note_width"]); - $noteText = html_escape($_POST["note_text"]); + $imageID = int_escape($_POST["image_id"]); + $user_id = $user->id; + $noteX1 = int_escape($_POST["note_x1"]); + $noteY1 = int_escape($_POST["note_y1"]); + $noteHeight = int_escape($_POST["note_height"]); + $noteWidth = int_escape($_POST["note_width"]); + $noteText = html_escape($_POST["note_text"]); - $database->execute(" + $database->execute( + " INSERT INTO notes (enable, image_id, user_id, user_ip, date, x1, y1, height, width, note) VALUES (?, ?, ?, ?, now(), ?, ?, ?, ?, ?)", - array(1, $imageID, $user_id, $_SERVER['REMOTE_ADDR'], $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText)); + [1, $imageID, $user_id, $_SERVER['REMOTE_ADDR'], $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText] + ); - $noteID = $database->get_last_insert_id('notes_id_seq'); + $noteID = $database->get_last_insert_id('notes_id_seq'); - log_info("notes", "Note added {$noteID} by {$user->name}"); + log_info("notes", "Note added {$noteID} by {$user->name}"); - $database->execute("UPDATE images SET notes=(SELECT COUNT(*) FROM notes WHERE image_id=?) WHERE id=?", array($imageID, $imageID)); + $database->execute("UPDATE images SET notes=(SELECT COUNT(*) FROM notes WHERE image_id=?) WHERE id=?", [$imageID, $imageID]); - $this->add_history(1, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); - } + $this->add_history(1, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); + } - /* - * HERE WE ADD A REQUEST TO DATABASE - */ - private function add_note_request() { - global $database, $user; + /* + * HERE WE ADD A REQUEST TO DATABASE + */ + private function add_note_request() + { + global $database, $user; - $image_id = int_escape($_POST["image_id"]); - $user_id = $user->id; + $image_id = int_escape($_POST["image_id"]); + $user_id = $user->id; - $database->execute(" + $database->execute( + " INSERT INTO note_request (image_id, user_id, date) VALUES (?, ?, now())", - array($image_id, $user_id)); + [$image_id, $user_id] + ); - $resultID = $database->get_last_insert_id('note_request_id_seq'); + $resultID = $database->get_last_insert_id('note_request_id_seq'); - log_info("notes", "Note requested {$resultID} by {$user->name}"); - } + log_info("notes", "Note requested {$resultID} by {$user->name}"); + } - /* - * HERE WE EDIT THE NOTE - */ - private function update_note() { - global $database; + /* + * HERE WE EDIT THE NOTE + */ + private function update_note() + { + global $database; - $note = array( - "noteX1" => int_escape($_POST["note_x1"]), - "noteY1" => int_escape($_POST["note_y1"]), - "noteHeight" => int_escape($_POST["note_height"]), - "noteWidth" => int_escape($_POST["note_width"]), - "noteText" => sql_escape(html_escape($_POST["note_text"])), - "imageID" => int_escape($_POST["image_id"]), - "noteID" => int_escape($_POST["note_id"]) - ); + $note = [ + "noteX1" => int_escape($_POST["note_x1"]), + "noteY1" => int_escape($_POST["note_y1"]), + "noteHeight" => int_escape($_POST["note_height"]), + "noteWidth" => int_escape($_POST["note_width"]), + "noteText" => sql_escape(html_escape($_POST["note_text"])), + "imageID" => int_escape($_POST["image_id"]), + "noteID" => int_escape($_POST["note_id"]) + ]; - // validate parameters - if (array_search(NULL, $note)|| strlen($note['noteText']) == 0) { - return; - } + // validate parameters + if (array_search(null, $note)|| strlen($note['noteText']) == 0) { + return; + } - $database->execute("UPDATE notes ". - "SET x1 = ?, ". - "y1 = ?, ". - "height = ?, ". - "width = ?,". - "note = ? ". - "WHERE image_id = ? AND id = ?", array_values($note)); + $database->execute("UPDATE notes ". + "SET x1 = ?, ". + "y1 = ?, ". + "height = ?, ". + "width = ?,". + "note = ? ". + "WHERE image_id = ? AND id = ?", array_values($note)); - $this->add_history(1, $note['noteID'], $note['imageID'], $note['noteX1'], $note['noteY1'], $note['noteHeight'], $note['noteWidth'], $note['noteText']); - } + $this->add_history(1, $note['noteID'], $note['imageID'], $note['noteX1'], $note['noteY1'], $note['noteHeight'], $note['noteWidth'], $note['noteText']); + } - /* - * HERE WE DELETE THE NOTE - */ - private function delete_note() { - global $user, $database; + /* + * HERE WE DELETE THE NOTE + */ + private function delete_note() + { + global $user, $database; - $imageID = int_escape($_POST["image_id"]); - $noteID = int_escape($_POST["note_id"]); + $imageID = int_escape($_POST["image_id"]); + $noteID = int_escape($_POST["note_id"]); - // validate parameters - if(is_null($imageID) || !is_numeric($imageID) || is_null($noteID) || !is_numeric($noteID)) { - return; - } + // validate parameters + if (is_null($imageID) || !is_numeric($imageID) || is_null($noteID) || !is_numeric($noteID)) { + return; + } - $database->execute("UPDATE notes ". - "SET enable = ? ". - "WHERE image_id = ? AND id = ?", array(0, $imageID, $noteID)); + $database->execute("UPDATE notes ". + "SET enable = ? ". + "WHERE image_id = ? AND id = ?", [0, $imageID, $noteID]); - log_info("notes", "Note deleted {$noteID} by {$user->name}"); - } + log_info("notes", "Note deleted {$noteID} by {$user->name}"); + } - /* - * HERE WE DELETE ALL NOTES FROM IMAGE - */ - private function nuke_notes() { - global $database, $user; - $image_id = int_escape($_POST["image_id"]); - $database->execute("DELETE FROM notes WHERE image_id = ?", array($image_id)); - log_info("notes", "Notes deleted from {$image_id} by {$user->name}"); - } + /* + * HERE WE DELETE ALL NOTES FROM IMAGE + */ + private function nuke_notes() + { + global $database, $user; + $image_id = int_escape($_POST["image_id"]); + $database->execute("DELETE FROM notes WHERE image_id = ?", [$image_id]); + log_info("notes", "Notes deleted from {$image_id} by {$user->name}"); + } - /* - * HERE WE DELETE ALL REQUESTS FOR IMAGE - */ - private function nuke_requests() { - global $database, $user; - $image_id = int_escape($_POST["image_id"]); + /* + * HERE WE DELETE ALL REQUESTS FOR IMAGE + */ + private function nuke_requests() + { + global $database, $user; + $image_id = int_escape($_POST["image_id"]); - $database->execute("DELETE FROM note_request WHERE image_id = ?", array($image_id)); + $database->execute("DELETE FROM note_request WHERE image_id = ?", [$image_id]); - log_info("notes", "Requests deleted from {$image_id} by {$user->name}"); - } + log_info("notes", "Requests deleted from {$image_id} by {$user->name}"); + } - /** - * HERE WE ALL IMAGES THAT HAVE NOTES - */ - private function get_notes_list(PageRequestEvent $event) { - global $database, $config; + /** + * HERE WE ALL IMAGES THAT HAVE NOTES + */ + private function get_notes_list(PageRequestEvent $event) + { + global $database, $config; - $pageNumber = $event->get_arg(1); - if(is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { - $pageNumber = 0; - } else { - $pageNumber--; - } + $pageNumber = $event->get_arg(1); + if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $notesPerPage = $config->get_int('notesNotesPerPage'); + $notesPerPage = $config->get_int('notesNotesPerPage'); - //$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID)); - $result = $database->execute("SELECT DISTINCT image_id". - "FROM notes ". - "WHERE enable = ? ". - "ORDER BY date DESC LIMIT ?, ?", - array(1, $pageNumber * $notesPerPage, $notesPerPage)); + //$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID)); + $result = $database->execute( + "SELECT DISTINCT image_id". + "FROM notes ". + "WHERE enable = ? ". + "ORDER BY date DESC LIMIT ?, ?", + [1, $pageNumber * $notesPerPage, $notesPerPage] + ); - $totalPages = ceil($database->get_one("SELECT COUNT(DISTINCT image_id) FROM notes") / $notesPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(DISTINCT image_id) FROM notes") / $notesPerPage); - $images = array(); - while($row = $result->fetch()) { - $images[] = array(Image::by_id($row["image_id"])); - } + $images = []; + while ($row = $result->fetch()) { + $images[] = [Image::by_id($row["image_id"])]; + } - $this->theme->display_note_list($images, $pageNumber + 1, $totalPages); - } + $this->theme->display_note_list($images, $pageNumber + 1, $totalPages); + } - /** - * HERE WE GET ALL NOTE REQUESTS - */ - private function get_notes_requests(PageRequestEvent $event) { - global $config, $database; + /** + * HERE WE GET ALL NOTE REQUESTS + */ + private function get_notes_requests(PageRequestEvent $event) + { + global $config, $database; - $pageNumber = $event->get_arg(1); - if(is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { - $pageNumber = 0; - } else { - $pageNumber--; - } + $pageNumber = $event->get_arg(1); + if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $requestsPerPage = $config->get_int('notesRequestsPerPage'); + $requestsPerPage = $config->get_int('notesRequestsPerPage'); - //$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID)); + //$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID)); - $result = $database->execute(" + $result = $database->execute( + " SELECT DISTINCT image_id FROM note_request ORDER BY date DESC LIMIT ?, ?", - array($pageNumber * $requestsPerPage, $requestsPerPage)); + [$pageNumber * $requestsPerPage, $requestsPerPage] + ); - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_request") / $requestsPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_request") / $requestsPerPage); - $images = array(); - while($row = $result->fetch()) { - $images[] = array(Image::by_id($row["image_id"])); - } + $images = []; + while ($row = $result->fetch()) { + $images[] = [Image::by_id($row["image_id"])]; + } - $this->theme->display_note_requests($images, $pageNumber + 1, $totalPages); - } + $this->theme->display_note_requests($images, $pageNumber + 1, $totalPages); + } - /* - * HERE WE ADD HISTORY TO TRACK THE CHANGES OF THE NOTES FOR THE IMAGES. - */ - private function add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText){ - global $user, $database; + /* + * HERE WE ADD HISTORY TO TRACK THE CHANGES OF THE NOTES FOR THE IMAGES. + */ + private function add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText) + { + global $user, $database; - $reviewID = $database->get_one("SELECT COUNT(*) FROM note_histories WHERE note_id = ?", array($noteID)); - $reviewID = $reviewID + 1; + $reviewID = $database->get_one("SELECT COUNT(*) FROM note_histories WHERE note_id = ?", [$noteID]); + $reviewID = $reviewID + 1; - $database->execute(" + $database->execute( + " INSERT INTO note_histories (note_enable, note_id, review_id, image_id, user_id, user_ip, date, x1, y1, height, width, note) VALUES (?, ?, ?, ?, ?, ?, now(), ?, ?, ?, ?, ?)", - array($noteEnable, $noteID, $reviewID, $imageID, $user->id, $_SERVER['REMOTE_ADDR'], $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText)); - } + [$noteEnable, $noteID, $reviewID, $imageID, $user->id, $_SERVER['REMOTE_ADDR'], $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText] + ); + } - /** - * HERE WE GET ALL HISTORIES. - */ - private function get_histories(PageRequestEvent $event){ - global $config, $database; + /** + * HERE WE GET ALL HISTORIES. + */ + private function get_histories(PageRequestEvent $event) + { + global $config, $database; - $pageNumber = $event->get_arg(1); - if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { - $pageNumber = 0; - } else { - $pageNumber--; - } + $pageNumber = $event->get_arg(1); + if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $historiesPerPage = $config->get_int('notesHistoriesPerPage'); + $historiesPerPage = $config->get_int('notesHistoriesPerPage'); - //ORDER BY IMAGE & DATE - $histories = $database->get_all("SELECT h.note_id, h.review_id, h.image_id, h.date, h.note, u.name AS user_name ". - "FROM note_histories AS h ". - "INNER JOIN users AS u ". - "ON u.id = h.user_id ". - "ORDER BY date DESC LIMIT ?, ?", - array($pageNumber * $historiesPerPage, $historiesPerPage)); + //ORDER BY IMAGE & DATE + $histories = $database->get_all( + "SELECT h.note_id, h.review_id, h.image_id, h.date, h.note, u.name AS user_name ". + "FROM note_histories AS h ". + "INNER JOIN users AS u ". + "ON u.id = h.user_id ". + "ORDER BY date DESC LIMIT ?, ?", + [$pageNumber * $historiesPerPage, $historiesPerPage] + ); - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_histories") / $historiesPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_histories") / $historiesPerPage); - $this->theme->display_histories($histories, $pageNumber + 1, $totalPages); - } + $this->theme->display_histories($histories, $pageNumber + 1, $totalPages); + } - /** - * HERE WE THE HISTORY FOR A SPECIFIC NOTE. - */ - private function get_history(PageRequestEvent $event){ - global $config, $database; + /** + * HERE WE THE HISTORY FOR A SPECIFIC NOTE. + */ + private function get_history(PageRequestEvent $event) + { + global $config, $database; - $noteID = $event->get_arg(1); + $noteID = $event->get_arg(1); - $pageNumber = $event->get_arg(2); - if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { - $pageNumber = 0; - } else { - $pageNumber--; - } + $pageNumber = $event->get_arg(2); + if (is_null($pageNumber) || !is_numeric($pageNumber) || $pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $historiesPerPage = $config->get_int('notesHistoriesPerPage'); + $historiesPerPage = $config->get_int('notesHistoriesPerPage'); - $histories = $database->get_all("SELECT h.note_id, h.review_id, h.image_id, h.date, h.note, u.name AS user_name ". - "FROM note_histories AS h ". - "INNER JOIN users AS u ". - "ON u.id = h.user_id ". - "WHERE note_id = ? ". - "ORDER BY date DESC LIMIT ?, ?", - array($noteID, $pageNumber * $historiesPerPage, $historiesPerPage)); + $histories = $database->get_all( + "SELECT h.note_id, h.review_id, h.image_id, h.date, h.note, u.name AS user_name ". + "FROM note_histories AS h ". + "INNER JOIN users AS u ". + "ON u.id = h.user_id ". + "WHERE note_id = ? ". + "ORDER BY date DESC LIMIT ?, ?", + [$noteID, $pageNumber * $historiesPerPage, $historiesPerPage] + ); - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_histories WHERE note_id = ?", array($noteID)) / $historiesPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM note_histories WHERE note_id = ?", [$noteID]) / $historiesPerPage); - $this->theme->display_history($histories, $pageNumber + 1, $totalPages); - } + $this->theme->display_history($histories, $pageNumber + 1, $totalPages); + } - /** - * HERE GO BACK IN HISTORY AND SET THE OLD NOTE. IF WAS REMOVED WE RE-ADD IT. - */ - private function revert_history(int $noteID, int $reviewID){ - global $database; + /** + * HERE GO BACK IN HISTORY AND SET THE OLD NOTE. IF WAS REMOVED WE RE-ADD IT. + */ + private function revert_history(int $noteID, int $reviewID) + { + global $database; - $history = $database->get_row("SELECT * FROM note_histories WHERE note_id = ? AND review_id = ?", array($noteID, $reviewID)); + $history = $database->get_row("SELECT * FROM note_histories WHERE note_id = ? AND review_id = ?", [$noteID, $reviewID]); - $noteEnable = $history['note_enable']; - $noteID = $history['note_id']; - $imageID = $history['image_id']; - $noteX1 = $history['x1']; - $noteY1 = $history['y1']; - $noteHeight = $history['height']; - $noteWidth = $history['width']; - $noteText = $history['note']; + $noteEnable = $history['note_enable']; + $noteID = $history['note_id']; + $imageID = $history['image_id']; + $noteX1 = $history['x1']; + $noteY1 = $history['y1']; + $noteHeight = $history['height']; + $noteWidth = $history['width']; + $noteText = $history['note']; - $database->execute("UPDATE notes ". - "SET enable = ?, x1 = ?, y1 = ?, height = ?, width = ?, note = ? ". - "WHERE image_id = ? AND id = ?", - array(1, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText, $imageID, $noteID)); + $database->execute( + "UPDATE notes ". + "SET enable = ?, x1 = ?, y1 = ?, height = ?, width = ?, note = ? ". + "WHERE image_id = ? AND id = ?", + [1, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText, $imageID, $noteID] + ); - $this->add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); - } + $this->add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); + } } diff --git a/ext/notes/theme.php b/ext/notes/theme.php index ec8d7f35..912ec615 100644 --- a/ext/notes/theme.php +++ b/ext/notes/theme.php @@ -1,74 +1,81 @@ Add a note -->
    '; - } - public function request_button($image_id) { - return make_form(make_link("note/add_request")) . ' + } + public function request_button($image_id) + { + return make_form(make_link("note/add_request")) . ' '; - } - public function nuke_notes_button($image_id) { - return make_form(make_link("note/nuke_notes")) . ' + } + public function nuke_notes_button($image_id) + { + return make_form(make_link("note/nuke_notes")) . ' '; - } - public function nuke_requests_button($image_id) { - return make_form(make_link("note/nuke_requests")) . ' + } + public function nuke_requests_button($image_id) + { + return make_form(make_link("note/nuke_requests")) . ' '; - } + } - public function search_notes_page(Page $page) { //IN DEVELOPMENT, NOT FULLY WORKING - $html = '
    + public function search_notes_page(Page $page) + { //IN DEVELOPMENT, NOT FULLY WORKING + $html = '
    '; - $page->set_title(html_escape("Search Note")); - $page->set_heading(html_escape("Search Note")); - $page->add_block(new Block("Search Note", $html, "main", 10)); - } + $page->set_title(html_escape("Search Note")); + $page->set_heading(html_escape("Search Note")); + $page->add_block(new Block("Search Note", $html, "main", 10)); + } - // check action POST on form - public function display_note_system(Page $page, $image_id, $recovered_notes, $adminOptions) { - $base_href = get_base_href(); + // check action POST on form + public function display_note_system(Page $page, $image_id, $recovered_notes, $adminOptions) + { + $base_href = get_base_href(); - $page->add_html_header(""); - $page->add_html_header(""); - $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header(""); - $to_json = array(); - foreach($recovered_notes as $note) { - $parsedNote = $note["note"]; - $parsedNote = str_replace("\n", "\\n", $parsedNote); - $parsedNote = str_replace("\r", "\\r", $parsedNote); + $to_json = []; + foreach ($recovered_notes as $note) { + $parsedNote = $note["note"]; + $parsedNote = str_replace("\n", "\\n", $parsedNote); + $parsedNote = str_replace("\r", "\\r", $parsedNote); - $to_json[] = array( - 'x1' => $note["x1"], - 'y1' => $note["y1"], - 'height' => $note["height"], - 'width' => $note["width"], - 'note' => $parsedNote, - 'note_id' => $note["id"], - ); - } + $to_json[] = [ + 'x1' => $note["x1"], + 'y1' => $note["y1"], + 'height' => $note["height"], + 'width' => $note["width"], + 'note' => $parsedNote, + 'note_id' => $note["id"], + ]; + } - $html = ""; + $html = ""; - $html .= " + $html .= "
    ".make_form(make_link("note/add_note"))." @@ -112,8 +119,8 @@ class NotesTheme extends Themelet { "; - if($adminOptions) - $html .= " + if ($adminOptions) { + $html .= " ".make_form(make_link("note/delete_note"))." @@ -124,119 +131,120 @@ class NotesTheme extends Themelet { "; + } - $html .= "
    "; + $html .= ""; - $page->add_block(new Block(null, $html, "main", 1, 'note_system')); - } + $page->add_block(new Block(null, $html, "main", 1, 'note_system')); + } - public function display_note_list($images, $pageNumber, $totalPages) { - global $page; - $pool_images = ''; - foreach($images as $pair) { - $image = $pair[0]; + public function display_note_list($images, $pageNumber, $totalPages) + { + global $page; + $pool_images = ''; + foreach ($images as $pair) { + $image = $pair[0]; - $thumb_html = $this->build_thumb_html($image); + $thumb_html = $this->build_thumb_html($image); - $pool_images .= ''. - ' '.$thumb_html.''. - ''; + $pool_images .= ''. + ' '.$thumb_html.''. + ''; + } + $this->display_paginator($page, "note/list", null, $pageNumber, $totalPages); + $page->set_title("Notes"); + $page->set_heading("Notes"); + $page->add_block(new Block("Notes", $pool_images, "main", 20)); + } - } - $this->display_paginator($page, "note/list", null, $pageNumber, $totalPages); + public function display_note_requests($images, $pageNumber, $totalPages) + { + global $page; - $page->set_title("Notes"); - $page->set_heading("Notes"); - $page->add_block(new Block("Notes", $pool_images, "main", 20)); - } + $pool_images = ''; + foreach ($images as $pair) { + $image = $pair[0]; - public function display_note_requests($images, $pageNumber, $totalPages) { - global $page; + $thumb_html = $this->build_thumb_html($image); - $pool_images = ''; - foreach($images as $pair) { - $image = $pair[0]; + $pool_images .= ''. + ' '.$thumb_html.''. + ''; + } + $this->display_paginator($page, "requests/list", null, $pageNumber, $totalPages); - $thumb_html = $this->build_thumb_html($image); + $page->set_title("Note Requests"); + $page->set_heading("Note Requests"); + $page->add_block(new Block("Note Requests", $pool_images, "main", 20)); + } - $pool_images .= ''. - ' '.$thumb_html.''. - ''; + private function get_history($histories) + { + global $user; + $html = "". + "". + "". + "". + "". + "". + ""; - } - $this->display_paginator($page, "requests/list", null, $pageNumber, $totalPages); + if (!$user->is_anonymous()) { + $html .= ""; + } - $page->set_title("Note Requests"); - $page->set_heading("Note Requests"); - $page->add_block(new Block("Note Requests", $pool_images, "main", 20)); - } + $html .= "". + ""; - private function get_history($histories) { - global $user; + foreach ($histories as $history) { + $image_link = "".$history['image_id'].""; + $history_link = "".$history['note_id'].".".$history['review_id'].""; + $user_link = "".$history['user_name'].""; + $revert_link = "Revert"; - $html = "
    ImageNoteBodyUpdaterDateAction
    ". - "". - "". - "". - "". - "". - ""; + $html .= "". + "". + "". + "". + "". + ""; - if(!$user->is_anonymous()){ - $html .= ""; - } + if (!$user->is_anonymous()) { + $html .= ""; + } + } - $html .= "". - ""; + $html .= "
    ImageNoteBodyUpdaterDate
    ".$image_link."".$history_link."".$history['note']."".$user_link."".autodate($history['date'])."Action".$revert_link."
    "; - foreach($histories as $history) { - $image_link = "".$history['image_id'].""; - $history_link = "".$history['note_id'].".".$history['review_id'].""; - $user_link = "".$history['user_name'].""; - $revert_link = "Revert"; + return $html; + } - $html .= "". - "".$image_link."". - "".$history_link."". - "".$history['note']."". - "".$user_link."". - "".autodate($history['date']).""; + public function display_histories($histories, $pageNumber, $totalPages) + { + global $page; - if(!$user->is_anonymous()){ - $html .= "".$revert_link.""; - } + $html = $this->get_history($histories); - } + $page->set_title("Note Updates"); + $page->set_heading("Note Updates"); + $page->add_block(new Block("Note Updates", $html, "main", 10)); - $html .= ""; + $this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages); + } - return $html; - } + public function display_history($histories, $pageNumber, $totalPages) + { + global $page; - public function display_histories($histories, $pageNumber, $totalPages) { - global $page; + $html = $this->get_history($histories); - $html = $this->get_history($histories); + $page->set_title("Note History"); + $page->set_heading("Note History"); + $page->add_block(new Block("Note History", $html, "main", 10)); - $page->set_title("Note Updates"); - $page->set_heading("Note Updates"); - $page->add_block(new Block("Note Updates", $html, "main", 10)); - - $this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages); - } - - public function display_history($histories, $pageNumber, $totalPages) { - global $page; - - $html = $this->get_history($histories); - - $page->set_title("Note History"); - $page->set_heading("Note History"); - $page->add_block(new Block("Note History", $html, "main", 10)); - - $this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages); - } + $this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages); + } } diff --git a/ext/numeric_score/main.php b/ext/numeric_score/main.php index 649ab0c0..f15a9d37 100644 --- a/ext/numeric_score/main.php +++ b/ext/numeric_score/main.php @@ -10,186 +10,206 @@ * image's score is the sum of all votes. */ -class NumericScoreSetEvent extends Event { - public $image_id, $user, $score; +class NumericScoreSetEvent extends Event +{ + public $image_id; + public $user; + public $score; - public function __construct(int $image_id, User $user, int $score) { - $this->image_id = $image_id; - $this->user = $user; - $this->score = $score; - } + public function __construct(int $image_id, User $user, int $score) + { + $this->image_id = $image_id; + $this->user = $user; + $this->score = $score; + } } -class NumericScore extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - if($config->get_int("ext_numeric_score_version", 0) < 1) { - $this->install(); - } - } +class NumericScore extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + if ($config->get_int("ext_numeric_score_version", 0) < 1) { + $this->install(); + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $user; - if(!$user->is_anonymous()) { - $this->theme->get_voter($event->image); - } - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $user; + if (!$user->is_anonymous()) { + $this->theme->get_voter($event->image); + } + } - public function onUserPageBuilding(UserPageBuildingEvent $event) { - global $user; - if($user->can("edit_other_vote")) { - $this->theme->get_nuller($event->display_user); - } + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + global $user; + if ($user->can("edit_other_vote")) { + $this->theme->get_nuller($event->display_user); + } - $u_id = url_escape($event->display_user->id); - $n_up = Image::count_images(array("upvoted_by_id={$event->display_user->id}")); - $link_up = make_link("post/list/upvoted_by_id=$u_id/1"); - $n_down = Image::count_images(array("downvoted_by_id={$event->display_user->id}")); - $link_down = make_link("post/list/downvoted_by_id=$u_id/1"); - $event->add_stats("$n_up Upvotes / $n_down Downvotes"); - } + $u_id = url_escape($event->display_user->id); + $n_up = Image::count_images(["upvoted_by_id={$event->display_user->id}"]); + $link_up = make_link("post/list/upvoted_by_id=$u_id/1"); + $n_down = Image::count_images(["downvoted_by_id={$event->display_user->id}"]); + $link_down = make_link("post/list/downvoted_by_id=$u_id/1"); + $event->add_stats("$n_up Upvotes / $n_down Downvotes"); + } - public function onPageRequest(PageRequestEvent $event) { - global $config, $database, $user, $page; + public function onPageRequest(PageRequestEvent $event) + { + global $config, $database, $user, $page; - if($event->page_matches("numeric_score_votes")) { - $image_id = int_escape($event->get_arg(0)); - $x = $database->get_all( - "SELECT users.name as username, user_id, score + if ($event->page_matches("numeric_score_votes")) { + $image_id = int_escape($event->get_arg(0)); + $x = $database->get_all( + "SELECT users.name as username, user_id, score FROM numeric_score_votes JOIN users ON numeric_score_votes.user_id=users.id WHERE image_id=?", - array($image_id)); - $html = ""; - foreach($x as $vote) { - $html .= ""; - } - die($html); - } - else if($event->page_matches("numeric_score_vote") && $user->check_auth_token()) { - if(!$user->is_anonymous()) { - $image_id = int_escape($_POST['image_id']); - $char = $_POST['vote']; - $score = null; - if($char == "up") $score = 1; - else if($char == "null") $score = 0; - else if($char == "down") $score = -1; - if(!is_null($score) && $image_id>0) send_event(new NumericScoreSetEvent($image_id, $user, $score)); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$image_id")); - } - } - else if($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) { - if($user->can("edit_other_vote")) { - $image_id = int_escape($_POST['image_id']); - $database->execute( - "DELETE FROM numeric_score_votes WHERE image_id=?", - array($image_id)); - $database->execute( - "UPDATE images SET numeric_score=0 WHERE id=?", - array($image_id)); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$image_id")); - } - } - else if($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) { - if($user->can("edit_other_vote")) { - $this->delete_votes_by(int_escape($_POST['user_id'])); - $page->set_mode("redirect"); - $page->set_redirect(make_link()); - } - } - else if($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) { - //FIXME: popular_by isn't linked from anywhere - list($day, $month, $year) = array(date("d"), date("m"), date("Y")); + [$image_id] + ); + $html = "
    "; - $html .= "{$vote['username']}"; - $html .= ""; - $html .= $vote['score']; - $html .= "
    "; + foreach ($x as $vote) { + $html .= ""; + } + die($html); + } elseif ($event->page_matches("numeric_score_vote") && $user->check_auth_token()) { + if (!$user->is_anonymous()) { + $image_id = int_escape($_POST['image_id']); + $char = $_POST['vote']; + $score = null; + if ($char == "up") { + $score = 1; + } elseif ($char == "null") { + $score = 0; + } elseif ($char == "down") { + $score = -1; + } + if (!is_null($score) && $image_id>0) { + send_event(new NumericScoreSetEvent($image_id, $user, $score)); + } + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$image_id")); + } + } elseif ($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) { + if ($user->can("edit_other_vote")) { + $image_id = int_escape($_POST['image_id']); + $database->execute( + "DELETE FROM numeric_score_votes WHERE image_id=?", + [$image_id] + ); + $database->execute( + "UPDATE images SET numeric_score=0 WHERE id=?", + [$image_id] + ); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$image_id")); + } + } elseif ($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) { + if ($user->can("edit_other_vote")) { + $this->delete_votes_by(int_escape($_POST['user_id'])); + $page->set_mode("redirect"); + $page->set_redirect(make_link()); + } + } elseif ($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) { + //FIXME: popular_by isn't linked from anywhere + list($day, $month, $year) = [date("d"), date("m"), date("Y")]; - if(!empty($_GET['day'])){ - $D = (int) $_GET['day']; - $day = clamp($D, 1, 31); - } - if(!empty($_GET['month'])){ - $M = (int) $_GET['month']; - $month = clamp($M, 1 ,12); - } - if(!empty($_GET['year'])){ - $Y = (int) $_GET['year']; - $year = clamp($Y, 1970, 2100); - } + if (!empty($_GET['day'])) { + $D = (int) $_GET['day']; + $day = clamp($D, 1, 31); + } + if (!empty($_GET['month'])) { + $M = (int) $_GET['month']; + $month = clamp($M, 1, 12); + } + if (!empty($_GET['year'])) { + $Y = (int) $_GET['year']; + $year = clamp($Y, 1970, 2100); + } - $totaldate = $year."/".$month."/".$day; + $totaldate = $year."/".$month."/".$day; - $sql = "SELECT id FROM images + $sql = "SELECT id FROM images WHERE EXTRACT(YEAR FROM posted) = :year "; - $args = array("limit" => $config->get_int("index_images"), "year" => $year); + $args = ["limit" => $config->get_int("index_images"), "year" => $year]; - if($event->page_matches("popular_by_day")){ - $sql .= - "AND EXTRACT(MONTH FROM posted) = :month + if ($event->page_matches("popular_by_day")) { + $sql .= + "AND EXTRACT(MONTH FROM posted) = :month AND EXTRACT(DAY FROM posted) = :day"; - $args = array_merge($args, array("month" => $month, "day" => $day)); - $dte = array($totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day"); - } - else if($event->page_matches("popular_by_month")){ - $sql .= "AND EXTRACT(MONTH FROM posted) = :month"; + $args = array_merge($args, ["month" => $month, "day" => $day]); + $dte = [$totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day"]; + } elseif ($event->page_matches("popular_by_month")) { + $sql .= "AND EXTRACT(MONTH FROM posted) = :month"; - $args = array_merge($args, array("month" => $month)); - $dte = array($totaldate, date("F Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month"); - } - else if($event->page_matches("popular_by_year")){ - $dte = array($totaldate, $year, "\\y\\e\\a\\r\=Y", "year"); - } - else { - // this should never happen due to the fact that the page event is already matched against earlier. - throw new UnexpectedValueException("Error: Invalid page event."); - } - $sql .= " AND NOT numeric_score=0 ORDER BY numeric_score DESC LIMIT :limit OFFSET 0"; + $args = array_merge($args, ["month" => $month]); + $dte = [$totaldate, date("F Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month"]; + } elseif ($event->page_matches("popular_by_year")) { + $dte = [$totaldate, $year, "\\y\\e\\a\\r\=Y", "year"]; + } else { + // this should never happen due to the fact that the page event is already matched against earlier. + throw new UnexpectedValueException("Error: Invalid page event."); + } + $sql .= " AND NOT numeric_score=0 ORDER BY numeric_score DESC LIMIT :limit OFFSET 0"; - //filter images by score != 0 + date > limit to max images on one page > order from highest to lowest score + //filter images by score != 0 + date > limit to max images on one page > order from highest to lowest score - $result = $database->get_col($sql, $args); - $images = array(); - foreach($result as $id) { $images[] = Image::by_id($id); } + $result = $database->get_col($sql, $args); + $images = []; + foreach ($result as $id) { + $images[] = Image::by_id($id); + } - $this->theme->view_popular($images, $dte); - } - } + $this->theme->view_popular($images, $dte); + } + } - public function onNumericScoreSet(NumericScoreSetEvent $event) { - global $user; - log_debug("numeric_score", "Rated Image #{$event->image_id} as {$event->score}", "Rated Image", array("image_id"=>$event->image_id)); - $this->add_vote($event->image_id, $user->id, $event->score); - } + public function onNumericScoreSet(NumericScoreSetEvent $event) + { + global $user; + log_debug("numeric_score", "Rated Image #{$event->image_id} as {$event->score}", "Rated Image", ["image_id"=>$event->image_id]); + $this->add_vote($event->image_id, $user->id, $event->score); + } - public function onImageDeletion(ImageDeletionEvent $event) { - global $database; - $database->execute("DELETE FROM numeric_score_votes WHERE image_id=:id", array("id" => $event->image->id)); - } + public function onImageDeletion(ImageDeletionEvent $event) + { + global $database; + $database->execute("DELETE FROM numeric_score_votes WHERE image_id=:id", ["id" => $event->image->id]); + } - public function onUserDeletion(UserDeletionEvent $event) { - $this->delete_votes_by($event->id); - } + public function onUserDeletion(UserDeletionEvent $event) + { + $this->delete_votes_by($event->id); + } - public function delete_votes_by(int $user_id) { - global $database; + public function delete_votes_by(int $user_id) + { + global $database; - $image_ids = $database->get_col("SELECT image_id FROM numeric_score_votes WHERE user_id=?", array($user_id)); + $image_ids = $database->get_col("SELECT image_id FROM numeric_score_votes WHERE user_id=?", [$user_id]); - if(count($image_ids) == 0) return; + if (count($image_ids) == 0) { + return; + } - // vote recounting is pretty heavy, and often hits statement timeouts - // if you try to recount all the images in one go - foreach(array_chunk($image_ids, 20) as $chunk) { - $id_list = implode(",", $chunk); - $database->execute( - "DELETE FROM numeric_score_votes WHERE user_id=? AND image_id IN (".$id_list.")", - array($user_id)); - $database->execute(" + // vote recounting is pretty heavy, and often hits statement timeouts + // if you try to recount all the images in one go + foreach (array_chunk($image_ids, 20) as $chunk) { + $id_list = implode(",", $chunk); + $database->execute( + "DELETE FROM numeric_score_votes WHERE user_id=? AND image_id IN (".$id_list.")", + [$user_id] + ); + $database->execute(" UPDATE images SET numeric_score=COALESCE( ( @@ -200,82 +220,89 @@ class NumericScore extends Extension { 0 ) WHERE images.id IN (".$id_list.")"); - } - } + } + } - public function onParseLinkTemplate(ParseLinkTemplateEvent $event) { - $event->replace('$score', $event->image->numeric_score); - } + public function onParseLinkTemplate(ParseLinkTemplateEvent $event) + { + $event->replace('$score', $event->image->numeric_score); + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - if(preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\d+)$/i", $event->term, $matches)) { - $cmp = ltrim($matches[1], ":") ?: "="; - $score = $matches[2]; - $event->add_querylet(new Querylet("numeric_score $cmp $score")); - } - else if(preg_match("/^upvoted_by[=|:](.*)$/i", $event->term, $matches)) { - $duser = User::by_name($matches[1]); - if(is_null($duser)) { - throw new SearchTermParseException( - "Can't find the user named ".html_escape($matches[1])); - } - $event->add_querylet(new Querylet( - "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", - array("ns_user_id"=>$duser->id))); - } - else if(preg_match("/^downvoted_by[=|:](.*)$/i", $event->term, $matches)) { - $duser = User::by_name($matches[1]); - if(is_null($duser)) { - throw new SearchTermParseException( - "Can't find the user named ".html_escape($matches[1])); - } - $event->add_querylet(new Querylet( - "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", - array("ns_user_id"=>$duser->id))); - } - else if(preg_match("/^upvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) { - $iid = int_escape($matches[1]); - $event->add_querylet(new Querylet( - "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", - array("ns_user_id"=>$iid))); - } - else if(preg_match("/^downvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) { - $iid = int_escape($matches[1]); - $event->add_querylet(new Querylet( - "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", - array("ns_user_id"=>$iid))); - } - else if(preg_match("/^order[=|:](?:numeric_)?(score)(?:_(desc|asc))?$/i", $event->term, $matches)){ - $default_order_for_column = "DESC"; - $sort = isset($matches[2]) ? strtoupper($matches[2]) : $default_order_for_column; - Image::$order_sql = "images.numeric_score $sort"; - $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag - } - } + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + if (preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\d+)$/i", $event->term, $matches)) { + $cmp = ltrim($matches[1], ":") ?: "="; + $score = $matches[2]; + $event->add_querylet(new Querylet("numeric_score $cmp $score")); + } elseif (preg_match("/^upvoted_by[=|:](.*)$/i", $event->term, $matches)) { + $duser = User::by_name($matches[1]); + if (is_null($duser)) { + throw new SearchTermParseException( + "Can't find the user named ".html_escape($matches[1]) + ); + } + $event->add_querylet(new Querylet( + "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", + ["ns_user_id"=>$duser->id] + )); + } elseif (preg_match("/^downvoted_by[=|:](.*)$/i", $event->term, $matches)) { + $duser = User::by_name($matches[1]); + if (is_null($duser)) { + throw new SearchTermParseException( + "Can't find the user named ".html_escape($matches[1]) + ); + } + $event->add_querylet(new Querylet( + "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", + ["ns_user_id"=>$duser->id] + )); + } elseif (preg_match("/^upvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) { + $iid = int_escape($matches[1]); + $event->add_querylet(new Querylet( + "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", + ["ns_user_id"=>$iid] + )); + } elseif (preg_match("/^downvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) { + $iid = int_escape($matches[1]); + $event->add_querylet(new Querylet( + "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", + ["ns_user_id"=>$iid] + )); + } elseif (preg_match("/^order[=|:](?:numeric_)?(score)(?:_(desc|asc))?$/i", $event->term, $matches)) { + $default_order_for_column = "DESC"; + $sort = isset($matches[2]) ? strtoupper($matches[2]) : $default_order_for_column; + Image::$order_sql = "images.numeric_score $sort"; + $event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag + } + } - public function onTagTermParse(TagTermParseEvent $event) { - $matches = array(); + public function onTagTermParse(TagTermParseEvent $event) + { + $matches = []; - if(preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches) && $event->parse) { - global $user; - $score = ($matches[1] == "up" ? 1 : ($matches[1] == "down" ? -1 : 0)); - if(!$user->is_anonymous()) { - send_event(new NumericScoreSetEvent($event->id, $user, $score)); - } - } + if (preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches) && $event->parse) { + global $user; + $score = ($matches[1] == "up" ? 1 : ($matches[1] == "down" ? -1 : 0)); + if (!$user->is_anonymous()) { + send_event(new NumericScoreSetEvent($event->id, $user, $score)); + } + } - if(!empty($matches)) $event->metatag = true; - } + if (!empty($matches)) { + $event->metatag = true; + } + } - private function install() { - global $database; - global $config; + private function install() + { + global $database; + global $config; - if($config->get_int("ext_numeric_score_version") < 1) { - $database->execute("ALTER TABLE images ADD COLUMN numeric_score INTEGER NOT NULL DEFAULT 0"); - $database->execute("CREATE INDEX images__numeric_score ON images(numeric_score)"); - $database->create_table("numeric_score_votes", " + if ($config->get_int("ext_numeric_score_version") < 1) { + $database->execute("ALTER TABLE images ADD COLUMN numeric_score INTEGER NOT NULL DEFAULT 0"); + $database->execute("CREATE INDEX images__numeric_score ON images(numeric_score)"); + $database->create_table("numeric_score_votes", " image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, score INTEGER NOT NULL, @@ -283,33 +310,36 @@ class NumericScore extends Extension { FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX numeric_score_votes_image_id_idx ON numeric_score_votes(image_id)", array()); - $config->set_int("ext_numeric_score_version", 1); - } - if($config->get_int("ext_numeric_score_version") < 2) { - $database->execute("CREATE INDEX numeric_score_votes__user_votes ON numeric_score_votes(user_id, score)"); - $config->set_int("ext_numeric_score_version", 2); - } - } + $database->execute("CREATE INDEX numeric_score_votes_image_id_idx ON numeric_score_votes(image_id)", []); + $config->set_int("ext_numeric_score_version", 1); + } + if ($config->get_int("ext_numeric_score_version") < 2) { + $database->execute("CREATE INDEX numeric_score_votes__user_votes ON numeric_score_votes(user_id, score)"); + $config->set_int("ext_numeric_score_version", 2); + } + } - private function add_vote(int $image_id, int $user_id, int $score) { - global $database; - $database->execute( - "DELETE FROM numeric_score_votes WHERE image_id=:imageid AND user_id=:userid", - array("imageid" => $image_id, "userid" => $user_id)); - if($score != 0) { - $database->execute( - "INSERT INTO numeric_score_votes(image_id, user_id, score) VALUES(:imageid, :userid, :score)", - array("imageid" => $image_id, "userid" => $user_id, "score" => $score)); - } - $database->Execute( - "UPDATE images SET numeric_score=( + private function add_vote(int $image_id, int $user_id, int $score) + { + global $database; + $database->execute( + "DELETE FROM numeric_score_votes WHERE image_id=:imageid AND user_id=:userid", + ["imageid" => $image_id, "userid" => $user_id] + ); + if ($score != 0) { + $database->execute( + "INSERT INTO numeric_score_votes(image_id, user_id, score) VALUES(:imageid, :userid, :score)", + ["imageid" => $image_id, "userid" => $user_id, "score" => $score] + ); + } + $database->Execute( + "UPDATE images SET numeric_score=( COALESCE( (SELECT SUM(score) FROM numeric_score_votes WHERE image_id=:imageid), 0 ) ) WHERE id=:id", - array("imageid" => $image_id, "id" => $image_id)); - } + ["imageid" => $image_id, "id" => $image_id] + ); + } } - diff --git a/ext/numeric_score/test.php b/ext/numeric_score/test.php index f492acdb..3fa7a5d5 100644 --- a/ext/numeric_score/test.php +++ b/ext/numeric_score/test.php @@ -1,60 +1,61 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); +class NumericScoreTest extends ShimmiePHPUnitTestCase +{ + public function testNumericScore() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->assert_text("Current Score: 0"); - $this->click("Vote Down"); - $this->assert_text("Current Score: -1"); - $this->click("Vote Up"); - $this->assert_text("Current Score: 1"); - # FIXME: "remove vote" button? - # FIXME: test that up and down are hidden if already voted up or down + $this->assert_text("Current Score: 0"); + $this->click("Vote Down"); + $this->assert_text("Current Score: -1"); + $this->click("Vote Up"); + $this->assert_text("Current Score: 1"); + # FIXME: "remove vote" button? + # FIXME: test that up and down are hidden if already voted up or down - # test search by score - $this->get_page("post/list/score=1/1"); - $this->assert_title("Image $image_id: pbx"); + # test search by score + $this->get_page("post/list/score=1/1"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("post/list/score>0/1"); - $this->assert_title("Image $image_id: pbx"); + $this->get_page("post/list/score>0/1"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("post/list/score>-5/1"); - $this->assert_title("Image $image_id: pbx"); + $this->get_page("post/list/score>-5/1"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("post/list/-score>5/1"); - $this->assert_title("Image $image_id: pbx"); + $this->get_page("post/list/-score>5/1"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("post/list/-score<-5/1"); - $this->assert_title("Image $image_id: pbx"); + $this->get_page("post/list/-score<-5/1"); + $this->assert_title("Image $image_id: pbx"); - # test search by vote - $this->get_page("post/list/upvoted_by=test/1"); - $this->assert_title("Image $image_id: pbx"); - $this->assert_no_text("No Images Found"); + # test search by vote + $this->get_page("post/list/upvoted_by=test/1"); + $this->assert_title("Image $image_id: pbx"); + $this->assert_no_text("No Images Found"); - # and downvote - $this->get_page("post/list/downvoted_by=test/1"); - $this->assert_text("No Images Found"); + # and downvote + $this->get_page("post/list/downvoted_by=test/1"); + $this->assert_text("No Images Found"); - # test errors - $this->get_page("post/list/upvoted_by=asdfasdf/1"); - $this->assert_text("No Images Found"); - $this->get_page("post/list/downvoted_by=asdfasdf/1"); - $this->assert_text("No Images Found"); - $this->get_page("post/list/upvoted_by_id=0/1"); - $this->assert_text("No Images Found"); - $this->get_page("post/list/downvoted_by_id=0/1"); - $this->assert_text("No Images Found"); + # test errors + $this->get_page("post/list/upvoted_by=asdfasdf/1"); + $this->assert_text("No Images Found"); + $this->get_page("post/list/downvoted_by=asdfasdf/1"); + $this->assert_text("No Images Found"); + $this->get_page("post/list/upvoted_by_id=0/1"); + $this->assert_text("No Images Found"); + $this->get_page("post/list/downvoted_by_id=0/1"); + $this->assert_text("No Images Found"); - $this->log_out(); + $this->log_out(); - $this->log_in_as_admin(); - $this->delete_image($image_id); - $this->log_out(); - } + $this->log_in_as_admin(); + $this->delete_image($image_id); + $this->log_out(); + } } - diff --git a/ext/numeric_score/theme.php b/ext/numeric_score/theme.php index d1a9f38b..c2dc31c7 100644 --- a/ext/numeric_score/theme.php +++ b/ext/numeric_score/theme.php @@ -1,12 +1,14 @@ id); - $i_score = int_escape($image->numeric_score); +class NumericScoreTheme extends Themelet +{ + public function get_voter(Image $image) + { + global $user, $page; + $i_image_id = int_escape($image->id); + $i_score = int_escape($image->numeric_score); - $html = " + $html = " Current Score: $i_score

    @@ -30,8 +32,8 @@ class NumericScoreTheme extends Themelet { "; - if($user->can("edit_other_vote")) { - $html .= " + if ($user->can("edit_other_vote")) { + $html .= "
    ".$user->get_auth_html()." @@ -45,48 +47,48 @@ class NumericScoreTheme extends Themelet { >See All Votes "; - } - $page->add_block(new Block("Image Score", $html, "left", 20)); - } + } + $page->add_block(new Block("Image Score", $html, "left", 20)); + } - public function get_nuller(User $duser) { - global $user, $page; - $html = " + public function get_nuller(User $duser) + { + global $user, $page; + $html = " ".$user->get_auth_html()." "; - $page->add_block(new Block("Votes", $html, "main", 80)); - } + $page->add_block(new Block("Votes", $html, "main", 80)); + } - public function view_popular($images, $dte) { - global $page, $config; + public function view_popular($images, $dte) + { + global $page, $config; - $pop_images = ""; - foreach($images as $image) { - $pop_images .= $this->build_thumb_html($image)."\n"; - } + $pop_images = ""; + foreach ($images as $image) { + $pop_images .= $this->build_thumb_html($image)."\n"; + } - $b_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('-1 '.$dte[3], strtotime($dte[0]))))); - $f_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('+1 '.$dte[3], strtotime($dte[0]))))); + $b_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('-1 '.$dte[3], strtotime($dte[0]))))); + $f_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('+1 '.$dte[3], strtotime($dte[0]))))); - $html = "\n". - "

    \n". - "

    \n". - " « {$dte[1]} »\n". - "

    \n". - "
    \n". - "
    \n".$pop_images; + $html = "\n". + "
    \n". + "

    \n". + " « {$dte[1]} »\n". + "

    \n". + "
    \n". + "
    \n".$pop_images; - $nav_html = "Index"; + $nav_html = "Index"; - $page->set_heading($config->get_string('title')); - $page->add_block(new Block("Navigation", $nav_html, "left", 10)); - $page->add_block(new Block(null, $html, "main", 30)); - } + $page->set_heading($config->get_string('title')); + $page->add_block(new Block("Navigation", $nav_html, "left", 10)); + $page->add_block(new Block(null, $html, "main", 30)); + } } - - diff --git a/ext/oekaki/main.php b/ext/oekaki/main.php index c26c1019..f18383e9 100644 --- a/ext/oekaki/main.php +++ b/ext/oekaki/main.php @@ -5,86 +5,87 @@ * Description: ChibiPaint-based Oekaki uploader */ -class Oekaki extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $user, $page; +class Oekaki extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $user, $page; - if($event->page_matches("oekaki")) { - if($user->can("create_image")) { - if($event->get_arg(0) == "create") { - $this->theme->display_page(); - $this->theme->display_block(); - } - if($event->get_arg(0) == "claim") { - // FIXME: move .chi to data/oekaki/$ha/$hash mirroring images and thumbs - // FIXME: .chi viewer? - // FIXME: clean out old unclaimed images? - $pattern = data_path('oekaki_unclaimed/' . $_SERVER['REMOTE_ADDR'] . ".*.png"); - foreach(glob($pattern) as $tmpname) { - assert(file_exists($tmpname)); + if ($event->page_matches("oekaki")) { + if ($user->can("create_image")) { + if ($event->get_arg(0) == "create") { + $this->theme->display_page(); + $this->theme->display_block(); + } + if ($event->get_arg(0) == "claim") { + // FIXME: move .chi to data/oekaki/$ha/$hash mirroring images and thumbs + // FIXME: .chi viewer? + // FIXME: clean out old unclaimed images? + $pattern = data_path('oekaki_unclaimed/' . $_SERVER['REMOTE_ADDR'] . ".*.png"); + foreach (glob($pattern) as $tmpname) { + assert(file_exists($tmpname)); - $pathinfo = pathinfo($tmpname); - if(!array_key_exists('extension', $pathinfo)) { - throw new UploadException("File has no extension"); - } - log_info("oekaki", "Processing file [{$pathinfo['filename']}]"); - $metadata = array(); - $metadata['filename'] = 'oekaki.png'; - $metadata['extension'] = $pathinfo['extension']; - $metadata['tags'] = Tag::explode('oekaki tagme'); - $metadata['source'] = null; - $duev = new DataUploadEvent($tmpname, $metadata); - send_event($duev); - if($duev->image_id == -1) { - throw new UploadException("File type not recognised"); - } - else { - unlink($tmpname); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/".$duev->image_id)); - } - } - } - } - if($event->get_arg(0) == "upload") { - // FIXME: this allows anyone to upload anything to /data ... - // hardcoding the ext to .png should stop the obvious exploit, - // but more checking may be wise - if(isset($_FILES["picture"])) { - header('Content-type: text/plain'); + $pathinfo = pathinfo($tmpname); + if (!array_key_exists('extension', $pathinfo)) { + throw new UploadException("File has no extension"); + } + log_info("oekaki", "Processing file [{$pathinfo['filename']}]"); + $metadata = []; + $metadata['filename'] = 'oekaki.png'; + $metadata['extension'] = $pathinfo['extension']; + $metadata['tags'] = Tag::explode('oekaki tagme'); + $metadata['source'] = null; + $duev = new DataUploadEvent($tmpname, $metadata); + send_event($duev); + if ($duev->image_id == -1) { + throw new UploadException("File type not recognised"); + } else { + unlink($tmpname); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$duev->image_id)); + } + } + } + } + if ($event->get_arg(0) == "upload") { + // FIXME: this allows anyone to upload anything to /data ... + // hardcoding the ext to .png should stop the obvious exploit, + // but more checking may be wise + if (isset($_FILES["picture"])) { + header('Content-type: text/plain'); - $file = $_FILES['picture']['name']; - //$ext = (strpos($file, '.') === FALSE) ? '' : substr($file, strrpos($file, '.')); - $uploadname = $_SERVER['REMOTE_ADDR'] . "." . time(); - $uploadfile = data_path('oekaki_unclaimed/'.$uploadname); + $file = $_FILES['picture']['name']; + //$ext = (strpos($file, '.') === FALSE) ? '' : substr($file, strrpos($file, '.')); + $uploadname = $_SERVER['REMOTE_ADDR'] . "." . time(); + $uploadfile = data_path('oekaki_unclaimed/'.$uploadname); - log_info("oekaki", "Uploading file [$uploadname]"); + log_info("oekaki", "Uploading file [$uploadname]"); - $success = TRUE; - if (isset($_FILES["chibifile"])) - $success = $success && move_uploaded_file($_FILES['chibifile']['tmp_name'], $uploadfile . ".chi"); + $success = true; + if (isset($_FILES["chibifile"])) { + $success = $success && move_uploaded_file($_FILES['chibifile']['tmp_name'], $uploadfile . ".chi"); + } - // hardcode the ext, so nobody can upload "foo.php" - $success = $success && move_uploaded_file($_FILES['picture']['tmp_name'], $uploadfile . ".png"); # $ext); - if ($success) { - echo "CHIBIOK\n"; - } else { - echo "CHIBIERROR\n"; - } - } - else { - echo "CHIBIERROR No Data\n"; - } - } - } - } + // hardcode the ext, so nobody can upload "foo.php" + $success = $success && move_uploaded_file($_FILES['picture']['tmp_name'], $uploadfile . ".png"); # $ext); + if ($success) { + echo "CHIBIOK\n"; + } else { + echo "CHIBIERROR\n"; + } + } else { + echo "CHIBIERROR No Data\n"; + } + } + } + } - // FIXME: "edit this image" button on existing images? - function onPostListBuilding(PostListBuildingEvent $event) { - global $user; - if($user->can("create_image")) { - $this->theme->display_block(); - } - } + // FIXME: "edit this image" button on existing images? + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $user; + if ($user->can("create_image")) { + $this->theme->display_block(); + } + } } - diff --git a/ext/oekaki/test.php b/ext/oekaki/test.php index 1061595c..c094bce3 100644 --- a/ext/oekaki/test.php +++ b/ext/oekaki/test.php @@ -1,7 +1,9 @@ log_in_as_user(); - $this->get_page("oekaki/create"); - } +class OekakiTest extends ShimmiePHPUnitTestCase +{ + public function testLog() + { + $this->log_in_as_user(); + $this->get_page("oekaki/create"); + } } diff --git a/ext/oekaki/theme.php b/ext/oekaki/theme.php index 8a0ee9b9..ae29a6ac 100644 --- a/ext/oekaki/theme.php +++ b/ext/oekaki/theme.php @@ -2,22 +2,24 @@ // FIXME: Move all the stuff that handles size input to main.php // FIXME: Move default canvas size to config file; changeable in board config // While we're here, add maximum and minimum image sizes in config -// Maybe allow the resolution limiter extension to have a say in this +// Maybe allow the resolution limiter extension to have a say in this -class OekakiTheme extends Themelet { - public function display_page() { - global $config, $page; +class OekakiTheme extends Themelet +{ + public function display_page() + { + global $config, $page; - $base_href = get_base_href(); + $base_href = get_base_href(); - $oekW = $config->get_int("oekaki_width", 400); - $oekH = $config->get_int("oekaki_height", 400); - if(isset($_POST['oekW']) && isset($_POST['oekH'])) { - $oekW = int_escape($_POST['oekW']); - $oekH = int_escape($_POST['oekH']); - } + $oekW = $config->get_int("oekaki_width", 400); + $oekH = $config->get_int("oekaki_height", 400); + if (isset($_POST['oekW']) && isset($_POST['oekH'])) { + $oekW = int_escape($_POST['oekW']); + $oekH = int_escape($_POST['oekH']); + } - $html = " + $html = " @@ -28,37 +30,40 @@ class OekakiTheme extends Themelet { "; -# -# - // FIXME: prevent oekaki block from collapsing on click in cerctain themes. This causes canvas reset - $page->set_title("Oekaki"); - $page->set_heading("Oekaki"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Oekaki", $html, "main", 20)); - } + # + # + // FIXME: prevent oekaki block from collapsing on click in cerctain themes. This causes canvas reset + $page->set_title("Oekaki"); + $page->set_heading("Oekaki"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Oekaki", $html, "main", 20)); + } - public function display_block() { - global $config, $page; - //FIXME: input field alignment could be done more elegantly, without inline styling - //FIXME: autocomplete='off' seems to be an invalid HTML tag + public function display_block() + { + global $config, $page; + //FIXME: input field alignment could be done more elegantly, without inline styling + //FIXME: autocomplete='off' seems to be an invalid HTML tag - $oekW = $config->get_int("oekaki_width", 400); - $oekH = $config->get_int("oekaki_height", 400); - if(isset($_POST['oekW']) && isset($_POST['oekH'])) { - $oekW = int_escape($_POST['oekW']); - $oekH = int_escape($_POST['oekH']); - } + $oekW = $config->get_int("oekaki_width", 400); + $oekH = $config->get_int("oekaki_height", 400); + if (isset($_POST['oekW']) && isset($_POST['oekH'])) { + $oekW = int_escape($_POST['oekW']); + $oekH = int_escape($_POST['oekH']); + } - $page->add_block(new Block("Oekaki", - " + $page->add_block(new Block( + "Oekaki", + " ". - "x". - "". - " + "x". + "". + " - " - , "left", 21)); // upload is 20 - } + ", + "left", + 21 + )); // upload is 20 + } } - diff --git a/ext/ouroboros_api/main.php b/ext/ouroboros_api/main.php index fd3623b8..54a68d35 100644 --- a/ext/ouroboros_api/main.php +++ b/ext/ouroboros_api/main.php @@ -209,7 +209,7 @@ class _SafeOuroborosImage // meta $this->change = intval($img->id); //DaFug is this even supposed to do? ChangeID? // Should be JSON specific, just strip this when converting to XML - $this->created_at = array('n' => 123456789, 's' => strtotime($img->posted), 'json_class' => 'Time'); + $this->created_at = ['n' => 123456789, 's' => strtotime($img->posted), 'json_class' => 'Time']; $this->id = intval($img->id); $this->parent_id = null; if (defined('ENABLED_EXTS')) { @@ -248,7 +248,7 @@ class OuroborosPost extends _SafeOuroborosImage * Multipart File * @var array */ - public $file = array(); + public $file = []; /** * Create with rating locked @@ -416,7 +416,6 @@ class OuroborosAPI extends Extension } else { $this->sendResponse(403, 'You cannot create new posts'); } - } elseif ($this->match('update')) { // Update //@todo add post update @@ -432,7 +431,7 @@ class OuroborosAPI extends Extension $p = !empty($_REQUEST['page']) ? intval( filter_var($_REQUEST['page'], FILTER_SANITIZE_NUMBER_INT) ) : 1; - $tags = !empty($_REQUEST['tags']) ? filter_var($_REQUEST['tags'], FILTER_SANITIZE_STRING) : array(); + $tags = !empty($_REQUEST['tags']) ? filter_var($_REQUEST['tags'], FILTER_SANITIZE_STRING) : []; if (!empty($tags)) { $tags = Tag::explode($tags); } @@ -470,7 +469,6 @@ class OuroborosAPI extends Extension $page->display(); die(); } - } /** @@ -491,7 +489,7 @@ class OuroborosAPI extends Extension return; } } - $meta = array(); + $meta = []; $meta['tags'] = is_array($post->tags) ? $post->tags : Tag::explode($post->tags); $meta['source'] = $post->source; if (defined('ENABLED_EXTS')) { @@ -501,8 +499,8 @@ class OuroborosAPI extends Extension } // Check where we should try for the file if (empty($post->file) && !empty($post->file_url) && filter_var( - $post->file_url, - FILTER_VALIDATE_URL + $post->file_url, + FILTER_VALIDATE_URL ) !== false ) { // Transload from source @@ -527,19 +525,18 @@ class OuroborosAPI extends Extension $img = Image::by_hash($meta['hash']); if (!is_null($img)) { $handler = $config->get_string("upload_collision_handler"); - if($handler == "merge") { + if ($handler == "merge") { $postTags = is_array($post->tags) ? $post->tags : Tag::explode($post->tags); $merged = array_merge($postTags, $img->get_tag_array()); send_event(new TagSetEvent($img, $merged)); // This is really the only thing besides tags we should care - if(isset($meta['source'])){ + if (isset($meta['source'])) { send_event(new SourceSetEvent($img, $meta['source'])); } $this->sendResponse(200, self::OK_POST_CREATE_UPDATE . ' ID: ' . $img->id); return; - } - else { + } else { $this->sendResponse(420, self::ERROR_POST_CREATE_DUPE); return; } @@ -586,7 +583,7 @@ class OuroborosAPI extends Extension { $start = ($page - 1) * $limit; $results = Image::find_images(max($start, 0), min($limit, 100), $tags); - $posts = array(); + $posts = []; foreach ($results as $img) { if (!is_object($img)) { continue; @@ -604,7 +601,7 @@ class OuroborosAPI extends Extension { global $database, $config; $start = ($page - 1) * $limit; - $tag_data = array(); + $tag_data = []; switch ($order) { case 'name': $tag_data = $database->get_col( @@ -617,7 +614,7 @@ class OuroborosAPI extends Extension ORDER BY SCORE_STRNORM(substr(tag, 1, 1)) LIMIT :start, :max_items " ), - array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) + ['tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit] ); break; case 'count': @@ -628,7 +625,7 @@ class OuroborosAPI extends Extension WHERE count >= :tags_min ORDER BY count DESC, tag ASC LIMIT :start, :max_items ", - array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) + ['tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit] ); break; case 'date': @@ -639,11 +636,11 @@ class OuroborosAPI extends Extension WHERE count >= :tags_min ORDER BY count DESC, tag ASC LIMIT :start, :max_items ", - array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) + ['tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit] ); break; } - $tags = array(); + $tags = []; foreach ($tag_data as $tag) { if (!is_array($tag)) { continue; @@ -686,7 +683,7 @@ class OuroborosAPI extends Extension } header("{$proto} {$code} {$header}", true); } - $response = array('success' => $success, 'reason' => $reason); + $response = ['success' => $success, 'reason' => $reason]; if ($this->type == 'json') { if ($location !== false) { $response['location'] = $response['reason']; @@ -713,7 +710,7 @@ class OuroborosAPI extends Extension $page->set_data($response); } - private function sendData(string $type = '', array $data = array(), int $offset = 0) + private function sendData(string $type = '', array $data = [], int $offset = 0) { global $page; $response = ''; diff --git a/ext/pm/main.php b/ext/pm/main.php index a5fc3e8f..2cf8d0a7 100644 --- a/ext/pm/main.php +++ b/ext/pm/main.php @@ -10,49 +10,61 @@ * profile page and a box will be shown. */ -class SendPMEvent extends Event { - public $pm; +class SendPMEvent extends Event +{ + public $pm; - public function __construct(PM $pm) { - $this->pm = $pm; - } + public function __construct(PM $pm) + { + $this->pm = $pm; + } } -class PM { - public $id, $from_id, $from_ip, $to_id, $sent_date, $subject, $message, $is_read; +class PM +{ + public $id; + public $from_id; + public $from_ip; + public $to_id; + public $sent_date; + public $subject; + public $message; + public $is_read; - public function __construct($from_id=0, string $from_ip="0.0.0.0", int $to_id=0, string $subject="A Message", string $message="Some Text", bool $read=False) { - # PHP: the P stands for "really", the H stands for "awful" and the other P stands for "language" - if(is_array($from_id)) { - $a = $from_id; - $this->id = $a["id"]; - $this->from_id = $a["from_id"]; - $this->from_ip = $a["from_ip"]; - $this->to_id = $a["to_id"]; - $this->sent_date = $a["sent_date"]; - $this->subject = $a["subject"]; - $this->message = $a["message"]; - $this->is_read = bool_escape($a["is_read"]); - } - else { - $this->id = -1; - $this->from_id = $from_id; - $this->from_ip = $from_ip; - $this->to_id = $to_id; - $this->subject = $subject; - $this->message = $message; - $this->is_read = $read; - } - } + public function __construct($from_id=0, string $from_ip="0.0.0.0", int $to_id=0, string $subject="A Message", string $message="Some Text", bool $read=false) + { + # PHP: the P stands for "really", the H stands for "awful" and the other P stands for "language" + if (is_array($from_id)) { + $a = $from_id; + $this->id = $a["id"]; + $this->from_id = $a["from_id"]; + $this->from_ip = $a["from_ip"]; + $this->to_id = $a["to_id"]; + $this->sent_date = $a["sent_date"]; + $this->subject = $a["subject"]; + $this->message = $a["message"]; + $this->is_read = bool_escape($a["is_read"]); + } else { + $this->id = -1; + $this->from_id = $from_id; + $this->from_ip = $from_ip; + $this->to_id = $to_id; + $this->subject = $subject; + $this->message = $message; + $this->is_read = $read; + } + } } -class PrivMsg extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; +class PrivMsg extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - // shortcut to latest - if($config->get_int("pm_version") < 1) { - $database->create_table("private_message", " + // shortcut to latest + if ($config->get_int("pm_version") < 1) { + $database->create_table("private_message", " id SCORE_AIPK, from_id INTEGER NOT NULL, from_ip SCORE_INET NOT NULL, @@ -64,150 +76,155 @@ class PrivMsg extends Extension { FOREIGN KEY (from_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (to_id) REFERENCES users(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX private_message__to_id ON private_message(to_id)"); - $config->set_int("pm_version", 2); - log_info("pm", "extension installed"); - } + $database->execute("CREATE INDEX private_message__to_id ON private_message(to_id)"); + $config->set_int("pm_version", 2); + log_info("pm", "extension installed"); + } - if($config->get_int("pm_version") < 2) { - log_info("pm", "Adding foreign keys to private messages"); - $database->Execute("delete from private_message where to_id not in (select id from users);"); - $database->Execute("delete from private_message where from_id not in (select id from users);"); - $database->Execute("ALTER TABLE private_message + if ($config->get_int("pm_version") < 2) { + log_info("pm", "Adding foreign keys to private messages"); + $database->Execute("delete from private_message where to_id not in (select id from users);"); + $database->Execute("delete from private_message where from_id not in (select id from users);"); + $database->Execute("ALTER TABLE private_message ADD FOREIGN KEY (from_id) REFERENCES users(id) ON DELETE CASCADE, ADD FOREIGN KEY (to_id) REFERENCES users(id) ON DELETE CASCADE;"); - $config->set_int("pm_version", 2); - log_info("pm", "extension installed"); - } - } + $config->set_int("pm_version", 2); + log_info("pm", "extension installed"); + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if(!$user->is_anonymous()) { - $count = $this->count_pms($user); - $h_count = $count > 0 ? " ($count)" : ""; - $event->add_link("Private Messages$h_count", make_link("user#private-messages")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if (!$user->is_anonymous()) { + $count = $this->count_pms($user); + $h_count = $count > 0 ? " ($count)" : ""; + $event->add_link("Private Messages$h_count", make_link("user#private-messages")); + } + } - public function onUserPageBuilding(UserPageBuildingEvent $event) { - global $page, $user; - $duser = $event->display_user; - if(!$user->is_anonymous() && !$duser->is_anonymous()) { - if(($user->id == $duser->id) || $user->can("view_other_pms")) { - $this->theme->display_pms($page, $this->get_pms($duser)); - } - if($user->id != $duser->id) { - $this->theme->display_composer($page, $user, $duser); - } - } - } + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + global $page, $user; + $duser = $event->display_user; + if (!$user->is_anonymous() && !$duser->is_anonymous()) { + if (($user->id == $duser->id) || $user->can("view_other_pms")) { + $this->theme->display_pms($page, $this->get_pms($duser)); + } + if ($user->id != $duser->id) { + $this->theme->display_composer($page, $user, $duser); + } + } + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page, $user; - if($event->page_matches("pm")) { - if(!$user->is_anonymous()) { - switch($event->get_arg(0)) { - case "read": - $pm_id = int_escape($event->get_arg(1)); - $pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", array("id" => $pm_id)); - if(is_null($pm)) { - $this->theme->display_error(404, "No such PM", "There is no PM #$pm_id"); - } - else if(($pm["to_id"] == $user->id) || $user->can("view_other_pms")) { - $from_user = User::by_id(int_escape($pm["from_id"])); - if($pm["to_id"] == $user->id) { - $database->execute("UPDATE private_message SET is_read='Y' WHERE id = :id", array("id" => $pm_id)); - $database->cache->delete("pm-count-{$user->id}"); - } - $this->theme->display_message($page, $from_user, $user, new PM($pm)); - } - else { - // permission denied - } - break; - case "delete": - if($user->check_auth_token()) { - $pm_id = int_escape($_POST["pm_id"]); - $pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", array("id" => $pm_id)); - if(is_null($pm)) { - $this->theme->display_error(404, "No such PM", "There is no PM #$pm_id"); - } - else if(($pm["to_id"] == $user->id) || $user->can("view_other_pms")) { - $database->execute("DELETE FROM private_message WHERE id = :id", array("id" => $pm_id)); - $database->cache->delete("pm-count-{$user->id}"); - log_info("pm", "Deleted PM #$pm_id", "PM deleted"); - $page->set_mode("redirect"); - $page->set_redirect($_SERVER["HTTP_REFERER"]); - } - } - break; - case "send": - if($user->check_auth_token()) { - $to_id = int_escape($_POST["to_id"]); - $from_id = $user->id; - $subject = $_POST["subject"]; - $message = $_POST["message"]; - send_event(new SendPMEvent(new PM($from_id, $_SERVER["REMOTE_ADDR"], $to_id, $subject, $message))); - flash_message("PM sent"); - $page->set_mode("redirect"); - $page->set_redirect($_SERVER["HTTP_REFERER"]); - } - break; - default: - $this->theme->display_error(400, "Invalid action", "That's not something you can do with a PM"); - break; - } - } - } - } + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page, $user; + if ($event->page_matches("pm")) { + if (!$user->is_anonymous()) { + switch ($event->get_arg(0)) { + case "read": + $pm_id = int_escape($event->get_arg(1)); + $pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", ["id" => $pm_id]); + if (is_null($pm)) { + $this->theme->display_error(404, "No such PM", "There is no PM #$pm_id"); + } elseif (($pm["to_id"] == $user->id) || $user->can("view_other_pms")) { + $from_user = User::by_id(int_escape($pm["from_id"])); + if ($pm["to_id"] == $user->id) { + $database->execute("UPDATE private_message SET is_read='Y' WHERE id = :id", ["id" => $pm_id]); + $database->cache->delete("pm-count-{$user->id}"); + } + $this->theme->display_message($page, $from_user, $user, new PM($pm)); + } else { + // permission denied + } + break; + case "delete": + if ($user->check_auth_token()) { + $pm_id = int_escape($_POST["pm_id"]); + $pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", ["id" => $pm_id]); + if (is_null($pm)) { + $this->theme->display_error(404, "No such PM", "There is no PM #$pm_id"); + } elseif (($pm["to_id"] == $user->id) || $user->can("view_other_pms")) { + $database->execute("DELETE FROM private_message WHERE id = :id", ["id" => $pm_id]); + $database->cache->delete("pm-count-{$user->id}"); + log_info("pm", "Deleted PM #$pm_id", "PM deleted"); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER["HTTP_REFERER"]); + } + } + break; + case "send": + if ($user->check_auth_token()) { + $to_id = int_escape($_POST["to_id"]); + $from_id = $user->id; + $subject = $_POST["subject"]; + $message = $_POST["message"]; + send_event(new SendPMEvent(new PM($from_id, $_SERVER["REMOTE_ADDR"], $to_id, $subject, $message))); + flash_message("PM sent"); + $page->set_mode("redirect"); + $page->set_redirect($_SERVER["HTTP_REFERER"]); + } + break; + default: + $this->theme->display_error(400, "Invalid action", "That's not something you can do with a PM"); + break; + } + } + } + } - public function onSendPM(SendPMEvent $event) { - global $database; - $database->execute(" + public function onSendPM(SendPMEvent $event) + { + global $database; + $database->execute( + " INSERT INTO private_message( from_id, from_ip, to_id, sent_date, subject, message) VALUES(:fromid, :fromip, :toid, now(), :subject, :message)", - array("fromid" => $event->pm->from_id, "fromip" => $event->pm->from_ip, - "toid" => $event->pm->to_id, "subject" => $event->pm->subject, "message" => $event->pm->message) - ); - $database->cache->delete("pm-count-{$event->pm->to_id}"); - log_info("pm", "Sent PM to User #{$event->pm->to_id}"); - } + ["fromid" => $event->pm->from_id, "fromip" => $event->pm->from_ip, + "toid" => $event->pm->to_id, "subject" => $event->pm->subject, "message" => $event->pm->message] + ); + $database->cache->delete("pm-count-{$event->pm->to_id}"); + log_info("pm", "Sent PM to User #{$event->pm->to_id}"); + } - private function get_pms(User $user) { - global $database; + private function get_pms(User $user) + { + global $database; - $arr = $database->get_all(" + $arr = $database->get_all( + " SELECT private_message.*,user_from.name AS from_name FROM private_message JOIN users AS user_from ON user_from.id=from_id WHERE to_id = :toid ORDER BY sent_date DESC", - array("toid" => $user->id)); - $pms = array(); - foreach($arr as $pm) { - $pms[] = new PM($pm); - } - return $pms; - } + ["toid" => $user->id] + ); + $pms = []; + foreach ($arr as $pm) { + $pms[] = new PM($pm); + } + return $pms; + } - private function count_pms(User $user) { - global $database; + private function count_pms(User $user) + { + global $database; - $count = $database->cache->get("pm-count:{$user->id}"); - if(is_null($count) || $count === false) { - $count = $database->get_one(" + $count = $database->cache->get("pm-count:{$user->id}"); + if (is_null($count) || $count === false) { + $count = $database->get_one(" SELECT count(*) FROM private_message WHERE to_id = :to_id AND is_read = :is_read - ", array("to_id" => $user->id, "is_read" => "N")); - $database->cache->set("pm-count:{$user->id}", $count, 600); - } - return $count; - } + ", ["to_id" => $user->id, "is_read" => "N"]); + $database->cache->set("pm-count:{$user->id}", $count, 600); + } + return $count; + } } - diff --git a/ext/pm/test.php b/ext/pm/test.php index df065139..ea19e722 100644 --- a/ext/pm/test.php +++ b/ext/pm/test.php @@ -1,59 +1,61 @@ log_in_as_admin(); - $this->get_page("user/test"); +class PrivMsgTest extends ShimmiePHPUnitTestCase +{ + public function testPM() + { + $this->log_in_as_admin(); + $this->get_page("user/test"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field('subject', "message demo to test"); - $this->set_field('message', "message contents"); - $this->click("Send"); - $this->log_out(); + $this->set_field('subject', "message demo to test"); + $this->set_field('message', "message contents"); + $this->click("Send"); + $this->log_out(); - $this->log_in_as_user(); - $this->get_page("user"); - $this->assert_text("message demo to test"); - $this->click("message demo to test"); - $this->assert_text("message contents"); - $this->back(); - $this->click("Delete"); - $this->assert_no_text("message demo to test"); + $this->log_in_as_user(); + $this->get_page("user"); + $this->assert_text("message demo to test"); + $this->click("message demo to test"); + $this->assert_text("message contents"); + $this->back(); + $this->click("Delete"); + $this->assert_no_text("message demo to test"); - $this->get_page("pm/read/0"); - $this->assert_text("No such PM"); - // GET doesn't work due to auth token check - //$this->get_page("pm/delete/0"); - //$this->assert_text("No such PM"); - $this->get_page("pm/waffle/0"); - $this->assert_text("Invalid action"); + $this->get_page("pm/read/0"); + $this->assert_text("No such PM"); + // GET doesn't work due to auth token check + //$this->get_page("pm/delete/0"); + //$this->assert_text("No such PM"); + $this->get_page("pm/waffle/0"); + $this->assert_text("Invalid action"); - $this->log_out(); - } + $this->log_out(); + } - public function testAdminAccess() { - $this->log_in_as_admin(); - $this->get_page("user/test"); + public function testAdminAccess() + { + $this->log_in_as_admin(); + $this->get_page("user/test"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field('subject', "message demo to test"); - $this->set_field('message', "message contents"); - $this->click("Send"); + $this->set_field('subject', "message demo to test"); + $this->set_field('message', "message contents"); + $this->click("Send"); - $this->get_page("user/test"); - $this->assert_text("message demo to test"); - $this->click("message demo to test"); - $this->assert_text("message contents"); - $this->back(); - $this->click("Delete"); + $this->get_page("user/test"); + $this->assert_text("message demo to test"); + $this->click("message demo to test"); + $this->assert_text("message contents"); + $this->back(); + $this->click("Delete"); - # simpletest bug? - redirect(referrer) works in opera, not in - # webtestcase, so we end up at the wrong page... - $this->get_page("user/test"); - $this->assert_title("test's Page"); - $this->assert_no_text("message demo to test"); - $this->log_out(); - } + # simpletest bug? - redirect(referrer) works in opera, not in + # webtestcase, so we end up at the wrong page... + $this->get_page("user/test"); + $this->assert_title("test's Page"); + $this->assert_no_text("message demo to test"); + $this->log_out(); + } } - diff --git a/ext/pm/theme.php b/ext/pm/theme.php index 81242c9c..bb9a0f49 100644 --- a/ext/pm/theme.php +++ b/ext/pm/theme.php @@ -1,30 +1,34 @@ "; - foreach($pms as $pm) { - $h_subject = html_escape($pm->subject); - if(strlen(trim($h_subject)) == 0) $h_subject = "(No subject)"; - $from = User::by_id($pm->from_id); - $from_name = $from->name; - $h_from = html_escape($from_name); - $from_url = make_link("user/".url_escape($from_name)); - $pm_url = make_link("pm/read/".$pm->id); - $del_url = make_link("pm/delete"); - $h_date = html_escape($pm->sent_date); - $readYN = "Y"; - if(!$pm->is_read) { - $h_subject = "$h_subject"; - $readYN = "N"; - } - $hb = $from->can("hellbanned") ? "hb" : ""; - $html .= " + foreach ($pms as $pm) { + $h_subject = html_escape($pm->subject); + if (strlen(trim($h_subject)) == 0) { + $h_subject = "(No subject)"; + } + $from = User::by_id($pm->from_id); + $from_name = $from->name; + $h_from = html_escape($from_name); + $from_url = make_link("user/".url_escape($from_name)); + $pm_url = make_link("pm/read/".$pm->id); + $del_url = make_link("pm/delete"); + $h_date = html_escape($pm->sent_date); + $readYN = "Y"; + if (!$pm->is_read) { + $h_subject = "$h_subject"; + $readYN = "N"; + } + $hb = $from->can("hellbanned") ? "hb" : ""; + $html .= " @@ -34,21 +38,22 @@ class PrivMsgTheme extends Themelet { "; - } - $html .= " + } + $html .= "
    "; + $html .= "{$vote['username']}"; + $html .= ""; + $html .= $vote['score']; + $html .= "
    R?SubjectFromDateAction
    $readYN $h_subject $h_from$h_date
    "; - $page->add_block(new Block("Private Messages", $html, "main", 40, "private-messages")); - } + $page->add_block(new Block("Private Messages", $html, "main", 40, "private-messages")); + } - public function display_composer(Page $page, User $from, User $to, $subject="") { - global $user; - $post_url = make_link("pm/send"); - $h_subject = html_escape($subject); - $to_id = $to->id; - $auth = $user->get_auth_html(); - $html = <<id; + $auth = $user->get_auth_html(); + $html = << $auth @@ -59,15 +64,15 @@ $auth EOD; - $page->add_block(new Block("Write a PM", $html, "main", 50)); - } + $page->add_block(new Block("Write a PM", $html, "main", 50)); + } - public function display_message(Page $page, User $from, User $to, PM $pm) { - $this->display_composer($page, $to, $from, "Re: ".$pm->subject); - $page->set_title("Private Message"); - $page->set_heading(html_escape($pm->subject)); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Message from {$from->name}", format_text($pm->message), "main", 10)); - } + public function display_message(Page $page, User $from, User $to, PM $pm) + { + $this->display_composer($page, $to, $from, "Re: ".$pm->subject); + $page->set_title("Private Message"); + $page->set_heading(html_escape($pm->subject)); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Message from {$from->name}", format_text($pm->message), "main", 10)); + } } - diff --git a/ext/pm_triggers/main.php b/ext/pm_triggers/main.php index 7cb80013..40f6f87d 100644 --- a/ext/pm_triggers/main.php +++ b/ext/pm_triggers/main.php @@ -6,24 +6,26 @@ * Description: Send PMs in response to certain events (eg image deletion) */ -class PMTrigger extends Extension { - public function onImageDeletion(ImageDeletionEvent $event) { - $this->send( - $event->image->owner_id, - "[System] An image you uploaded has been deleted", - "Image le gone~ (#{$event->image->id}, {$event->image->get_tag_list()})" - ); - } +class PMTrigger extends Extension +{ + public function onImageDeletion(ImageDeletionEvent $event) + { + $this->send( + $event->image->owner_id, + "[System] An image you uploaded has been deleted", + "Image le gone~ (#{$event->image->id}, {$event->image->get_tag_list()})" + ); + } - private function send($to_id, $subject, $body) { - global $user; - send_event(new SendPMEvent(new PM( - $user->id, - $_SERVER["REMOTE_ADDR"], - $to_id, - $subject, - $body - ))); - } + private function send($to_id, $subject, $body) + { + global $user; + send_event(new SendPMEvent(new PM( + $user->id, + $_SERVER["REMOTE_ADDR"], + $to_id, + $subject, + $body + ))); + } } - diff --git a/ext/pools/main.php b/ext/pools/main.php index 5cc78db2..6fd35b9e 100644 --- a/ext/pools/main.php +++ b/ext/pools/main.php @@ -12,33 +12,36 @@ /** * This class is just a wrapper around SCoreException. */ -class PoolCreationException extends SCoreException { - /** @var string */ - public $error; +class PoolCreationException extends SCoreException +{ + /** @var string */ + public $error; - public function __construct(string $error) { - $this->error = $error; - } + public function __construct(string $error) + { + $this->error = $error; + } } -class Pools extends Extension { +class Pools extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - public function onInitExt(InitExtEvent $event) { - global $config, $database; + // Set the defaults for the pools extension + $config->set_default_int("poolsMaxImportResults", 1000); + $config->set_default_int("poolsImagesPerPage", 20); + $config->set_default_int("poolsListsPerPage", 20); + $config->set_default_int("poolsUpdatedPerPage", 20); + $config->set_default_bool("poolsInfoOnViewImage", false); + $config->set_default_bool("poolsAdderOnViewImage", false); + $config->set_default_bool("poolsShowNavLinks", false); + $config->set_default_bool("poolsAutoIncrementOrder", false); - // Set the defaults for the pools extension - $config->set_default_int("poolsMaxImportResults", 1000); - $config->set_default_int("poolsImagesPerPage", 20); - $config->set_default_int("poolsListsPerPage", 20); - $config->set_default_int("poolsUpdatedPerPage", 20); - $config->set_default_bool("poolsInfoOnViewImage", false); - $config->set_default_bool("poolsAdderOnViewImage", false); - $config->set_default_bool("poolsShowNavLinks", false); - $config->set_default_bool("poolsAutoIncrementOrder", false); - - // Create the database tables - if ($config->get_int("ext_pools_version") < 1){ - $database->create_table("pools", " + // Create the database tables + if ($config->get_int("ext_pools_version") < 1) { + $database->create_table("pools", " id SCORE_AIPK, user_id INTEGER NOT NULL, public SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, @@ -48,14 +51,14 @@ class Pools extends Extension { posts INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE "); - $database->create_table("pool_images", " + $database->create_table("pool_images", " pool_id INTEGER NOT NULL, image_id INTEGER NOT NULL, image_order INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (pool_id) REFERENCES pools(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (image_id) REFERENCES images(id) ON UPDATE CASCADE ON DELETE CASCADE "); - $database->create_table("pool_history", " + $database->create_table("pool_history", " id SCORE_AIPK, pool_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -66,323 +69,330 @@ class Pools extends Extension { FOREIGN KEY (pool_id) REFERENCES pools(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE "); - $config->set_int("ext_pools_version", 3); + $config->set_int("ext_pools_version", 3); - log_info("pools", "extension installed"); - } + log_info("pools", "extension installed"); + } - if ($config->get_int("ext_pools_version") < 2){ - $database->Execute("ALTER TABLE pools ADD UNIQUE INDEX (title);"); - $database->Execute("ALTER TABLE pools ADD lastupdated TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;"); + if ($config->get_int("ext_pools_version") < 2) { + $database->Execute("ALTER TABLE pools ADD UNIQUE INDEX (title);"); + $database->Execute("ALTER TABLE pools ADD lastupdated TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;"); - $config->set_int("ext_pools_version", 3); // skip 2 - } - } + $config->set_int("ext_pools_version", 3); // skip 2 + } + } - // Add a block to the Board Config / Setup - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Pools"); - $sb->add_int_option("poolsMaxImportResults", "Max results on import: "); - $sb->add_int_option("poolsImagesPerPage", "
    Images per page: "); - $sb->add_int_option("poolsListsPerPage", "
    Index list items per page: "); - $sb->add_int_option("poolsUpdatedPerPage", "
    Updated list items per page: "); - $sb->add_bool_option("poolsInfoOnViewImage", "
    Show pool info on image: "); - $sb->add_bool_option("poolsShowNavLinks", "
    Show 'Prev' & 'Next' links when viewing pool images: "); - $sb->add_bool_option("poolsAutoIncrementOrder", "
    Autoincrement order when post is added to pool:"); - //$sb->add_bool_option("poolsAdderOnViewImage", "
    Show pool adder on image: "); + // Add a block to the Board Config / Setup + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Pools"); + $sb->add_int_option("poolsMaxImportResults", "Max results on import: "); + $sb->add_int_option("poolsImagesPerPage", "
    Images per page: "); + $sb->add_int_option("poolsListsPerPage", "
    Index list items per page: "); + $sb->add_int_option("poolsUpdatedPerPage", "
    Updated list items per page: "); + $sb->add_bool_option("poolsInfoOnViewImage", "
    Show pool info on image: "); + $sb->add_bool_option("poolsShowNavLinks", "
    Show 'Prev' & 'Next' links when viewing pool images: "); + $sb->add_bool_option("poolsAutoIncrementOrder", "
    Autoincrement order when post is added to pool:"); + //$sb->add_bool_option("poolsAdderOnViewImage", "
    Show pool adder on image: "); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - - if ($event->page_matches("pool")) { - $pool_id = 0; - $pool = array(); + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + + if ($event->page_matches("pool")) { + $pool_id = 0; + $pool = []; - // Check if we have pool id, since this is most often the case. - if (isset($_POST["pool_id"])) { - $pool_id = int_escape($_POST["pool_id"]); - $pool = $this->get_single_pool($pool_id); - } - - // What action are we trying to perform? - switch($event->get_arg(0)) { - case "list": //index - $this->list_pools($page, int_escape($event->get_arg(1))); - break; + // Check if we have pool id, since this is most often the case. + if (isset($_POST["pool_id"])) { + $pool_id = int_escape($_POST["pool_id"]); + $pool = $this->get_single_pool($pool_id); + } + + // What action are we trying to perform? + switch ($event->get_arg(0)) { + case "list": //index + $this->list_pools($page, int_escape($event->get_arg(1))); + break; - case "new": // Show form for new pools - if(!$user->is_anonymous()){ - $this->theme->new_pool_composer($page); - } else { - $errMessage = "You must be registered and logged in to create a new pool."; - $this->theme->display_error(401, "Error", $errMessage); - } - break; + case "new": // Show form for new pools + if (!$user->is_anonymous()) { + $this->theme->new_pool_composer($page); + } else { + $errMessage = "You must be registered and logged in to create a new pool."; + $this->theme->display_error(401, "Error", $errMessage); + } + break; - case "create": // ADD _POST - try { - $newPoolID = $this->add_pool(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$newPoolID)); - } - catch(PoolCreationException $e) { - $this->theme->display_error(400, "Error", $e->error); - } - break; + case "create": // ADD _POST + try { + $newPoolID = $this->add_pool(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$newPoolID)); + } catch (PoolCreationException $e) { + $this->theme->display_error(400, "Error", $e->error); + } + break; - case "view": - $poolID = int_escape($event->get_arg(1)); - $this->get_posts($event, $poolID); - break; + case "view": + $poolID = int_escape($event->get_arg(1)); + $this->get_posts($event, $poolID); + break; - case "updated": - $this->get_history(int_escape($event->get_arg(1))); - break; + case "updated": + $this->get_history(int_escape($event->get_arg(1))); + break; - case "revert": - if(!$user->is_anonymous()) { - $historyID = int_escape($event->get_arg(1)); - $this->revert_history($historyID); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/updated")); - } - break; + case "revert": + if (!$user->is_anonymous()) { + $historyID = int_escape($event->get_arg(1)); + $this->revert_history($historyID); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/updated")); + } + break; - case "edit": // Edit the pool (remove images) - if ($this->have_permission($user, $pool)) { - $this->theme->edit_pool($page, $this->get_pool($pool_id), $this->edit_posts($pool_id)); - } else { - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } - break; + case "edit": // Edit the pool (remove images) + if ($this->have_permission($user, $pool)) { + $this->theme->edit_pool($page, $this->get_pool($pool_id), $this->edit_posts($pool_id)); + } else { + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } + break; - case "order": // Order the pool (view and change the order of images within the pool) - if (isset($_POST["order_view"])) { - if ($this->have_permission($user, $pool)) { - $this->theme->edit_order($page, $this->get_pool($pool_id), $this->edit_order($pool_id)); - } else { - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } - } - else { - if ($this->have_permission($user, $pool)) { - $this->order_posts(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } - } - break; + case "order": // Order the pool (view and change the order of images within the pool) + if (isset($_POST["order_view"])) { + if ($this->have_permission($user, $pool)) { + $this->theme->edit_order($page, $this->get_pool($pool_id), $this->edit_order($pool_id)); + } else { + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } + } else { + if ($this->have_permission($user, $pool)) { + $this->order_posts(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } + } + break; - case "import": - if ($this->have_permission($user, $pool)) { - $this->import_posts($pool_id); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } - break; + case "import": + if ($this->have_permission($user, $pool)) { + $this->import_posts($pool_id); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } + break; - case "add_posts": - if ($this->have_permission($user, $pool)) { - $this->add_posts(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } - break; + case "add_posts": + if ($this->have_permission($user, $pool)) { + $this->add_posts(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } + break; - case "remove_posts": - if ($this->have_permission($user, $pool)) { - $this->remove_posts(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } + case "remove_posts": + if ($this->have_permission($user, $pool)) { + $this->remove_posts(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } - break; + break; - case "edit_description": - if ($this->have_permission($user, $pool)) { - $this->edit_description(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/view/".$pool_id)); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } + case "edit_description": + if ($this->have_permission($user, $pool)) { + $this->edit_description(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/view/".$pool_id)); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } - break; + break; - case "nuke": - // Completely remove the given pool. - // -> Only admins and owners may do this - if($user->is_admin() || $user->id == $pool['user_id']) { - $this->nuke_pool($pool_id); - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/list")); - } else { - $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); - } - break; + case "nuke": + // Completely remove the given pool. + // -> Only admins and owners may do this + if ($user->is_admin() || $user->id == $pool['user_id']) { + $this->nuke_pool($pool_id); + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/list")); + } else { + $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); + } + break; - default: - $page->set_mode("redirect"); - $page->set_redirect(make_link("pool/list")); - break; - } - } - } + default: + $page->set_mode("redirect"); + $page->set_redirect(make_link("pool/list")); + break; + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - $event->add_link("Pools", make_link("pool/list")); - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + $event->add_link("Pools", make_link("pool/list")); + } - /** - * When displaying an image, optionally list all the pools that the - * image is currently a member of on a side panel, as well as a link - * to the Next image in the pool. - * - * @var DisplayingImageEvent $event - */ - public function onDisplayingImage(DisplayingImageEvent $event) { - global $config; + /** + * When displaying an image, optionally list all the pools that the + * image is currently a member of on a side panel, as well as a link + * to the Next image in the pool. + * + * @var DisplayingImageEvent $event + */ + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $config; - if($config->get_bool("poolsInfoOnViewImage")) { - $imageID = $event->image->id; - $poolsIDs = $this->get_pool_ids($imageID); + if ($config->get_bool("poolsInfoOnViewImage")) { + $imageID = $event->image->id; + $poolsIDs = $this->get_pool_ids($imageID); - $show_nav = $config->get_bool("poolsShowNavLinks", false); + $show_nav = $config->get_bool("poolsShowNavLinks", false); - $navInfo = array(); - foreach($poolsIDs as $poolID) { - $pool = $this->get_single_pool($poolID); + $navInfo = []; + foreach ($poolsIDs as $poolID) { + $pool = $this->get_single_pool($poolID); - $navInfo[$pool['id']] = array(); - $navInfo[$pool['id']]['info'] = $pool; + $navInfo[$pool['id']] = []; + $navInfo[$pool['id']]['info'] = $pool; - // Optionally show a link the Prev/Next image in the Pool. - if ($show_nav) { - $navInfo[$pool['id']]['nav'] = $this->get_nav_posts($pool, $imageID); - } - } - $this->theme->pool_info($navInfo); - } - } + // Optionally show a link the Prev/Next image in the Pool. + if ($show_nav) { + $navInfo[$pool['id']]['nav'] = $this->get_nav_posts($pool, $imageID); + } + } + $this->theme->pool_info($navInfo); + } + } - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - global $config, $database, $user; - if($config->get_bool("poolsAdderOnViewImage") && !$user->is_anonymous()) { - if($user->is_admin()) { - $pools = $database->get_all("SELECT * FROM pools"); - } - else { - $pools = $database->get_all("SELECT * FROM pools WHERE user_id=:id", array("id"=>$user->id)); - } - if(count($pools) > 0) { - $event->add_part($this->theme->get_adder_html($event->image, $pools)); - } - } - } + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + global $config, $database, $user; + if ($config->get_bool("poolsAdderOnViewImage") && !$user->is_anonymous()) { + if ($user->is_admin()) { + $pools = $database->get_all("SELECT * FROM pools"); + } else { + $pools = $database->get_all("SELECT * FROM pools WHERE user_id=:id", ["id"=>$user->id]); + } + if (count($pools) > 0) { + $event->add_part($this->theme->get_adder_html($event->image, $pools)); + } + } + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); - if(preg_match("/^pool[=|:]([0-9]+|any|none)$/i", $event->term, $matches)) { - $poolID = $matches[1]; + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; + if (preg_match("/^pool[=|:]([0-9]+|any|none)$/i", $event->term, $matches)) { + $poolID = $matches[1]; - if(preg_match("/^(any|none)$/", $poolID)){ - $not = ($poolID == "none" ? "NOT" : ""); - $event->add_querylet(new Querylet("images.id $not IN (SELECT DISTINCT image_id FROM pool_images)")); - }else{ - $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); - } - } - else if(preg_match("/^pool_by_name[=|:](.*)$/i", $event->term, $matches)) { - $poolTitle = str_replace("_", " ", $matches[1]); + if (preg_match("/^(any|none)$/", $poolID)) { + $not = ($poolID == "none" ? "NOT" : ""); + $event->add_querylet(new Querylet("images.id $not IN (SELECT DISTINCT image_id FROM pool_images)")); + } else { + $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); + } + } elseif (preg_match("/^pool_by_name[=|:](.*)$/i", $event->term, $matches)) { + $poolTitle = str_replace("_", " ", $matches[1]); - $pool = $this->get_single_pool_from_title($poolTitle); - $poolID = 0; - if ($pool){ $poolID = $pool['id']; } - $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); - } - } + $pool = $this->get_single_pool_from_title($poolTitle); + $poolID = 0; + if ($pool) { + $poolID = $pool['id']; + } + $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); + } + } - public function onTagTermParse(TagTermParseEvent $event) { - $matches = array(); + public function onTagTermParse(TagTermParseEvent $event) + { + $matches = []; - if(preg_match("/^pool[=|:]([^:]*|lastcreated):?([0-9]*)$/i", $event->term, $matches)) { - global $user; - $poolTag = (string) str_replace("_", " ", $matches[1]); + if (preg_match("/^pool[=|:]([^:]*|lastcreated):?([0-9]*)$/i", $event->term, $matches)) { + global $user; + $poolTag = (string) str_replace("_", " ", $matches[1]); - $pool = null; - if($poolTag == 'lastcreated'){ - $pool = $this->get_last_userpool($user->id); - } - elseif(ctype_digit($poolTag)){ //If only digits, assume PoolID - $pool = $this->get_single_pool($poolTag); - }else{ //assume PoolTitle - $pool = $this->get_single_pool_from_title($poolTag); - } + $pool = null; + if ($poolTag == 'lastcreated') { + $pool = $this->get_last_userpool($user->id); + } elseif (ctype_digit($poolTag)) { //If only digits, assume PoolID + $pool = $this->get_single_pool($poolTag); + } else { //assume PoolTitle + $pool = $this->get_single_pool_from_title($poolTag); + } - if($pool ? $this->have_permission($user, $pool) : FALSE){ - $image_order = ($matches[2] ?: 0); - $this->add_post($pool['id'], $event->id, true, $image_order); - } - } + if ($pool ? $this->have_permission($user, $pool) : false) { + $image_order = ($matches[2] ?: 0); + $this->add_post($pool['id'], $event->id, true, $image_order); + } + } - if(!empty($matches)) $event->metatag = true; - } + if (!empty($matches)) { + $event->metatag = true; + } + } - /* ------------------------------------------------- */ - /* -------------- Private Functions -------------- */ - /* ------------------------------------------------- */ + /* ------------------------------------------------- */ + /* -------------- Private Functions -------------- */ + /* ------------------------------------------------- */ - /** - * Check if the given user has permission to edit/change the pool. - * - * TODO: Should the user variable be global? - */ - private function have_permission(User $user, array $pool): bool { - // If the pool is public and user is logged OR if the user is admin OR if the pool is owned by the user. - if ( (($pool['public'] == "Y" || $pool['public'] == "y") && !$user->is_anonymous()) || $user->is_admin() || $user->id == $pool['user_id']) - { - return true; - } else { - return false; - } - } + /** + * Check if the given user has permission to edit/change the pool. + * + * TODO: Should the user variable be global? + */ + private function have_permission(User $user, array $pool): bool + { + // If the pool is public and user is logged OR if the user is admin OR if the pool is owned by the user. + if ((($pool['public'] == "Y" || $pool['public'] == "y") && !$user->is_anonymous()) || $user->is_admin() || $user->id == $pool['user_id']) { + return true; + } else { + return false; + } + } - /** - * HERE WE GET THE LIST OF POOLS. - */ - private function list_pools(Page $page, int $pageNumber) { - global $config, $database; + /** + * HERE WE GET THE LIST OF POOLS. + */ + private function list_pools(Page $page, int $pageNumber) + { + global $config, $database; - $pageNumber = clamp($pageNumber, 1, null) - 1; + $pageNumber = clamp($pageNumber, 1, null) - 1; - $poolsPerPage = $config->get_int("poolsListsPerPage"); + $poolsPerPage = $config->get_int("poolsListsPerPage"); - $order_by = ""; - $order = $page->get_cookie("ui-order-pool"); - if($order == "created" || is_null($order)){ - $order_by = "ORDER BY p.date DESC"; - }elseif($order == "updated"){ - $order_by = "ORDER BY p.lastupdated DESC"; - }elseif($order == "name"){ - $order_by = "ORDER BY p.title ASC"; - }elseif($order == "count"){ - $order_by = "ORDER BY p.posts DESC"; - } + $order_by = ""; + $order = $page->get_cookie("ui-order-pool"); + if ($order == "created" || is_null($order)) { + $order_by = "ORDER BY p.date DESC"; + } elseif ($order == "updated") { + $order_by = "ORDER BY p.lastupdated DESC"; + } elseif ($order == "name") { + $order_by = "ORDER BY p.title ASC"; + } elseif ($order == "count") { + $order_by = "ORDER BY p.posts DESC"; + } - $pools = $database->get_all(" + $pools = $database->get_all(" SELECT p.id, p.user_id, p.public, p.title, p.description, p.posts, u.name as user_name FROM pools AS p @@ -390,209 +400,230 @@ class Pools extends Extension { ON p.user_id = u.id $order_by LIMIT :l OFFSET :o - ", array("l"=>$poolsPerPage, "o"=>$pageNumber * $poolsPerPage)); + ", ["l"=>$poolsPerPage, "o"=>$pageNumber * $poolsPerPage]); - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pools") / $poolsPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pools") / $poolsPerPage); - $this->theme->list_pools($page, $pools, $pageNumber + 1, $totalPages); - } + $this->theme->list_pools($page, $pools, $pageNumber + 1, $totalPages); + } - /** - * HERE WE CREATE A NEW POOL - */ - private function add_pool(): int { - global $user, $database; + /** + * HERE WE CREATE A NEW POOL + */ + private function add_pool(): int + { + global $user, $database; - if($user->is_anonymous()) { - throw new PoolCreationException("You must be registered and logged in to add a image."); - } - if(empty($_POST["title"])) { - throw new PoolCreationException("Pool title is empty."); - } - if($this->get_single_pool_from_title($_POST["title"])) { - throw new PoolCreationException("A pool using this title already exists."); - } + if ($user->is_anonymous()) { + throw new PoolCreationException("You must be registered and logged in to add a image."); + } + if (empty($_POST["title"])) { + throw new PoolCreationException("Pool title is empty."); + } + if ($this->get_single_pool_from_title($_POST["title"])) { + throw new PoolCreationException("A pool using this title already exists."); + } - $public = $_POST["public"] === "Y" ? "Y" : "N"; - $database->execute(" + $public = $_POST["public"] === "Y" ? "Y" : "N"; + $database->execute( + " INSERT INTO pools (user_id, public, title, description, date) VALUES (:uid, :public, :title, :desc, now())", - array("uid"=>$user->id, "public"=>$public, "title"=>$_POST["title"], "desc"=>$_POST["description"])); + ["uid"=>$user->id, "public"=>$public, "title"=>$_POST["title"], "desc"=>$_POST["description"]] + ); - $poolID = $database->get_last_insert_id('pools_id_seq'); - log_info("pools", "Pool {$poolID} created by {$user->name}"); - return $poolID; - } + $poolID = $database->get_last_insert_id('pools_id_seq'); + log_info("pools", "Pool {$poolID} created by {$user->name}"); + return $poolID; + } - /** - * Retrieve information about pools given multiple pool IDs. - * - * TODO: What is the difference between this and get_single_pool() other than the db query? - */ - private function get_pool(int $poolID): array { - global $database; - return $database->get_all("SELECT * FROM pools WHERE id=:id", array("id"=>$poolID)); - } + /** + * Retrieve information about pools given multiple pool IDs. + * + * TODO: What is the difference between this and get_single_pool() other than the db query? + */ + private function get_pool(int $poolID): array + { + global $database; + return $database->get_all("SELECT * FROM pools WHERE id=:id", ["id"=>$poolID]); + } - /** - * Retrieve information about a pool given a pool ID. - */ - private function get_single_pool(int $poolID): array { - global $database; - return $database->get_row("SELECT * FROM pools WHERE id=:id", array("id"=>$poolID)); - } + /** + * Retrieve information about a pool given a pool ID. + */ + private function get_single_pool(int $poolID): array + { + global $database; + return $database->get_row("SELECT * FROM pools WHERE id=:id", ["id"=>$poolID]); + } - /** - * Retrieve information about a pool given a pool title. - */ - private function get_single_pool_from_title(string $poolTitle): array { - global $database; - return $database->get_row("SELECT * FROM pools WHERE title=:title", array("title"=>$poolTitle)); - } + /** + * Retrieve information about a pool given a pool title. + */ + private function get_single_pool_from_title(string $poolTitle): array + { + global $database; + return $database->get_row("SELECT * FROM pools WHERE title=:title", ["title"=>$poolTitle]); + } - /** - * Get all of the pool IDs that an image is in, given an image ID. - * #return int[] - */ - private function get_pool_ids(int $imageID): array { - global $database; - return $database->get_col("SELECT pool_id FROM pool_images WHERE image_id=:iid", array("iid"=>$imageID)); - } + /** + * Get all of the pool IDs that an image is in, given an image ID. + * #return int[] + */ + private function get_pool_ids(int $imageID): array + { + global $database; + return $database->get_col("SELECT pool_id FROM pool_images WHERE image_id=:iid", ["iid"=>$imageID]); + } - /** - * Retrieve information about the last pool the given userID created - */ - private function get_last_userpool(int $userID): array { - global $database; - return $database->get_row("SELECT * FROM pools WHERE user_id=:uid ORDER BY id DESC", array("uid"=>$userID)); - } + /** + * Retrieve information about the last pool the given userID created + */ + private function get_last_userpool(int $userID): array + { + global $database; + return $database->get_row("SELECT * FROM pools WHERE user_id=:uid ORDER BY id DESC", ["uid"=>$userID]); + } - /** - * HERE WE GET THE IMAGES FROM THE TAG ON IMPORT - */ - private function import_posts(int $pool_id) { - global $page, $config; + /** + * HERE WE GET THE IMAGES FROM THE TAG ON IMPORT + */ + private function import_posts(int $pool_id) + { + global $page, $config; - $poolsMaxResults = $config->get_int("poolsMaxImportResults", 1000); - - $images = $images = Image::find_images(0, $poolsMaxResults, Tag::explode($_POST["pool_tag"])); - $this->theme->pool_result($page, $images, $this->get_pool($pool_id)); - } + $poolsMaxResults = $config->get_int("poolsMaxImportResults", 1000); + + $images = $images = Image::find_images(0, $poolsMaxResults, Tag::explode($_POST["pool_tag"])); + $this->theme->pool_result($page, $images, $this->get_pool($pool_id)); + } - /** - * HERE WE ADD CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY - * - * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. - */ - private function add_posts(): int { - global $database; + /** + * HERE WE ADD CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY + * + * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. + */ + private function add_posts(): int + { + global $database; - $poolID = int_escape($_POST['pool_id']); - $images = ""; + $poolID = int_escape($_POST['pool_id']); + $images = ""; - foreach ($_POST['check'] as $imageID){ - if(!$this->check_post($poolID, $imageID)){ - $database->execute(" + foreach ($_POST['check'] as $imageID) { + if (!$this->check_post($poolID, $imageID)) { + $database->execute( + " INSERT INTO pool_images (pool_id, image_id) VALUES (:pid, :iid)", - array("pid"=>$poolID, "iid"=>$imageID)); + ["pid"=>$poolID, "iid"=>$imageID] + ); - $images .= " ".$imageID; - } - } + $images .= " ".$imageID; + } + } - if(!strlen($images) == 0) { - $count = int_escape($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID))); - $this->add_history($poolID, 1, $images, $count); - } + if (!strlen($images) == 0) { + $count = int_escape($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID])); + $this->add_history($poolID, 1, $images, $count); + } - $database->Execute(" + $database->Execute( + " UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", - array("pid"=>$poolID) - ); - return $poolID; - } + ["pid"=>$poolID] + ); + return $poolID; + } - /** - * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. - */ - private function order_posts(): int { - global $database; + /** + * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. + */ + private function order_posts(): int + { + global $database; - $poolID = int_escape($_POST['pool_id']); + $poolID = int_escape($_POST['pool_id']); - foreach($_POST['imgs'] as $data) { - list($imageORDER, $imageID) = $data; - $database->Execute(" + foreach ($_POST['imgs'] as $data) { + list($imageORDER, $imageID) = $data; + $database->Execute( + " UPDATE pool_images SET image_order = :ord WHERE pool_id = :pid AND image_id = :iid", - array("ord"=>$imageORDER, "pid"=>$poolID, "iid"=>$imageID) - ); - } + ["ord"=>$imageORDER, "pid"=>$poolID, "iid"=>$imageID] + ); + } - return $poolID; - } + return $poolID; + } - /** - * HERE WE REMOVE CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY - * - * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. - */ - private function remove_posts(): int { - global $database; + /** + * HERE WE REMOVE CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY + * + * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. + */ + private function remove_posts(): int + { + global $database; - $poolID = int_escape($_POST['pool_id']); - $images = ""; + $poolID = int_escape($_POST['pool_id']); + $images = ""; - foreach($_POST['check'] as $imageID) { - $database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", array("pid"=>$poolID, "iid"=>$imageID)); - $images .= " ".$imageID; - } + foreach ($_POST['check'] as $imageID) { + $database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", ["pid"=>$poolID, "iid"=>$imageID]); + $images .= " ".$imageID; + } - $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)); - $this->add_history($poolID, 0, $images, $count); - return $poolID; - } + $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID]); + $this->add_history($poolID, 0, $images, $count); + return $poolID; + } - /** - * Allows editing of pool description. - */ - private function edit_description(): int { - global $database; + /** + * Allows editing of pool description. + */ + private function edit_description(): int + { + global $database; - $poolID = int_escape($_POST['pool_id']); - $database->execute("UPDATE pools SET description=:dsc WHERE id=:pid", array("dsc"=>$_POST['description'], "pid"=>$poolID)); + $poolID = int_escape($_POST['pool_id']); + $database->execute("UPDATE pools SET description=:dsc WHERE id=:pid", ["dsc"=>$_POST['description'], "pid"=>$poolID]); - return $poolID; - } + return $poolID; + } - /** - * This function checks if a given image is contained within a given pool. - * Used by add_posts() - */ - private function check_post(int $poolID, int $imageID): bool { - global $database; - $result = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid AND image_id=:iid", array("pid"=>$poolID, "iid"=>$imageID)); - return ($result != 0); - } + /** + * This function checks if a given image is contained within a given pool. + * Used by add_posts() + */ + private function check_post(int $poolID, int $imageID): bool + { + global $database; + $result = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid AND image_id=:iid", ["pid"=>$poolID, "iid"=>$imageID]); + return ($result != 0); + } - /** - * Gets the previous and next successive images from a pool, given a pool ID and an image ID. - * - * #return int[] Array returning two elements (prev, next) in 1 dimension. Each returns ImageID or NULL if none. - */ - private function get_nav_posts(array $pool, int $imageID): array { - global $database; + /** + * Gets the previous and next successive images from a pool, given a pool ID and an image ID. + * + * #return int[] Array returning two elements (prev, next) in 1 dimension. Each returns ImageID or NULL if none. + */ + private function get_nav_posts(array $pool, int $imageID): array + { + global $database; - if (empty($pool) || empty($imageID)) - return null; - - $result = $database->get_row(" + if (empty($pool) || empty($imageID)) { + return null; + } + + $result = $database->get_row( + " SELECT ( SELECT image_id FROM pool_images @@ -621,172 +652,188 @@ class Pools extends Extension { ) AS next LIMIT 1", - array("pid"=>$pool['id'], "iid"=>$imageID) ); + ["pid"=>$pool['id'], "iid"=>$imageID] + ); - if (empty($result)) { - // assume that we are at the end of the pool - return null; - } else { - return $result; - } - } + if (empty($result)) { + // assume that we are at the end of the pool + return null; + } else { + return $result; + } + } - /** - * Retrieve all the images in a pool, given a pool ID. - */ - private function get_posts(PageRequestEvent $event, int $poolID) { - global $config, $user, $database; + /** + * Retrieve all the images in a pool, given a pool ID. + */ + private function get_posts(PageRequestEvent $event, int $poolID) + { + global $config, $user, $database; - $pageNumber = int_escape($event->get_arg(2)); - if(is_null($pageNumber) || !is_numeric($pageNumber)) - $pageNumber = 0; - else if ($pageNumber <= 0) - $pageNumber = 0; - else - $pageNumber--; + $pageNumber = int_escape($event->get_arg(2)); + if (is_null($pageNumber) || !is_numeric($pageNumber)) { + $pageNumber = 0; + } elseif ($pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $poolID = int_escape($poolID); - $pool = $this->get_pool($poolID); + $poolID = int_escape($poolID); + $pool = $this->get_pool($poolID); - $imagesPerPage = $config->get_int("poolsImagesPerPage"); + $imagesPerPage = $config->get_int("poolsImagesPerPage"); - // WE CHECK IF THE EXTENSION RATING IS INSTALLED, WHICH VERSION AND IF IT - // WORKS TO SHOW/HIDE SAFE, QUESTIONABLE, EXPLICIT AND UNRATED IMAGES FROM USER - if(ext_is_live("Ratings")) { - $rating = Ratings::privs_to_sql(Ratings::get_user_privs($user)); - } - if (isset($rating) && !empty($rating)) { - - $result = $database->get_all(" + // WE CHECK IF THE EXTENSION RATING IS INSTALLED, WHICH VERSION AND IF IT + // WORKS TO SHOW/HIDE SAFE, QUESTIONABLE, EXPLICIT AND UNRATED IMAGES FROM USER + if (ext_is_live("Ratings")) { + $rating = Ratings::privs_to_sql(Ratings::get_user_privs($user)); + } + if (isset($rating) && !empty($rating)) { + $result = $database->get_all( + " SELECT p.image_id FROM pool_images AS p INNER JOIN images AS i ON i.id = p.image_id WHERE p.pool_id = :pid AND i.rating IN ($rating) ORDER BY p.image_order ASC LIMIT :l OFFSET :o", - array("pid"=>$poolID, "l"=>$imagesPerPage, "o"=>$pageNumber * $imagesPerPage)); + ["pid"=>$poolID, "l"=>$imagesPerPage, "o"=>$pageNumber * $imagesPerPage] + ); - $totalPages = ceil($database->get_one(" + $totalPages = ceil($database->get_one( + " SELECT COUNT(*) FROM pool_images AS p INNER JOIN images AS i ON i.id = p.image_id WHERE pool_id=:pid AND i.rating IN ($rating)", - array("pid"=>$poolID)) / $imagesPerPage); - } else { - - $result = $database->get_all(" + ["pid"=>$poolID] + ) / $imagesPerPage); + } else { + $result = $database->get_all( + " SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC LIMIT :l OFFSET :o", - array("pid"=>$poolID, "l"=>$imagesPerPage, "o"=>$pageNumber * $imagesPerPage)); - - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)) / $imagesPerPage); - } + ["pid"=>$poolID, "l"=>$imagesPerPage, "o"=>$pageNumber * $imagesPerPage] + ); + + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID]) / $imagesPerPage); + } - $images = array(); - foreach($result as $singleResult) { - $images[] = Image::by_id($singleResult["image_id"]); - } + $images = []; + foreach ($result as $singleResult) { + $images[] = Image::by_id($singleResult["image_id"]); + } - $this->theme->view_pool($pool, $images, $pageNumber + 1, $totalPages); - } + $this->theme->view_pool($pool, $images, $pageNumber + 1, $totalPages); + } - /** - * This function gets the current order of images from a given pool. - * #return Image[] Array of image objects. - */ - private function edit_posts(int $poolID): array { - global $database; + /** + * This function gets the current order of images from a given pool. + * #return Image[] Array of image objects. + */ + private function edit_posts(int $poolID): array + { + global $database; - $result = $database->Execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", array("pid"=>$poolID)); - $images = array(); - - while($row = $result->fetch()) { - $image = Image::by_id($row["image_id"]); - $images[] = array($image); - } - - return $images; - } + $result = $database->Execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", ["pid"=>$poolID]); + $images = []; + + while ($row = $result->fetch()) { + $image = Image::by_id($row["image_id"]); + $images[] = [$image]; + } + + return $images; + } - /** - * WE GET THE ORDER OF THE IMAGES BUT HERE WE SEND KEYS ADDED IN ARRAY TO GET THE ORDER IN THE INPUT VALUE. - * - * #return Image[] - */ - private function edit_order(int $poolID): array { - global $database; + /** + * WE GET THE ORDER OF THE IMAGES BUT HERE WE SEND KEYS ADDED IN ARRAY TO GET THE ORDER IN THE INPUT VALUE. + * + * #return Image[] + */ + private function edit_order(int $poolID): array + { + global $database; - $result = $database->Execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", array("pid"=>$poolID)); - $images = array(); - - while($row = $result->fetch()) - { - $image = $database->get_row(" + $result = $database->Execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", ["pid"=>$poolID]); + $images = []; + + while ($row = $result->fetch()) { + $image = $database->get_row( + " SELECT * FROM images AS i INNER JOIN pool_images AS p ON i.id = p.image_id WHERE pool_id=:pid AND i.id=:iid", - array("pid"=>$poolID, "iid"=>$row['image_id'])); - $image = ($image ? new Image($image) : null); - $images[] = array($image); - } - - return $images; - } + ["pid"=>$poolID, "iid"=>$row['image_id']] + ); + $image = ($image ? new Image($image) : null); + $images[] = [$image]; + } + + return $images; + } - /** - * HERE WE NUKE ENTIRE POOL. WE REMOVE POOLS AND POSTS FROM REMOVED POOL AND HISTORIES ENTRIES FROM REMOVED POOL. - */ - private function nuke_pool(int $poolID) { - global $user, $database; + /** + * HERE WE NUKE ENTIRE POOL. WE REMOVE POOLS AND POSTS FROM REMOVED POOL AND HISTORIES ENTRIES FROM REMOVED POOL. + */ + private function nuke_pool(int $poolID) + { + global $user, $database; - $p_id = $database->get_one("SELECT user_id FROM pools WHERE id = :pid", array("pid"=>$poolID)); - if($user->is_admin()) { - $database->execute("DELETE FROM pool_history WHERE pool_id = :pid", array("pid"=>$poolID)); - $database->execute("DELETE FROM pool_images WHERE pool_id = :pid", array("pid"=>$poolID)); - $database->execute("DELETE FROM pools WHERE id = :pid", array("pid"=>$poolID)); - } elseif($user->id == $p_id) { - $database->execute("DELETE FROM pool_history WHERE pool_id = :pid", array("pid"=>$poolID)); - $database->execute("DELETE FROM pool_images WHERE pool_id = :pid", array("pid"=>$poolID)); - $database->execute("DELETE FROM pools WHERE id = :pid AND user_id = :uid", array("pid"=>$poolID, "uid"=>$user->id)); - } - } + $p_id = $database->get_one("SELECT user_id FROM pools WHERE id = :pid", ["pid"=>$poolID]); + if ($user->is_admin()) { + $database->execute("DELETE FROM pool_history WHERE pool_id = :pid", ["pid"=>$poolID]); + $database->execute("DELETE FROM pool_images WHERE pool_id = :pid", ["pid"=>$poolID]); + $database->execute("DELETE FROM pools WHERE id = :pid", ["pid"=>$poolID]); + } elseif ($user->id == $p_id) { + $database->execute("DELETE FROM pool_history WHERE pool_id = :pid", ["pid"=>$poolID]); + $database->execute("DELETE FROM pool_images WHERE pool_id = :pid", ["pid"=>$poolID]); + $database->execute("DELETE FROM pools WHERE id = :pid AND user_id = :uid", ["pid"=>$poolID, "uid"=>$user->id]); + } + } - /** - * HERE WE ADD A HISTORY ENTRY. - * - * $action Action=1 (one) MEANS ADDED, Action=0 (zero) MEANS REMOVED - */ - private function add_history(int $poolID, int $action, string $images, int $count) { - global $user, $database; + /** + * HERE WE ADD A HISTORY ENTRY. + * + * $action Action=1 (one) MEANS ADDED, Action=0 (zero) MEANS REMOVED + */ + private function add_history(int $poolID, int $action, string $images, int $count) + { + global $user, $database; - $database->execute(" + $database->execute( + " INSERT INTO pool_history (pool_id, user_id, action, images, count, date) VALUES (:pid, :uid, :act, :img, :count, now())", - array("pid"=>$poolID, "uid"=>$user->id, "act"=>$action, "img"=>$images, "count"=>$count)); - } + ["pid"=>$poolID, "uid"=>$user->id, "act"=>$action, "img"=>$images, "count"=>$count] + ); + } - /** - * HERE WE GET THE HISTORY LIST. - */ - private function get_history(int $pageNumber) { - global $config, $database; + /** + * HERE WE GET THE HISTORY LIST. + */ + private function get_history(int $pageNumber) + { + global $config, $database; - if(is_null($pageNumber) || !is_numeric($pageNumber)) - $pageNumber = 0; - else if ($pageNumber <= 0) - $pageNumber = 0; - else - $pageNumber--; + if (is_null($pageNumber) || !is_numeric($pageNumber)) { + $pageNumber = 0; + } elseif ($pageNumber <= 0) { + $pageNumber = 0; + } else { + $pageNumber--; + } - $historiesPerPage = $config->get_int("poolsUpdatedPerPage"); + $historiesPerPage = $config->get_int("poolsUpdatedPerPage"); - $history = $database->get_all(" + $history = $database->get_all(" SELECT h.id, h.pool_id, h.user_id, h.action, h.images, h.count, h.date, u.name as user_name, p.title as title FROM pool_history AS h @@ -796,102 +843,106 @@ class Pools extends Extension { ON h.user_id = u.id ORDER BY h.date DESC LIMIT :l OFFSET :o - ", array("l"=>$historiesPerPage, "o"=>$pageNumber * $historiesPerPage)); + ", ["l"=>$historiesPerPage, "o"=>$pageNumber * $historiesPerPage]); - $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pool_history") / $historiesPerPage); + $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pool_history") / $historiesPerPage); - $this->theme->show_history($history, $pageNumber + 1, $totalPages); - } + $this->theme->show_history($history, $pageNumber + 1, $totalPages); + } - /** - * HERE GO BACK IN HISTORY AND ADD OR REMOVE POSTS TO POOL. - */ - private function revert_history(int $historyID) { - global $database; - $status = $database->get_all("SELECT * FROM pool_history WHERE id=:hid", array("hid"=>$historyID)); + /** + * HERE GO BACK IN HISTORY AND ADD OR REMOVE POSTS TO POOL. + */ + private function revert_history(int $historyID) + { + global $database; + $status = $database->get_all("SELECT * FROM pool_history WHERE id=:hid", ["hid"=>$historyID]); - foreach($status as $entry) { - $images = trim($entry['images']); - $images = explode(" ", $images); - $poolID = $entry['pool_id']; - $imageArray = ""; - $newAction = -1; + foreach ($status as $entry) { + $images = trim($entry['images']); + $images = explode(" ", $images); + $poolID = $entry['pool_id']; + $imageArray = ""; + $newAction = -1; - if($entry['action'] == 0) { - // READ ENTRIES - foreach($images as $image) { - $imageID = $image; - $this->add_post($poolID, $imageID); + if ($entry['action'] == 0) { + // READ ENTRIES + foreach ($images as $image) { + $imageID = $image; + $this->add_post($poolID, $imageID); - $imageArray .= " ".$imageID; - $newAction = 1; - } - } - else if($entry['action'] == 1) { - // DELETE ENTRIES - foreach($images as $image) { - $imageID = $image; - $this->delete_post($poolID, $imageID); + $imageArray .= " ".$imageID; + $newAction = 1; + } + } elseif ($entry['action'] == 1) { + // DELETE ENTRIES + foreach ($images as $image) { + $imageID = $image; + $this->delete_post($poolID, $imageID); - $imageArray .= " ".$imageID; - $newAction = 0; - } - } else { - // FIXME: should this throw an exception instead? - log_error("pools", "Invalid history action."); - continue; // go on to the next one. - } + $imageArray .= " ".$imageID; + $newAction = 0; + } + } else { + // FIXME: should this throw an exception instead? + log_error("pools", "Invalid history action."); + continue; // go on to the next one. + } - $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)); - $this->add_history($poolID, $newAction, $imageArray, $count); - } - } + $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID]); + $this->add_history($poolID, $newAction, $imageArray, $count); + } + } - /** - * HERE WE ADD A SIMPLE POST FROM POOL. - * USED WITH FOREACH IN revert_history() & onTagTermParse(). - */ - private function add_post(int $poolID, int $imageID, bool $history=false, int $imageOrder=0) { - global $database, $config; + /** + * HERE WE ADD A SIMPLE POST FROM POOL. + * USED WITH FOREACH IN revert_history() & onTagTermParse(). + */ + private function add_post(int $poolID, int $imageID, bool $history=false, int $imageOrder=0) + { + global $database, $config; - if(!$this->check_post($poolID, $imageID)) { - if($config->get_bool("poolsAutoIncrementOrder") && $imageOrder === 0){ - $imageOrder = $database->get_one(" + if (!$this->check_post($poolID, $imageID)) { + if ($config->get_bool("poolsAutoIncrementOrder") && $imageOrder === 0) { + $imageOrder = $database->get_one( + " SELECT CASE WHEN image_order IS NOT NULL THEN MAX(image_order) + 1 ELSE 0 END FROM pool_images WHERE pool_id = :pid", - array("pid"=>$poolID)); - } + ["pid"=>$poolID] + ); + } - $database->execute(" + $database->execute( + " INSERT INTO pool_images (pool_id, image_id, image_order) VALUES (:pid, :iid, :ord)", - array("pid"=>$poolID, "iid"=>$imageID, "ord"=>$imageOrder)); - } + ["pid"=>$poolID, "iid"=>$imageID, "ord"=>$imageOrder] + ); + } - $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); + $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", ["pid"=>$poolID]); - if($history){ - $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)); - $this->add_history($poolID, 1, $imageID, $count); - } - } + if ($history) { + $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID]); + $this->add_history($poolID, 1, $imageID, $count); + } + } - /** - * HERE WE REMOVE A SIMPLE POST FROM POOL. - * USED WITH FOREACH IN revert_history() & onTagTermParse(). - */ - private function delete_post(int $poolID, int $imageID, bool $history=false) { - global $database; + /** + * HERE WE REMOVE A SIMPLE POST FROM POOL. + * USED WITH FOREACH IN revert_history() & onTagTermParse(). + */ + private function delete_post(int $poolID, int $imageID, bool $history=false) + { + global $database; - $database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", array("pid"=>$poolID, "iid"=>$imageID)); - $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); - - if($history){ - $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)); - $this->add_history($poolID, 0, $imageID, $count); - } - } + $database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", ["pid"=>$poolID, "iid"=>$imageID]); + $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", ["pid"=>$poolID]); + if ($history) { + $count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", ["pid"=>$poolID]); + $this->add_history($poolID, 0, $imageID, $count); + } + } } - diff --git a/ext/pools/test.php b/ext/pools/test.php index 0a3cc265..5f4fadd9 100644 --- a/ext/pools/test.php +++ b/ext/pools/test.php @@ -1,42 +1,43 @@ get_page('pool/list'); - $this->assert_title("Pools"); +class PoolsTest extends ShimmiePHPUnitTestCase +{ + public function testPools() + { + $this->get_page('pool/list'); + $this->assert_title("Pools"); - $this->get_page('pool/new'); - $this->assert_title("Error"); + $this->get_page('pool/new'); + $this->assert_title("Error"); - $this->log_in_as_user(); - $this->get_page('pool/list'); + $this->log_in_as_user(); + $this->get_page('pool/list'); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->click("Create Pool"); - $this->assert_title("Create Pool"); - $this->click("Create"); - $this->assert_title("Error"); + $this->click("Create Pool"); + $this->assert_title("Create Pool"); + $this->click("Create"); + $this->assert_title("Error"); - $this->get_page('pool/new'); - $this->assert_title("Create Pool"); - $this->set_field("title", "Test Pool Title"); - $this->set_field("description", "Test pool description"); - $this->click("Create"); - $this->assert_title("Pool: Test Pool Title"); + $this->get_page('pool/new'); + $this->assert_title("Create Pool"); + $this->set_field("title", "Test Pool Title"); + $this->set_field("description", "Test pool description"); + $this->click("Create"); + $this->assert_title("Pool: Test Pool Title"); - $this->log_out(); + $this->log_out(); - $this->log_in_as_admin(); + $this->log_in_as_admin(); - $this->get_page('pool/list'); - $this->click("Test Pool Title"); - $this->assert_title("Pool: Test Pool Title"); - $this->click("Delete Pool"); - $this->assert_title("Pools"); - $this->assert_no_text("Test Pool Title"); + $this->get_page('pool/list'); + $this->click("Test Pool Title"); + $this->assert_title("Pool: Test Pool Title"); + $this->click("Delete Pool"); + $this->assert_title("Pools"); + $this->assert_no_text("Test Pool Title"); - $this->log_out(); - } + $this->log_out(); + } } - diff --git a/ext/pools/theme.php b/ext/pools/theme.php index 38bd6b50..2dd12045 100644 --- a/ext/pools/theme.php +++ b/ext/pools/theme.php @@ -1,43 +1,46 @@ $pool){ - $linksPools[] = "".html_escape($pool['info']['title']).""; + $linksPools = []; + foreach ($navIDs as $poolID => $pool) { + $linksPools[] = "".html_escape($pool['info']['title']).""; - if (array_key_exists('nav', $pool)){ - $navlinks = ""; - if (!empty($pool['nav']['prev'])) { - $navlinks .= 'Prev'; - } - if (!empty($pool['nav']['next'])) { - $navlinks .= 'Next'; - } - if(!empty($navlinks)){ - $navlinks .= "
    "; - $linksPools[] = $navlinks; - } - } - } + if (array_key_exists('nav', $pool)) { + $navlinks = ""; + if (!empty($pool['nav']['prev'])) { + $navlinks .= 'Prev'; + } + if (!empty($pool['nav']['next'])) { + $navlinks .= 'Next'; + } + if (!empty($navlinks)) { + $navlinks .= "
    "; + $linksPools[] = $navlinks; + } + } + } - if(count($linksPools) > 0) { - $page->add_block(new Block("Pools", implode("
    ", $linksPools), "left")); - } - } + if (count($linksPools) > 0) { + $page->add_block(new Block("Pools", implode("
    ", $linksPools), "left")); + } + } - public function get_adder_html(Image $image, array $pools): string { - $h = ""; - foreach($pools as $pool) { - $h .= ""; - } - $editor = "\n".make_form(make_link("pool/add_post"))." + public function get_adder_html(Image $image, array $pools): string + { + $h = ""; + foreach ($pools as $pool) { + $h .= ""; + } + $editor = "\n".make_form(make_link("pool/add_post"))." @@ -45,14 +48,15 @@ class PoolsTheme extends Themelet { "; - return $editor; - } + return $editor; + } - /** - * HERE WE SHOWS THE LIST OF POOLS. - */ - public function list_pools(Page $page, array $pools, int $pageNumber, int $totalPages) { - $html = ' + /** + * HERE WE SHOWS THE LIST OF POOLS. + */ + public function list_pools(Page $page, array $pools, int $pageNumber, int $totalPages) + { + $html = ' @@ -61,46 +65,47 @@ class PoolsTheme extends Themelet { '; - // Build up the list of pools. - foreach($pools as $pool) { - $pool_link = ''.html_escape($pool['title']).""; - $user_link = ''.html_escape($pool['user_name']).""; - $public = ($pool['public'] == "Y" ? "Yes" : "No"); + // Build up the list of pools. + foreach ($pools as $pool) { + $pool_link = ''.html_escape($pool['title']).""; + $user_link = ''.html_escape($pool['user_name']).""; + $public = ($pool['public'] == "Y" ? "Yes" : "No"); - $html .= "". - "". - "". - "". - "". - ""; - } + $html .= "". + "". + "". + "". + "". + ""; + } - $html .= "
    NamePublic
    ".$pool_link."".$user_link."".$pool['posts']."".$public."
    ".$pool_link."".$user_link."".$pool['posts']."".$public."
    "; + $html .= ""; - $order_html = ''; + $order_html = ''; - $this->display_top(null, "Pools"); - $page->add_block(new Block("Order By", $order_html, "left", 15)); + $this->display_top(null, "Pools"); + $page->add_block(new Block("Order By", $order_html, "left", 15)); - $page->add_block(new Block("Pools", $html, "main", 10)); + $page->add_block(new Block("Pools", $html, "main", 10)); - $this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); - } + $this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); + } - /* - * HERE WE DISPLAY THE NEW POOL COMPOSER - */ - public function new_pool_composer(Page $page) { - $create_html = " + /* + * HERE WE DISPLAY THE NEW POOL COMPOSER + */ + public function new_pool_composer(Page $page) + { + $create_html = " ".make_form(make_link("pool/create"))." @@ -111,85 +116,88 @@ class PoolsTheme extends Themelet { "; - $this->display_top(null, "Create Pool"); - $page->add_block(new Block("Create Pool", $create_html, "main", 20)); - } + $this->display_top(null, "Create Pool"); + $page->add_block(new Block("Create Pool", $create_html, "main", 20)); + } - private function display_top(array $pools=null, string $heading, bool $check_all=false) { - global $page, $user; + private function display_top(array $pools=null, string $heading, bool $check_all=false) + { + global $page, $user; - $page->set_title($heading); - $page->set_heading($heading); + $page->set_title($heading); + $page->set_heading($heading); - $poolnav_html = ' + $poolnav_html = ' Pool Index
    Create Pool
    Pool Changes '; - $page->add_block(new NavBlock()); - $page->add_block(new Block("Pool Navigation", $poolnav_html, "left", 10)); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Pool Navigation", $poolnav_html, "left", 10)); - if(!is_null($pools) && count($pools) == 1) { - $pool = $pools[0]; - if($pool['public'] == "Y" || $user->is_admin()) {// IF THE POOL IS PUBLIC OR IS ADMIN SHOW EDIT PANEL - if(!$user->is_anonymous()) {// IF THE USER IS REGISTERED AND LOGGED IN SHOW EDIT PANEL - $this->sidebar_options($page, $pool, $check_all); - } - } + if (!is_null($pools) && count($pools) == 1) { + $pool = $pools[0]; + if ($pool['public'] == "Y" || $user->is_admin()) {// IF THE POOL IS PUBLIC OR IS ADMIN SHOW EDIT PANEL + if (!$user->is_anonymous()) {// IF THE USER IS REGISTERED AND LOGGED IN SHOW EDIT PANEL + $this->sidebar_options($page, $pool, $check_all); + } + } - $tfe = new TextFormattingEvent($pool['description']); - send_event($tfe); - $page->add_block(new Block(html_escape($pool['title']), $tfe->formatted, "main", 10)); - } - } + $tfe = new TextFormattingEvent($pool['description']); + send_event($tfe); + $page->add_block(new Block(html_escape($pool['title']), $tfe->formatted, "main", 10)); + } + } - /** - * HERE WE DISPLAY THE POOL WITH TITLE DESCRIPTION AND IMAGES WITH PAGINATION. - */ - public function view_pool(array $pools, array $images, int $pageNumber, int $totalPages) { - global $page; + /** + * HERE WE DISPLAY THE POOL WITH TITLE DESCRIPTION AND IMAGES WITH PAGINATION. + */ + public function view_pool(array $pools, array $images, int $pageNumber, int $totalPages) + { + global $page; - $this->display_top($pools, "Pool: ".html_escape($pools[0]['title'])); + $this->display_top($pools, "Pool: ".html_escape($pools[0]['title'])); - $pool_images = ''; - foreach($images as $image) { - $thumb_html = $this->build_thumb_html($image); - $pool_images .= "\n".$thumb_html."\n"; - } + $pool_images = ''; + foreach ($images as $image) { + $thumb_html = $this->build_thumb_html($image); + $pool_images .= "\n".$thumb_html."\n"; + } - $page->add_block(new Block("Viewing Posts", $pool_images, "main", 30)); - $this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); - } + $page->add_block(new Block("Viewing Posts", $pool_images, "main", 30)); + $this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); + } - /** - * HERE WE DISPLAY THE POOL OPTIONS ON SIDEBAR BUT WE HIDE REMOVE OPTION IF THE USER IS NOT THE OWNER OR ADMIN. - */ - public function sidebar_options(Page $page, array $pool, bool $check_all) { - global $user; + /** + * HERE WE DISPLAY THE POOL OPTIONS ON SIDEBAR BUT WE HIDE REMOVE OPTION IF THE USER IS NOT THE OWNER OR ADMIN. + */ + public function sidebar_options(Page $page, array $pool, bool $check_all) + { + global $user; - $editor = "\n".make_form( make_link('pool/import') ).' + $editor = "\n".make_form(make_link('pool/import')).' - '.make_form( make_link('pool/edit') ).' + '.make_form(make_link('pool/edit')).' - '.make_form( make_link('pool/order') ).' + '.make_form(make_link('pool/order')).' '; - if($user->id == $pool['user_id'] || $user->is_admin()){ - $editor .= " + if ($user->id == $pool['user_id'] || $user->is_admin()) { + $editor .= " "; - $sb = new SetupBlock("General"); - $sb->position = 0; - $sb->add_text_option("title", "Site title: "); - $sb->add_text_option("front_page", "
    Front page: "); - $sb->add_text_option("main_page", "
    Main page: "); - $sb->add_text_option("contact_link", "
    Contact URL: "); - $sb->add_choice_option("theme", $themes, "
    Theme: "); - //$sb->add_multichoice_option("testarray", array("a" => "b", "c" => "d"), "
    Test Array: "); - $sb->add_bool_option("nice_urls", "
    Nice URLs: "); - $sb->add_label("(Javascript inactive, can't test!)$nicescript"); - $event->panel->add_block($sb); + $sb = new SetupBlock("General"); + $sb->position = 0; + $sb->add_text_option("title", "Site title: "); + $sb->add_text_option("front_page", "
    Front page: "); + $sb->add_text_option("main_page", "
    Main page: "); + $sb->add_text_option("contact_link", "
    Contact URL: "); + $sb->add_choice_option("theme", $themes, "
    Theme: "); + //$sb->add_multichoice_option("testarray", array("a" => "b", "c" => "d"), "
    Test Array: "); + $sb->add_bool_option("nice_urls", "
    Nice URLs: "); + $sb->add_label("(Javascript inactive, can't test!)$nicescript"); + $event->panel->add_block($sb); - $sb = new SetupBlock("Remote API Integration"); - $sb->add_label("Akismet"); - $sb->add_text_option("comment_wordpress_key", "
    API key: "); - $sb->add_label("
     
    ReCAPTCHA"); - $sb->add_text_option("api_recaptcha_privkey", "
    Secret key: "); - $sb->add_text_option("api_recaptcha_pubkey", "
    Site key: "); - $event->panel->add_block($sb); - } + $sb = new SetupBlock("Remote API Integration"); + $sb->add_label("Akismet"); + $sb->add_text_option("comment_wordpress_key", "
    API key: "); + $sb->add_label("
     
    ReCAPTCHA"); + $sb->add_text_option("api_recaptcha_privkey", "
    Secret key: "); + $sb->add_text_option("api_recaptcha_pubkey", "
    Site key: "); + $event->panel->add_block($sb); + } - public function onConfigSave(ConfigSaveEvent $event) { - global $config; - foreach($_POST as $_name => $junk) { - if(substr($_name, 0, 6) == "_type_") { - $name = substr($_name, 6); - $type = $_POST["_type_$name"]; - $value = isset($_POST["_config_$name"]) ? $_POST["_config_$name"] : null; - switch($type) { - case "string": $config->set_string($name, $value); break; - case "int": $config->set_int($name, $value); break; - case "bool": $config->set_bool($name, $value); break; - case "array": $config->set_array($name, $value); break; - } - } - } - log_warning("setup", "Configuration updated"); - foreach(glob("data/cache/*.css") as $css_cache) { - unlink($css_cache); - } - log_warning("setup", "Cache cleared"); - } + public function onConfigSave(ConfigSaveEvent $event) + { + global $config; + foreach ($_POST as $_name => $junk) { + if (substr($_name, 0, 6) == "_type_") { + $name = substr($_name, 6); + $type = $_POST["_type_$name"]; + $value = isset($_POST["_config_$name"]) ? $_POST["_config_$name"] : null; + switch ($type) { + case "string": $config->set_string($name, $value); break; + case "int": $config->set_int($name, $value); break; + case "bool": $config->set_bool($name, $value); break; + case "array": $config->set_array($name, $value); break; + } + } + } + log_warning("setup", "Configuration updated"); + foreach (glob("data/cache/*.css") as $css_cache) { + unlink($css_cache); + } + log_warning("setup", "Cache cleared"); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("change_setting")) { - $event->add_link("Board Config", make_link("setup")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("change_setting")) { + $event->add_link("Board Config", make_link("setup")); + } + } } - diff --git a/ext/setup/test.php b/ext/setup/test.php index 2989472d..c2bb2874 100644 --- a/ext/setup/test.php +++ b/ext/setup/test.php @@ -1,39 +1,44 @@ get_page('nicetest'); - $this->assert_content("ok"); - $this->assert_no_content("\n"); - } +class SetupTest extends ShimmiePHPUnitTestCase +{ + public function testNiceUrlsTest() + { + # XXX: this only checks that the text is "ok", to check + # for a bug where it was coming out as "\nok"; it doesn't + # check that niceurls actually work + $this->get_page('nicetest'); + $this->assert_content("ok"); + $this->assert_no_content("\n"); + } - public function testAuthAnon() { - $this->get_page('setup'); - $this->assert_response(403); - $this->assert_title("Permission Denied"); - } + public function testAuthAnon() + { + $this->get_page('setup'); + $this->assert_response(403); + $this->assert_title("Permission Denied"); + } - public function testAuthUser() { - $this->log_in_as_user(); - $this->get_page('setup'); - $this->assert_response(403); - $this->assert_title("Permission Denied"); - } + public function testAuthUser() + { + $this->log_in_as_user(); + $this->get_page('setup'); + $this->assert_response(403); + $this->assert_title("Permission Denied"); + } - public function testAuthAdmin() { - $this->log_in_as_admin(); - $this->get_page('setup'); - $this->assert_title("Shimmie Setup"); - $this->assert_text("General"); - } + public function testAuthAdmin() + { + $this->log_in_as_admin(); + $this->get_page('setup'); + $this->assert_title("Shimmie Setup"); + $this->assert_text("General"); + } - public function testAdvanced() { - $this->log_in_as_admin(); - $this->get_page('setup/advanced'); - $this->assert_title("Shimmie Setup"); - $this->assert_text("thumb_quality"); - } + public function testAdvanced() + { + $this->log_in_as_admin(); + $this->get_page('setup/advanced'); + $this->assert_title("Shimmie Setup"); + $this->assert_text("thumb_quality"); + } } - diff --git a/ext/setup/theme.php b/ext/setup/theme.php index 6a563890..fc3f97cc 100644 --- a/ext/setup/theme.php +++ b/ext/setup/theme.php @@ -1,61 +1,63 @@ blocks the blocks to be displayed, unsorted - * - * It's recommented that the theme sort the blocks before doing anything - * else, using: usort($panel->blocks, "blockcmp"); - * - * The page should wrap all the options in a form which links to setup_save - */ - public function display_page(Page $page, SetupPanel $panel) { - usort($panel->blocks, "blockcmp"); +class SetupTheme extends Themelet +{ + /* + * Display a set of setup option blocks + * + * $panel = the container of the blocks + * $panel->blocks the blocks to be displayed, unsorted + * + * It's recommented that the theme sort the blocks before doing anything + * else, using: usort($panel->blocks, "blockcmp"); + * + * The page should wrap all the options in a form which links to setup_save + */ + public function display_page(Page $page, SetupPanel $panel) + { + usort($panel->blocks, "blockcmp"); - /* - * Try and keep the two columns even; count the line breaks in - * each an calculate where a block would work best - */ - $setupblock_html = ""; - foreach($panel->blocks as $block) { - $setupblock_html .= $this->sb_to_html($block); - } + /* + * Try and keep the two columns even; count the line breaks in + * each an calculate where a block would work best + */ + $setupblock_html = ""; + foreach ($panel->blocks as $block) { + $setupblock_html .= $this->sb_to_html($block); + } - $table = " + $table = " ".make_form(make_link("setup/save"))."
    $setupblock_html
    "; - $page->set_title("Shimmie Setup"); - $page->set_heading("Shimmie Setup"); - $page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0)); - $page->add_block(new Block("Setup", $table)); - } + $page->set_title("Shimmie Setup"); + $page->set_heading("Shimmie Setup"); + $page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0)); + $page->add_block(new Block("Setup", $table)); + } - public function display_advanced(Page $page, $options) { - $h_rows = ""; - ksort($options); - foreach($options as $name => $value) { - $h_name = html_escape($name); - $h_value = html_escape($value); + public function display_advanced(Page $page, $options) + { + $h_rows = ""; + ksort($options); + foreach ($options as $name => $value) { + $h_name = html_escape($name); + $h_value = html_escape($value); - $h_box = ""; - if(strpos($value, "\n") > 0) { - $h_box .= ""; - } - else { - $h_box .= ""; - } - $h_box .= ""; - $h_rows .= ""; - } + $h_box = ""; + if (strpos($value, "\n") > 0) { + $h_box .= ""; + } else { + $h_box .= ""; + } + $h_box .= ""; + $h_rows .= ""; + } - $table = " + $table = " ".make_form(make_link("setup/save"))."
    Title:
    $h_name$h_box
    $h_name$h_box
    @@ -65,31 +67,32 @@ class SetupTheme extends Themelet { "; - $page->set_title("Shimmie Setup"); - $page->set_heading("Shimmie Setup"); - $page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0)); - $page->add_block(new Block("Setup", $table)); - } + $page->set_title("Shimmie Setup"); + $page->set_heading("Shimmie Setup"); + $page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0)); + $page->add_block(new Block("Setup", $table)); + } - protected function build_navigation() { - return " + protected function build_navigation() + { + return " Index
    Help
    Advanced "; - } + } - protected function sb_to_html(SetupBlock $block) { - $h = $block->header; - $b = $block->body; - $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; - $html = " + protected function sb_to_html(SetupBlock $block) + { + $h = $block->header; + $b = $block->body; + $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; + $html = "
    $h
    $b
    "; - return $html; - } + return $html; + } } - diff --git a/ext/shimmie_api/main.php b/ext/shimmie_api/main.php index e5bb90c4..317fae7b 100644 --- a/ext/shimmie_api/main.php +++ b/ext/shimmie_api/main.php @@ -18,150 +18,159 @@ */ -class _SafeImage { - public $id; - public $height; - public $width; - public $hash; - public $filesize; - public $ext; - public $posted; - public $source; - public $owner_id; - public $tags; +class _SafeImage +{ + public $id; + public $height; + public $width; + public $hash; + public $filesize; + public $ext; + public $posted; + public $source; + public $owner_id; + public $tags; - function __construct(Image $img) { - $this->id = $img->id; - $this->height = $img->height; - $this->width = $img->width; - $this->hash = $img->hash; - $this->filesize = $img->filesize; - $this->ext = $img->ext; - $this->posted = strtotime($img->posted); - $this->source = $img->source; - $this->owner_id = $img->owner_id; - $this->tags = $img->get_tag_array(); - } + public function __construct(Image $img) + { + $this->id = $img->id; + $this->height = $img->height; + $this->width = $img->width; + $this->hash = $img->hash; + $this->filesize = $img->filesize; + $this->ext = $img->ext; + $this->posted = strtotime($img->posted); + $this->source = $img->source; + $this->owner_id = $img->owner_id; + $this->tags = $img->get_tag_array(); + } } -class ShimmieApi extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; +class ShimmieApi extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("api/shimmie")) { - $page->set_mode("data"); - $page->set_type("text/plain"); + if ($event->page_matches("api/shimmie")) { + $page->set_mode("data"); + $page->set_type("text/plain"); - if($event->page_matches("api/shimmie/get_tags")){ - $tag = $event->get_arg(0); - if(empty($tag) && isset($_GET['tag'])) $tag = $_GET['tag']; - $res = $this->api_get_tags($tag); - $page->set_data(json_encode($res)); - } + if ($event->page_matches("api/shimmie/get_tags")) { + $tag = $event->get_arg(0); + if (empty($tag) && isset($_GET['tag'])) { + $tag = $_GET['tag']; + } + $res = $this->api_get_tags($tag); + $page->set_data(json_encode($res)); + } elseif ($event->page_matches("api/shimmie/get_image")) { + $arg = $event->get_arg(0); + if (empty($arg) && isset($_GET['id'])) { + $arg = $_GET['id']; + } + $image = Image::by_id(int_escape($arg)); + // FIXME: handle null image + $image->get_tag_array(); // tag data isn't loaded into the object until necessary + $safe_image = new _SafeImage($image); + $page->set_data(json_encode($safe_image)); + } elseif ($event->page_matches("api/shimmie/find_images")) { + $search_terms = $event->get_search_terms(); + $page_number = $event->get_page_number(); + $page_size = $event->get_page_size(); + $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); + $safe_images = []; + foreach ($images as $image) { + $image->get_tag_array(); + $safe_images[] = new _SafeImage($image); + } + $page->set_data(json_encode($safe_images)); + } elseif ($event->page_matches("api/shimmie/get_user")) { + $query = $user->id; + $type = "id"; + if ($event->count_args() == 1) { + $query = $event->get_arg(0); + $type = "name"; + } elseif (isset($_GET['id'])) { + $query = $_GET['id']; + } elseif (isset($_GET['name'])) { + $query = $_GET['name']; + $type = "name"; + } - elseif($event->page_matches("api/shimmie/get_image")) { - $arg = $event->get_arg(0); - if(empty($arg) && isset($_GET['id'])) $arg = $_GET['id']; - $image = Image::by_id(int_escape($arg)); - // FIXME: handle null image - $image->get_tag_array(); // tag data isn't loaded into the object until necessary - $safe_image = new _SafeImage($image); - $page->set_data(json_encode($safe_image)); - } + $all = $this->api_get_user($type, $query); + $page->set_data(json_encode($all)); + } else { + $page->set_mode("redirect"); + $page->set_redirect(make_link("ext_doc/shimmie_api")); + } + } + } - elseif($event->page_matches("api/shimmie/find_images")) { - $search_terms = $event->get_search_terms(); - $page_number = $event->get_page_number(); - $page_size = $event->get_page_size(); - $images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); - $safe_images = array(); - foreach($images as $image) { - $image->get_tag_array(); - $safe_images[] = new _SafeImage($image); - } - $page->set_data(json_encode($safe_images)); - } + /** + * #return string[] + */ + private function api_get_tags(string $arg): array + { + global $database; + if (!empty($arg)) { + $all = $database->get_all("SELECT tag FROM tags WHERE tag LIKE ?", [$arg . "%"]); + } else { + $all = $database->get_all("SELECT tag FROM tags"); + } + $res = []; + foreach ($all as $row) { + $res[] = $row["tag"]; + } + return $res; + } - elseif($event->page_matches("api/shimmie/get_user")) { - $query = $user->id; - $type = "id"; - if($event->count_args() == 1) { - $query = $event->get_arg(0); - $type = "name"; - } - elseif(isset($_GET['id'])) { - $query = $_GET['id']; - } - elseif(isset($_GET['name'])) { - $query = $_GET['name']; - $type = "name"; - } + private function api_get_user(string $type, string $query): array + { + global $database; + $all = $database->get_row( + "SELECT id, name, joindate, class FROM users WHERE $type=?", + [$query] + ); - $all = $this->api_get_user($type, $query); - $page->set_data(json_encode($all)); - } + if (!empty($all)) { + //FIXME?: For some weird reason, get_all seems to return twice. Unsetting second value to make things look nice.. + // - it returns data as eg array(0=>1234, 'id'=>1234, 1=>'bob', 'name'=>bob, ...); + for ($i = 0; $i < 4; $i++) { + unset($all[$i]); + } + $all['uploadcount'] = Image::count_images(["user_id=" . $all['id']]); + $all['commentcount'] = $database->get_one( + "SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", + ["owner_id" => $all['id']] + ); - else { - $page->set_mode("redirect"); - $page->set_redirect(make_link("ext_doc/shimmie_api")); - } + if (isset($_GET['recent'])) { + $recent = $database->get_all( + "SELECT * FROM images WHERE owner_id=? ORDER BY id DESC LIMIT 0, 5", + [$all['id']] + ); - } - } + $i = 0; + foreach ($recent as $all['recentposts'][$i]) { + unset($all['recentposts'][$i]['owner_id']); //We already know the owners id.. + unset($all['recentposts'][$i]['owner_ip']); - /** - * #return string[] - */ - private function api_get_tags(string $arg): array { - global $database; - if (!empty($arg)) { - $all = $database->get_all("SELECT tag FROM tags WHERE tag LIKE ?", array($arg . "%")); - } else { - $all = $database->get_all("SELECT tag FROM tags"); - } - $res = array(); - foreach ($all as $row) { - $res[] = $row["tag"]; - } - return $res; - } - - private function api_get_user(string $type, string $query): array { - global $database; - $all = $database->get_row( - "SELECT id, name, joindate, class FROM users WHERE $type=?", - array($query) - ); - - if (!empty($all)) { - //FIXME?: For some weird reason, get_all seems to return twice. Unsetting second value to make things look nice.. - // - it returns data as eg array(0=>1234, 'id'=>1234, 1=>'bob', 'name'=>bob, ...); - for ($i = 0; $i < 4; $i++) unset($all[$i]); - $all['uploadcount'] = Image::count_images(array("user_id=" . $all['id'])); - $all['commentcount'] = $database->get_one( - "SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", - array("owner_id" => $all['id'])); - - if (isset($_GET['recent'])) { - $recent = $database->get_all( - "SELECT * FROM images WHERE owner_id=? ORDER BY id DESC LIMIT 0, 5", - array($all['id'])); - - $i = 0; - foreach ($recent as $all['recentposts'][$i]) { - unset($all['recentposts'][$i]['owner_id']); //We already know the owners id.. - unset($all['recentposts'][$i]['owner_ip']); - - for ($x = 0; $x < 14; $x++) unset($all['recentposts'][$i][$x]); - if (empty($all['recentposts'][$i]['author'])) unset($all['recentposts'][$i]['author']); - if ($all['recentposts'][$i]['notes'] > 0) $all['recentposts'][$i]['has_notes'] = "Y"; - else $all['recentposts'][$i]['has_notes'] = "N"; - unset($all['recentposts'][$i]['notes']); - $i += 1; - } - } - } - return $all; - } + for ($x = 0; $x < 14; $x++) { + unset($all['recentposts'][$i][$x]); + } + if (empty($all['recentposts'][$i]['author'])) { + unset($all['recentposts'][$i]['author']); + } + if ($all['recentposts'][$i]['notes'] > 0) { + $all['recentposts'][$i]['has_notes'] = "Y"; + } else { + $all['recentposts'][$i]['has_notes'] = "N"; + } + unset($all['recentposts'][$i]['notes']); + $i += 1; + } + } + } + return $all; + } } - diff --git a/ext/shimmie_api/test.php b/ext/shimmie_api/test.php index 99327dba..2f6e2f39 100644 --- a/ext/shimmie_api/test.php +++ b/ext/shimmie_api/test.php @@ -1,23 +1,25 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); +class ShimmieApiTest extends ShimmiePHPUnitTestCase +{ + public function testAPI() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - // FIXME: get_page should support GET params - $this->get_page("api/shimmie/get_tags"); - $this->get_page("api/shimmie/get_tags/pb"); - //$this->get_page("api/shimmie/get_tags?tag=pb"); - $this->get_page("api/shimmie/get_image/$image_id"); - //$this->get_page("api/shimmie/get_image?id=$image_id"); - $this->get_page("api/shimmie/find_images"); - $this->get_page("api/shimmie/find_images/pbx"); - $this->get_page("api/shimmie/find_images/pbx/1"); - $this->get_page("api/shimmie/get_user/demo"); - //$this->get_page("api/shimmie/get_user?name=demo"); - //$this->get_page("api/shimmie/get_user?id=2"); + // FIXME: get_page should support GET params + $this->get_page("api/shimmie/get_tags"); + $this->get_page("api/shimmie/get_tags/pb"); + //$this->get_page("api/shimmie/get_tags?tag=pb"); + $this->get_page("api/shimmie/get_image/$image_id"); + //$this->get_page("api/shimmie/get_image?id=$image_id"); + $this->get_page("api/shimmie/find_images"); + $this->get_page("api/shimmie/find_images/pbx"); + $this->get_page("api/shimmie/find_images/pbx/1"); + $this->get_page("api/shimmie/get_user/demo"); + //$this->get_page("api/shimmie/get_user?name=demo"); + //$this->get_page("api/shimmie/get_user?id=2"); - // FIXME: test unspecified / bad values - // FIXME: test that json is encoded properly - } + // FIXME: test unspecified / bad values + // FIXME: test that json is encoded properly + } } diff --git a/ext/site_description/main.php b/ext/site_description/main.php index 80563617..56c4d730 100644 --- a/ext/site_description/main.php +++ b/ext/site_description/main.php @@ -10,24 +10,26 @@ * This extension sets the "description" meta tag in the header * of pages so that search engines can pick it up */ -class SiteDescription extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $config, $page; - if(strlen($config->get_string("site_description")) > 0) { - $description = $config->get_string("site_description"); - $page->add_html_header(""); - } - if(strlen($config->get_string("site_keywords")) > 0) { - $keywords = $config->get_string("site_keywords"); - $page->add_html_header(""); - } - } +class SiteDescription extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $config, $page; + if (strlen($config->get_string("site_description")) > 0) { + $description = $config->get_string("site_description"); + $page->add_html_header(""); + } + if (strlen($config->get_string("site_keywords")) > 0) { + $keywords = $config->get_string("site_keywords"); + $page->add_html_header(""); + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Site Description"); - $sb->add_text_option("site_description", "Description: "); - $sb->add_text_option("site_keywords", "
    Keywords: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Site Description"); + $sb->add_text_option("site_description", "Description: "); + $sb->add_text_option("site_keywords", "
    Keywords: "); + $event->panel->add_block($sb); + } } - diff --git a/ext/site_description/test.php b/ext/site_description/test.php index 073252be..6cd01aa0 100644 --- a/ext/site_description/test.php +++ b/ext/site_description/test.php @@ -1,23 +1,25 @@ set_string("site_description", "A Shimmie testbed"); - $this->get_page("post/list"); - $this->assertContains( - '', - $page->get_all_html_headers() - ); - } +class SiteDescriptionTest extends ShimmiePHPUnitTestCase +{ + public function testSiteDescription() + { + global $config, $page; + $config->set_string("site_description", "A Shimmie testbed"); + $this->get_page("post/list"); + $this->assertContains( + '', + $page->get_all_html_headers() + ); + } - public function testSiteKeywords() { - global $config, $page; - $config->set_string("site_keywords", "foo,bar,baz"); - $this->get_page("post/list"); - $this->assertContains( - '', - $page->get_all_html_headers() - ); - } + public function testSiteKeywords() + { + global $config, $page; + $config->set_string("site_keywords", "foo,bar,baz"); + $this->get_page("post/list"); + $this->assertContains( + '', + $page->get_all_html_headers() + ); + } } - diff --git a/ext/sitemap/main.php b/ext/sitemap/main.php index dc500cad..d7a17217 100644 --- a/ext/sitemap/main.php +++ b/ext/sitemap/main.php @@ -12,177 +12,184 @@ class XMLSitemap extends Extension { - private $sitemap_queue = ""; - private $sitemap_filepath = ""; // set onPageRequest + private $sitemap_queue = ""; + private $sitemap_filepath = ""; // set onPageRequest - public function onPageRequest(PageRequestEvent $event) - { - if ($event->page_matches("sitemap.xml")) { - global $config; + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("sitemap.xml")) { + global $config; - $this->sitemap_filepath = data_path("cache/sitemap.xml"); - // determine if new sitemap needs to be generated - if ($this->new_sitemap_needed()) { - // determine which type of sitemap to generate - if ($config->get_bool("sitemap_generatefull", false)) { - $this->handle_full_sitemap(); // default false until cache fixed - } else { - $this->handle_smaller_sitemap(); - } - } else $this->display_existing_sitemap(); - } - } + $this->sitemap_filepath = data_path("cache/sitemap.xml"); + // determine if new sitemap needs to be generated + if ($this->new_sitemap_needed()) { + // determine which type of sitemap to generate + if ($config->get_bool("sitemap_generatefull", false)) { + $this->handle_full_sitemap(); // default false until cache fixed + } else { + $this->handle_smaller_sitemap(); + } + } else { + $this->display_existing_sitemap(); + } + } + } - public function onSetupBuilding(SetupBuildingEvent $event) - { - $sb = new SetupBlock("Sitemap"); + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Sitemap"); - $sb->add_bool_option("sitemap_generatefull", "Generate full sitemap"); - $sb->add_label("
    (Enabled: every image and tag in sitemap, generation takes longer)"); - $sb->add_label("
    (Disabled: only display the last 50 uploads in the sitemap)"); + $sb->add_bool_option("sitemap_generatefull", "Generate full sitemap"); + $sb->add_label("
    (Enabled: every image and tag in sitemap, generation takes longer)"); + $sb->add_label("
    (Disabled: only display the last 50 uploads in the sitemap)"); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - // sitemap with only the latest 50 images - private function handle_smaller_sitemap() - { - /* --- Add latest images to sitemap with higher priority --- */ - $latestimages = Image::find_images(0, 50, array()); - if(empty($latestimages)) return; - $latestimages_urllist = array(); - foreach ($latestimages as $arrayid => $image) { - // create url from image id's - $latestimages_urllist[$arrayid] = "post/view/$image->id"; - } + // sitemap with only the latest 50 images + private function handle_smaller_sitemap() + { + /* --- Add latest images to sitemap with higher priority --- */ + $latestimages = Image::find_images(0, 50, []); + if (empty($latestimages)) { + return; + } + $latestimages_urllist = []; + foreach ($latestimages as $arrayid => $image) { + // create url from image id's + $latestimages_urllist[$arrayid] = "post/view/$image->id"; + } - $this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", strtotime($image->posted))); + $this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", strtotime($image->posted))); - /* --- Display page --- */ - // when sitemap is ok, display it from the file - $this->generate_display_sitemap(); - } + /* --- Display page --- */ + // when sitemap is ok, display it from the file + $this->generate_display_sitemap(); + } - // Full sitemap - private function handle_full_sitemap() - { - global $database, $config; + // Full sitemap + private function handle_full_sitemap() + { + global $database, $config; - // add index - $index = array(); - $index[0] = $config->get_string("front_page"); - $this->add_sitemap_queue($index, "weekly", "1"); + // add index + $index = []; + $index[0] = $config->get_string("front_page"); + $this->add_sitemap_queue($index, "weekly", "1"); - /* --- Add 20 most used tags --- */ - $popular_tags = $database->get_all("SELECT tag, count FROM tags ORDER BY `count` DESC LIMIT 0,20"); - foreach ($popular_tags as $arrayid => $tag) { - $tag = $tag['tag']; - $popular_tags[$arrayid] = "post/list/$tag/"; - } - $this->add_sitemap_queue($popular_tags, "monthly", "0.9" /* not sure how to deal with date here */); + /* --- Add 20 most used tags --- */ + $popular_tags = $database->get_all("SELECT tag, count FROM tags ORDER BY `count` DESC LIMIT 0,20"); + foreach ($popular_tags as $arrayid => $tag) { + $tag = $tag['tag']; + $popular_tags[$arrayid] = "post/list/$tag/"; + } + $this->add_sitemap_queue($popular_tags, "monthly", "0.9" /* not sure how to deal with date here */); - /* --- Add latest images to sitemap with higher priority --- */ - $latestimages = Image::find_images(0, 50, array()); - $latestimages_urllist = array(); - foreach ($latestimages as $arrayid => $image) { - // create url from image id's - $latestimages_urllist[$arrayid] = "post/view/$image->id"; - } - $this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", strtotime($image->posted))); + /* --- Add latest images to sitemap with higher priority --- */ + $latestimages = Image::find_images(0, 50, []); + $latestimages_urllist = []; + foreach ($latestimages as $arrayid => $image) { + // create url from image id's + $latestimages_urllist[$arrayid] = "post/view/$image->id"; + } + $this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", strtotime($image->posted))); - /* --- Add other tags --- */ - $other_tags = $database->get_all("SELECT tag, count FROM tags ORDER BY `count` DESC LIMIT 21,10000000"); - foreach ($other_tags as $arrayid => $tag) { - $tag = $tag['tag']; - // create url from tags (tagme ignored) - if ($tag != "tagme") - $other_tags[$arrayid] = "post/list/$tag/"; - } - $this->add_sitemap_queue($other_tags, "monthly", "0.7" /* not sure how to deal with date here */); + /* --- Add other tags --- */ + $other_tags = $database->get_all("SELECT tag, count FROM tags ORDER BY `count` DESC LIMIT 21,10000000"); + foreach ($other_tags as $arrayid => $tag) { + $tag = $tag['tag']; + // create url from tags (tagme ignored) + if ($tag != "tagme") { + $other_tags[$arrayid] = "post/list/$tag/"; + } + } + $this->add_sitemap_queue($other_tags, "monthly", "0.7" /* not sure how to deal with date here */); - /* --- Add all other images to sitemap with lower priority --- */ - $otherimages = Image::find_images(51, 10000000, array()); - foreach ($otherimages as $arrayid => $image) { - // create url from image id's - $otherimages[$arrayid] = "post/view/$image->id"; - } - $this->add_sitemap_queue($otherimages, "monthly", "0.6", date("Y-m-d", strtotime($image->posted))); + /* --- Add all other images to sitemap with lower priority --- */ + $otherimages = Image::find_images(51, 10000000, []); + foreach ($otherimages as $arrayid => $image) { + // create url from image id's + $otherimages[$arrayid] = "post/view/$image->id"; + } + $this->add_sitemap_queue($otherimages, "monthly", "0.6", date("Y-m-d", strtotime($image->posted))); - /* --- Display page --- */ - // when sitemap is ok, display it from the file - $this->generate_display_sitemap(); - } + /* --- Display page --- */ + // when sitemap is ok, display it from the file + $this->generate_display_sitemap(); + } - /** - * Adds an array of urls to the sitemap with the given information. - */ - private function add_sitemap_queue(array $urls, string $changefreq = "monthly", - string $priority = "0.5", string $date = "2013-02-01") - { - foreach ($urls as $url) { - $link = make_http(make_link("$url")); - $this->sitemap_queue .= " + /** + * Adds an array of urls to the sitemap with the given information. + */ + private function add_sitemap_queue( + array $urls, + string $changefreq = "monthly", + string $priority = "0.5", + string $date = "2013-02-01" + ) { + foreach ($urls as $url) { + $link = make_http(make_link("$url")); + $this->sitemap_queue .= " $link $date $changefreq $priority "; - } - } + } + } - // sets sitemap with entries in sitemap_queue - private function generate_display_sitemap() - { - global $page; + // sets sitemap with entries in sitemap_queue + private function generate_display_sitemap() + { + global $page; - $xml = "<" . "?xml version=\"1.0\" encoding=\"utf-8\"?" . "> + $xml = "<" . "?xml version=\"1.0\" encoding=\"utf-8\"?" . "> $this->sitemap_queue "; - // Generate new sitemap - file_put_contents($this->sitemap_filepath, $xml); - $page->set_mode("data"); - $page->set_type("application/xml"); - $page->set_data($xml); - } + // Generate new sitemap + file_put_contents($this->sitemap_filepath, $xml); + $page->set_mode("data"); + $page->set_type("application/xml"); + $page->set_data($xml); + } - /** - * Returns true if a new sitemap is needed. - */ - private function new_sitemap_needed(): bool - { - if(!file_exists($this->sitemap_filepath)) { - return true; - } + /** + * Returns true if a new sitemap is needed. + */ + private function new_sitemap_needed(): bool + { + if (!file_exists($this->sitemap_filepath)) { + return true; + } - $sitemap_generation_interval = 86400; // allow new site map every day - $last_generated_time = filemtime($this->sitemap_filepath); + $sitemap_generation_interval = 86400; // allow new site map every day + $last_generated_time = filemtime($this->sitemap_filepath); - // if file doesn't exist, return true - if ($last_generated_time == false) { - return true; - } + // if file doesn't exist, return true + if ($last_generated_time == false) { + return true; + } - // if it's been a day since last sitemap creation, return true - if ($last_generated_time + $sitemap_generation_interval < time()) { - return true; - } else { - return false; - } - } + // if it's been a day since last sitemap creation, return true + if ($last_generated_time + $sitemap_generation_interval < time()) { + return true; + } else { + return false; + } + } - private function display_existing_sitemap() - { - global $page; + private function display_existing_sitemap() + { + global $page; - $xml = file_get_contents($this->sitemap_filepath); + $xml = file_get_contents($this->sitemap_filepath); - $page->set_mode("data"); - $page->set_type("application/xml"); - $page->set_data($xml); - } + $page->set_mode("data"); + $page->set_type("application/xml"); + $page->set_data($xml); + } } - diff --git a/ext/sitemap/test.php b/ext/sitemap/test.php index a2756249..638c4c38 100644 --- a/ext/sitemap/test.php +++ b/ext/sitemap/test.php @@ -1,8 +1,10 @@ get_page('sitemap.xml'); - } +class XMLSitemapTest extends ShimmiePHPUnitTestCase +{ + public function testBasic() + { + # this will implicitly check that there are no + # PHP-level error messages + $this->get_page('sitemap.xml'); + } } diff --git a/ext/source_history/main.php b/ext/source_history/main.php index b4db5ef2..037f41a4 100644 --- a/ext/source_history/main.php +++ b/ext/source_history/main.php @@ -5,89 +5,97 @@ * Description: Keep a record of source changes, and allows you to revert changes. */ -class Source_History extends Extension { - // in before source are actually set, so that "get current source" works - public function get_priority(): int {return 40;} +class Source_History extends Extension +{ + // in before source are actually set, so that "get current source" works + public function get_priority(): int + { + return 40; + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int("history_limit", -1); + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int("history_limit", -1); - // shimmie is being installed so call install to create the table. - if($config->get_int("ext_source_history_version") < 3) { - $this->install(); - } - } + // shimmie is being installed so call install to create the table. + if ($config->get_int("ext_source_history_version") < 3) { + $this->install(); + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_admin_block(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_admin_block(); + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("source_history/revert")) { - // this is a request to revert to a previous version of the source - if($user->can("edit_image_tag")) { - if(isset($_POST['revert'])) { - $this->process_revert_request($_POST['revert']); - } - } - } - else if($event->page_matches("source_history/bulk_revert")) { - if($user->can("bulk_edit_image_tag") && $user->check_auth_token()) { - $this->process_bulk_revert_request(); - } - } - else if($event->page_matches("source_history/all")) { - $page_id = int_escape($event->get_arg(0)); - $this->theme->display_global_page($page, $this->get_global_source_history($page_id), $page_id); - } - else if($event->page_matches("source_history") && $event->count_args() == 1) { - // must be an attempt to view a source history - $image_id = int_escape($event->get_arg(0)); - $this->theme->display_history_page($page, $image_id, $this->get_source_history_from_id($image_id)); - } - } - - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - $event->add_part(" + if ($event->page_matches("source_history/revert")) { + // this is a request to revert to a previous version of the source + if ($user->can("edit_image_tag")) { + if (isset($_POST['revert'])) { + $this->process_revert_request($_POST['revert']); + } + } + } elseif ($event->page_matches("source_history/bulk_revert")) { + if ($user->can("bulk_edit_image_tag") && $user->check_auth_token()) { + $this->process_bulk_revert_request(); + } + } elseif ($event->page_matches("source_history/all")) { + $page_id = int_escape($event->get_arg(0)); + $this->theme->display_global_page($page, $this->get_global_source_history($page_id), $page_id); + } elseif ($event->page_matches("source_history") && $event->count_args() == 1) { + // must be an attempt to view a source history + $image_id = int_escape($event->get_arg(0)); + $this->theme->display_history_page($page, $image_id, $this->get_source_history_from_id($image_id)); + } + } + + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + $event->add_part(" ", 20); - } + } - /* - // disk space is cheaper than manually rebuilding history, - // so let's default to -1 and the user can go advanced if - // they /really/ want to - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Source History"); - $sb->add_label("Limit to "); - $sb->add_int_option("history_limit"); - $sb->add_label(" entires per image"); - $sb->add_label("
    (-1 for unlimited)"); - $event->panel->add_block($sb); - } - */ + /* + // disk space is cheaper than manually rebuilding history, + // so let's default to -1 and the user can go advanced if + // they /really/ want to + public function onSetupBuilding(SetupBuildingEvent $event) { + $sb = new SetupBlock("Source History"); + $sb->add_label("Limit to "); + $sb->add_int_option("history_limit"); + $sb->add_label(" entires per image"); + $sb->add_label("
    (-1 for unlimited)"); + $event->panel->add_block($sb); + } + */ - public function onSourceSet(SourceSetEvent $event) { - $this->add_source_history($event->image, $event->source); - } + public function onSourceSet(SourceSetEvent $event) + { + $this->add_source_history($event->image, $event->source); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("bulk_edit_image_tag")) { - $event->add_link("Source Changes", make_link("source_history/all/1")); - } - } - - protected function install() { - global $database, $config; + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("bulk_edit_image_tag")) { + $event->add_link("Source Changes", make_link("source_history/all/1")); + } + } + + protected function install() + { + global $database, $config; - if($config->get_int("ext_source_history_version") < 1) { - $database->create_table("source_histories", " + if ($config->get_int("ext_source_history_version") < 1) { + $database->create_table("source_histories", " id SCORE_AIPK, image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -97,185 +105,188 @@ class Source_History extends Extension { FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX source_histories_image_id_idx ON source_histories(image_id)", array()); - $config->set_int("ext_source_history_version", 3); - } - - if($config->get_int("ext_source_history_version") == 1) { - $database->Execute("ALTER TABLE source_histories ADD COLUMN user_id INTEGER NOT NULL"); - $database->Execute("ALTER TABLE source_histories ADD COLUMN date_set DATETIME NOT NULL"); - $config->set_int("ext_source_history_version", 2); - } + $database->execute("CREATE INDEX source_histories_image_id_idx ON source_histories(image_id)", []); + $config->set_int("ext_source_history_version", 3); + } + + if ($config->get_int("ext_source_history_version") == 1) { + $database->Execute("ALTER TABLE source_histories ADD COLUMN user_id INTEGER NOT NULL"); + $database->Execute("ALTER TABLE source_histories ADD COLUMN date_set DATETIME NOT NULL"); + $config->set_int("ext_source_history_version", 2); + } - if($config->get_int("ext_source_history_version") == 2) { - $database->Execute("ALTER TABLE source_histories ADD COLUMN user_ip CHAR(15) NOT NULL"); - $config->set_int("ext_source_history_version", 3); - } - } + if ($config->get_int("ext_source_history_version") == 2) { + $database->Execute("ALTER TABLE source_histories ADD COLUMN user_ip CHAR(15) NOT NULL"); + $config->set_int("ext_source_history_version", 3); + } + } - /** - * This function is called when a revert request is received. - */ - private function process_revert_request(int $revert_id) { - global $page; + /** + * This function is called when a revert request is received. + */ + private function process_revert_request(int $revert_id) + { + global $page; - $revert_id = int_escape($revert_id); + $revert_id = int_escape($revert_id); - // check for the nothing case - if($revert_id < 1) { - $page->set_mode("redirect"); - $page->set_redirect(make_link()); - return; - } - - // lets get this revert id assuming it exists - $result = $this->get_source_history_from_revert($revert_id); - - if(empty($result)) { - // there is no history entry with that id so either the image was deleted - // while the user was viewing the history, someone is playing with form - // variables or we have messed up in code somewhere. - /* calling die() is probably not a good idea, we should throw an Exception */ - die("Error: No source history with specified id was found."); - } - - // lets get the values out of the result - //$stored_result_id = $result['id']; - $stored_image_id = $result['image_id']; - $stored_source = $result['source']; - - log_debug("source_history", 'Reverting source of Image #'.$stored_image_id.' to ['.$stored_source.']'); + // check for the nothing case + if ($revert_id < 1) { + $page->set_mode("redirect"); + $page->set_redirect(make_link()); + return; + } + + // lets get this revert id assuming it exists + $result = $this->get_source_history_from_revert($revert_id); + + if (empty($result)) { + // there is no history entry with that id so either the image was deleted + // while the user was viewing the history, someone is playing with form + // variables or we have messed up in code somewhere. + /* calling die() is probably not a good idea, we should throw an Exception */ + die("Error: No source history with specified id was found."); + } + + // lets get the values out of the result + //$stored_result_id = $result['id']; + $stored_image_id = $result['image_id']; + $stored_source = $result['source']; + + log_debug("source_history", 'Reverting source of Image #'.$stored_image_id.' to ['.$stored_source.']'); - $image = Image::by_id($stored_image_id); - - if (is_null($image)) { - die('Error: No image with the id ('.$stored_image_id.') was found. Perhaps the image was deleted while processing this request.'); - } + $image = Image::by_id($stored_image_id); + + if (is_null($image)) { + die('Error: No image with the id ('.$stored_image_id.') was found. Perhaps the image was deleted while processing this request.'); + } - // all should be ok so we can revert by firing the SetUserSources event. - send_event(new SourceSetEvent($image, $stored_source)); - - // all should be done now so redirect the user back to the image - $page->set_mode("redirect"); - $page->set_redirect(make_link('post/view/'.$stored_image_id)); - } + // all should be ok so we can revert by firing the SetUserSources event. + send_event(new SourceSetEvent($image, $stored_source)); + + // all should be done now so redirect the user back to the image + $page->set_mode("redirect"); + $page->set_redirect(make_link('post/view/'.$stored_image_id)); + } - protected function process_bulk_revert_request() { - if (isset($_POST['revert_name']) && !empty($_POST['revert_name'])) { - $revert_name = $_POST['revert_name']; - } - else { - $revert_name = null; - } + protected function process_bulk_revert_request() + { + if (isset($_POST['revert_name']) && !empty($_POST['revert_name'])) { + $revert_name = $_POST['revert_name']; + } else { + $revert_name = null; + } - if (isset($_POST['revert_ip']) && !empty($_POST['revert_ip'])) { - $revert_ip = filter_var($_POST['revert_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE); - - if ($revert_ip === false) { - // invalid ip given. - $this->theme->display_admin_block('Invalid IP'); - return; - } - } - else { - $revert_ip = null; - } - - if (isset($_POST['revert_date']) && !empty($_POST['revert_date'])) { - if (isValidDate($_POST['revert_date']) ){ - $revert_date = addslashes($_POST['revert_date']); // addslashes is really unnecessary since we just checked if valid, but better safe. - } - else { - $this->theme->display_admin_block('Invalid Date'); - return; - } - } - else { - $revert_date = null; - } - - set_time_limit(0); // reverting changes can take a long time, disable php's timelimit if possible. - - // Call the revert function. - $this->process_revert_all_changes($revert_name, $revert_ip, $revert_date); - // output results - $this->theme->display_revert_ip_results(); - } + if (isset($_POST['revert_ip']) && !empty($_POST['revert_ip'])) { + $revert_ip = filter_var($_POST['revert_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE); + + if ($revert_ip === false) { + // invalid ip given. + $this->theme->display_admin_block('Invalid IP'); + return; + } + } else { + $revert_ip = null; + } + + if (isset($_POST['revert_date']) && !empty($_POST['revert_date'])) { + if (isValidDate($_POST['revert_date'])) { + $revert_date = addslashes($_POST['revert_date']); // addslashes is really unnecessary since we just checked if valid, but better safe. + } else { + $this->theme->display_admin_block('Invalid Date'); + return; + } + } else { + $revert_date = null; + } + + set_time_limit(0); // reverting changes can take a long time, disable php's timelimit if possible. + + // Call the revert function. + $this->process_revert_all_changes($revert_name, $revert_ip, $revert_date); + // output results + $this->theme->display_revert_ip_results(); + } - public function get_source_history_from_revert(int $revert_id): ?array { - global $database; - $row = $database->get_row(" + public function get_source_history_from_revert(int $revert_id): ?array + { + global $database; + $row = $database->get_row(" SELECT source_histories.*, users.name FROM source_histories JOIN users ON source_histories.user_id = users.id - WHERE source_histories.id = ?", array($revert_id)); - return ($row ? $row : null); - } + WHERE source_histories.id = ?", [$revert_id]); + return ($row ? $row : null); + } - public function get_source_history_from_id(int $image_id): array { - global $database; - $row = $database->get_all(" + public function get_source_history_from_id(int $image_id): array + { + global $database; + $row = $database->get_all( + " SELECT source_histories.*, users.name FROM source_histories JOIN users ON source_histories.user_id = users.id WHERE image_id = ? ORDER BY source_histories.id DESC", - array($image_id)); - return ($row ? $row : array()); - } + [$image_id] + ); + return ($row ? $row : []); + } - public function get_global_source_history(int $page_id): array { - global $database; - $row = $database->get_all(" + public function get_global_source_history(int $page_id): array + { + global $database; + $row = $database->get_all(" SELECT source_histories.*, users.name FROM source_histories JOIN users ON source_histories.user_id = users.id ORDER BY source_histories.id DESC LIMIT 100 OFFSET :offset - ", array("offset" => ($page_id-1)*100)); - return ($row ? $row : array()); - } + ", ["offset" => ($page_id-1)*100]); + return ($row ? $row : []); + } - /** - * This function attempts to revert all changes by a given IP within an (optional) timeframe. - */ - public function process_revert_all_changes(string $name, string $ip, string $date) { - global $database; - - $select_code = array(); - $select_args = array(); + /** + * This function attempts to revert all changes by a given IP within an (optional) timeframe. + */ + public function process_revert_all_changes(string $name, string $ip, string $date) + { + global $database; + + $select_code = []; + $select_args = []; - if(!is_null($name)) { - $duser = User::by_name($name); - if(is_null($duser)) { - $this->theme->add_status($name, "user not found"); - return; - } - else { - $select_code[] = 'user_id = ?'; - $select_args[] = $duser->id; - } - } + if (!is_null($name)) { + $duser = User::by_name($name); + if (is_null($duser)) { + $this->theme->add_status($name, "user not found"); + return; + } else { + $select_code[] = 'user_id = ?'; + $select_args[] = $duser->id; + } + } - if(!is_null($date)) { - $select_code[] = 'date_set >= ?'; - $select_args[] = $date; - } + if (!is_null($date)) { + $select_code[] = 'date_set >= ?'; + $select_args[] = $date; + } - if(!is_null($ip)) { - $select_code[] = 'user_ip = ?'; - $select_args[] = $ip; - } + if (!is_null($ip)) { + $select_code[] = 'user_ip = ?'; + $select_args[] = $ip; + } - if(count($select_code) == 0) { - log_error("source_history", "Tried to mass revert without any conditions"); - return; - } + if (count($select_code) == 0) { + log_error("source_history", "Tried to mass revert without any conditions"); + return; + } - log_info("source_history", 'Attempting to revert edits where '.implode(" and ", $select_code)." (".implode(" / ", $select_args).")"); - - // Get all the images that the given IP has changed source on (within the timeframe) that were last editied by the given IP - $result = $database->get_col(' + log_info("source_history", 'Attempting to revert edits where '.implode(" and ", $select_code)." (".implode(" / ", $select_args).")"); + + // Get all the images that the given IP has changed source on (within the timeframe) that were last editied by the given IP + $result = $database->get_col(' SELECT t1.image_id FROM source_histories t1 LEFT JOIN source_histories t2 ON (t1.image_id = t2.image_id AND t1.date_set < t2.date_set) @@ -283,108 +294,116 @@ class Source_History extends Extension { AND t1.image_id IN ( select image_id from source_histories where '.implode(" AND ", $select_code).') ORDER BY t1.image_id ', $select_args); - - foreach($result as $image_id) { - // Get the first source history that was done before the given IP edit - $row = $database->get_row(' + + foreach ($result as $image_id) { + // Get the first source history that was done before the given IP edit + $row = $database->get_row(' SELECT id, source FROM source_histories WHERE image_id='.$image_id.' AND NOT ('.implode(" AND ", $select_code).') ORDER BY date_set DESC LIMIT 1 ', $select_args); - - if (empty($row)) { - // we can not revert this image based on the date restriction. - // Output a message perhaps? - } - else { - $revert_id = $row['id']; - $result = $this->get_source_history_from_revert($revert_id); - - if(empty($result)) { - // there is no history entry with that id so either the image was deleted - // while the user was viewing the history, or something messed up - /* calling die() is probably not a good idea, we should throw an Exception */ - die('Error: No source history with specified id ('.$revert_id.') was found in the database.'."\n\n". - 'Perhaps the image was deleted while processing this request.'); - } - - // lets get the values out of the result - $stored_result_id = $result['id']; - $stored_image_id = $result['image_id']; - $stored_source = $result['source']; - - log_debug("source_history", 'Reverting source of Image #'.$stored_image_id.' to ['.$stored_source.']'); + + if (empty($row)) { + // we can not revert this image based on the date restriction. + // Output a message perhaps? + } else { + $revert_id = $row['id']; + $result = $this->get_source_history_from_revert($revert_id); + + if (empty($result)) { + // there is no history entry with that id so either the image was deleted + // while the user was viewing the history, or something messed up + /* calling die() is probably not a good idea, we should throw an Exception */ + die('Error: No source history with specified id ('.$revert_id.') was found in the database.'."\n\n". + 'Perhaps the image was deleted while processing this request.'); + } + + // lets get the values out of the result + $stored_result_id = $result['id']; + $stored_image_id = $result['image_id']; + $stored_source = $result['source']; + + log_debug("source_history", 'Reverting source of Image #'.$stored_image_id.' to ['.$stored_source.']'); - $image = Image::by_id($stored_image_id); + $image = Image::by_id($stored_image_id); - if (is_null($image)) { - die('Error: No image with the id ('.$stored_image_id.') was found. Perhaps the image was deleted while processing this request.'); - } + if (is_null($image)) { + die('Error: No image with the id ('.$stored_image_id.') was found. Perhaps the image was deleted while processing this request.'); + } - // all should be ok so we can revert by firing the SetSources event. - send_event(new SourceSetEvent($image, $stored_source)); - $this->theme->add_status('Reverted Change','Reverted Image #'.$image_id.' to Source History #'.$stored_result_id.' ('.$row['source'].')'); - } - } + // all should be ok so we can revert by firing the SetSources event. + send_event(new SourceSetEvent($image, $stored_source)); + $this->theme->add_status('Reverted Change', 'Reverted Image #'.$image_id.' to Source History #'.$stored_result_id.' ('.$row['source'].')'); + } + } - log_info("source_history", 'Reverted '.count($result).' edits.'); - } + log_info("source_history", 'Reverted '.count($result).' edits.'); + } - /** - * This function is called just before an images source is changed. - */ - private function add_source_history(Image $image, string $source) { - global $database, $config, $user; + /** + * This function is called just before an images source is changed. + */ + private function add_source_history(Image $image, string $source) + { + global $database, $config, $user; - $new_source = $source; - $old_source = $image->source; - - if($new_source == $old_source) return; - - if(empty($old_source)) { - /* no old source, so we are probably adding the image for the first time */ - log_debug("source_history", "adding new source history: [$new_source]"); - } - else { - log_debug("source_history", "adding source history: [$old_source] -> [$new_source]"); - } - - $allowed = $config->get_int("history_limit"); - if($allowed == 0) return; - - // if the image has no history, make one with the old source - $entries = $database->get_one("SELECT COUNT(*) FROM source_histories WHERE image_id = ?", array($image->id)); - if($entries == 0 && !empty($old_source)) { - $database->execute(" + $new_source = $source; + $old_source = $image->source; + + if ($new_source == $old_source) { + return; + } + + if (empty($old_source)) { + /* no old source, so we are probably adding the image for the first time */ + log_debug("source_history", "adding new source history: [$new_source]"); + } else { + log_debug("source_history", "adding source history: [$old_source] -> [$new_source]"); + } + + $allowed = $config->get_int("history_limit"); + if ($allowed == 0) { + return; + } + + // if the image has no history, make one with the old source + $entries = $database->get_one("SELECT COUNT(*) FROM source_histories WHERE image_id = ?", [$image->id]); + if ($entries == 0 && !empty($old_source)) { + $database->execute( + " INSERT INTO source_histories(image_id, source, user_id, user_ip, date_set) VALUES (?, ?, ?, ?, now())", - array($image->id, $old_source, $config->get_int('anon_id'), '127.0.0.1')); - $entries++; - } + [$image->id, $old_source, $config->get_int('anon_id'), '127.0.0.1'] + ); + $entries++; + } - // add a history entry - $database->execute(" + // add a history entry + $database->execute( + " INSERT INTO source_histories(image_id, source, user_id, user_ip, date_set) VALUES (?, ?, ?, ?, now())", - array($image->id, $new_source, $user->id, $_SERVER['REMOTE_ADDR'])); - $entries++; - - // if needed remove oldest one - if($allowed == -1) return; - if($entries > $allowed) { - // TODO: Make these queries better - /* - MySQL does NOT allow you to modify the same table which you use in the SELECT part. - Which means that these will probably have to stay as TWO separate queries... - - http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html - http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause - */ - $min_id = $database->get_one("SELECT MIN(id) FROM source_histories WHERE image_id = ?", array($image->id)); - $database->execute("DELETE FROM source_histories WHERE id = ?", array($min_id)); - } - } + [$image->id, $new_source, $user->id, $_SERVER['REMOTE_ADDR']] + ); + $entries++; + + // if needed remove oldest one + if ($allowed == -1) { + return; + } + if ($entries > $allowed) { + // TODO: Make these queries better + /* + MySQL does NOT allow you to modify the same table which you use in the SELECT part. + Which means that these will probably have to stay as TWO separate queries... + + http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html + http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause + */ + $min_id = $database->get_one("SELECT MIN(id) FROM source_histories WHERE image_id = ?", [$image->id]); + $database->execute("DELETE FROM source_histories WHERE id = ?", [$min_id]); + } + } } - diff --git a/ext/source_history/theme.php b/ext/source_history/theme.php index 345f4216..f987c0f2 100644 --- a/ext/source_history/theme.php +++ b/ext/source_history/theme.php @@ -1,30 +1,31 @@ ".make_form(make_link("source_history/revert"))."
      "; - $history_list = ""; - $n = 0; - foreach($history as $fields) - { - $n++; - $current_id = $fields['id']; - $current_source = html_escape($fields['source']); - $name = $fields['name']; - $date_set = autodate($fields['date_set']); - $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : ""; - $setter = "".html_escape($name)."$h_ip"; + $history_list = ""; + $n = 0; + foreach ($history as $fields) { + $n++; + $current_id = $fields['id']; + $current_source = html_escape($fields['source']); + $name = $fields['name']; + $date_set = autodate($fields['date_set']); + $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : ""; + $setter = "".html_escape($name)."$h_ip"; - $selected = ($n == 2) ? " checked" : ""; + $selected = ($n == 2) ? " checked" : ""; - $history_list .= " + $history_list .= "
    • "; - } + } - $end_string = " + $end_string = "
    "; - $history_html = $start_string . $history_list . $end_string; + $history_html = $start_string . $history_list . $end_string; - $page->set_title('Image '.$image_id.' Source History'); - $page->set_heading('Source History: '.$image_id); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Source History", $history_html, "main", 10)); - } + $page->set_title('Image '.$image_id.' Source History'); + $page->set_heading('Source History: '.$image_id); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Source History", $history_html, "main", 10)); + } - public function display_global_page(Page $page, array $history, int $page_number) { - $start_string = " + public function display_global_page(Page $page, array $history, int $page_number) + { + $start_string = "
    ".make_form(make_link("source_history/revert"))."
      "; - $end_string = " + $end_string = "
    "; - global $user; - $history_list = ""; - foreach($history as $fields) - { - $current_id = $fields['id']; - $image_id = $fields['image_id']; - $current_source = html_escape($fields['source']); - $name = $fields['name']; - $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : ""; - $setter = "".html_escape($name)."$h_ip"; + global $user; + $history_list = ""; + foreach ($history as $fields) { + $current_id = $fields['id']; + $image_id = $fields['image_id']; + $current_source = html_escape($fields['source']); + $name = $fields['name']; + $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : ""; + $setter = "".html_escape($name)."$h_ip"; - $history_list .= ' + $history_list .= '
  • '.$image_id.': '.$current_source.' (Set by '.$setter.')
  • '; - } + } - $history_html = $start_string . $history_list . $end_string; - $page->set_title("Global Source History"); - $page->set_heading("Global Source History"); - $page->add_block(new Block("Source History", $history_html, "main", 10)); + $history_html = $start_string . $history_list . $end_string; + $page->set_title("Global Source History"); + $page->set_heading("Global Source History"); + $page->add_block(new Block("Source History", $history_html, "main", 10)); - $h_prev = ($page_number <= 1) ? "Prev" : - 'Prev'; - $h_index = "Index"; - $h_next = 'Next'; + $h_prev = ($page_number <= 1) ? "Prev" : + 'Prev'; + $h_index = "Index"; + $h_next = 'Next'; - $nav = $h_prev.' | '.$h_index.' | '.$h_next; - $page->add_block(new Block("Navigation", $nav, "left")); - } + $nav = $h_prev.' | '.$h_index.' | '.$h_next; + $page->add_block(new Block("Navigation", $nav, "left")); + } - /** - * Add a section to the admin page. - */ - public function display_admin_block(string $validation_msg='') { - global $page; - - if (!empty($validation_msg)) { - $validation_msg = '
    '. $validation_msg .''; - } - - $html = ' + /** + * Add a section to the admin page. + */ + public function display_admin_block(string $validation_msg='') + { + global $page; + + if (!empty($validation_msg)) { + $validation_msg = '
    '. $validation_msg .''; + } + + $html = ' Revert source changes/edit by a specific IP address or username.
    You can restrict the time frame to revert these edits as well.
    (Date format: 2011-10-23) @@ -123,20 +125,21 @@ class Source_HistoryTheme extends Themelet {
    NameValue
    "; - $page->add_block(new Block("Mass Source Revert", $html)); - } - - /* - * Show a standard page for results to be put into - */ - public function display_revert_ip_results() { - global $page; - $html = implode($this->messages, "\n"); - $page->add_block(new Block("Bulk Revert Results", $html)); - } + $page->add_block(new Block("Mass Source Revert", $html)); + } + + /* + * Show a standard page for results to be put into + */ + public function display_revert_ip_results() + { + global $page; + $html = implode($this->messages, "\n"); + $page->add_block(new Block("Bulk Revert Results", $html)); + } - public function add_status(string $title, string $body) { - $this->messages[] = '

    '. $title .'
    '. $body .'

    '; - } + public function add_status(string $title, string $body) + { + $this->messages[] = '

    '. $title .'
    '. $body .'

    '; + } } - diff --git a/ext/statsd/main.php b/ext/statsd/main.php index 0aa28cdf..4af3c79f 100644 --- a/ext/statsd/main.php +++ b/ext/statsd/main.php @@ -11,82 +11,90 @@ _d("STATSD_HOST", null); -function dstat($name, $val) { - StatsDInterface::$stats["shimmie.$name"] = $val; +function dstat($name, $val) +{ + StatsDInterface::$stats["shimmie.$name"] = $val; } -class StatsDInterface extends Extension { - public static $stats = array(); +class StatsDInterface extends Extension +{ + public static $stats = []; - private function _stats(string $type) { - global $_shm_event_count, $database, $_shm_load_start; - $time = microtime(true) - $_shm_load_start; - StatsDInterface::$stats["shimmie.$type.hits"] = "1|c"; - StatsDInterface::$stats["shimmie.$type.time"] = "$time|ms"; - StatsDInterface::$stats["shimmie.$type.time-db"] = "{$database->dbtime}|ms"; - StatsDInterface::$stats["shimmie.$type.memory"] = memory_get_peak_usage(true)."|c"; - StatsDInterface::$stats["shimmie.$type.files"] = count(get_included_files())."|c"; - StatsDInterface::$stats["shimmie.$type.queries"] = $database->query_count."|c"; - StatsDInterface::$stats["shimmie.$type.events"] = $_shm_event_count."|c"; - StatsDInterface::$stats["shimmie.$type.cache-hits"] = $database->cache->get_hits()."|c"; - StatsDInterface::$stats["shimmie.$type.cache-misses"] = $database->cache->get_misses()."|c"; - } + private function _stats(string $type) + { + global $_shm_event_count, $database, $_shm_load_start; + $time = microtime(true) - $_shm_load_start; + StatsDInterface::$stats["shimmie.$type.hits"] = "1|c"; + StatsDInterface::$stats["shimmie.$type.time"] = "$time|ms"; + StatsDInterface::$stats["shimmie.$type.time-db"] = "{$database->dbtime}|ms"; + StatsDInterface::$stats["shimmie.$type.memory"] = memory_get_peak_usage(true)."|c"; + StatsDInterface::$stats["shimmie.$type.files"] = count(get_included_files())."|c"; + StatsDInterface::$stats["shimmie.$type.queries"] = $database->query_count."|c"; + StatsDInterface::$stats["shimmie.$type.events"] = $_shm_event_count."|c"; + StatsDInterface::$stats["shimmie.$type.cache-hits"] = $database->cache->get_hits()."|c"; + StatsDInterface::$stats["shimmie.$type.cache-misses"] = $database->cache->get_misses()."|c"; + } - public function onPageRequest(PageRequestEvent $event) { - $this->_stats("overall"); + public function onPageRequest(PageRequestEvent $event) + { + $this->_stats("overall"); - if($event->page_matches("post/view")) { # 40% - $this->_stats("post-view"); - } - else if($event->page_matches("post/list")) { # 30% - $this->_stats("post-list"); - } - else if($event->page_matches("user")) { - $this->_stats("user"); - } - else if($event->page_matches("upload")) { - $this->_stats("upload"); - } - else if($event->page_matches("rss")) { - $this->_stats("rss"); - } - else if($event->page_matches("api")) { - $this->_stats("api"); - } - else { - #global $_shm_load_start; - #$time = microtime(true) - $_shm_load_start; - #file_put_contents("data/other.log", "{$_SERVER['REQUEST_URI']} $time\n", FILE_APPEND); - $this->_stats("other"); - } + if ($event->page_matches("post/view")) { # 40% + $this->_stats("post-view"); + } elseif ($event->page_matches("post/list")) { # 30% + $this->_stats("post-list"); + } elseif ($event->page_matches("user")) { + $this->_stats("user"); + } elseif ($event->page_matches("upload")) { + $this->_stats("upload"); + } elseif ($event->page_matches("rss")) { + $this->_stats("rss"); + } elseif ($event->page_matches("api")) { + $this->_stats("api"); + } else { + #global $_shm_load_start; + #$time = microtime(true) - $_shm_load_start; + #file_put_contents("data/other.log", "{$_SERVER['REQUEST_URI']} $time\n", FILE_APPEND); + $this->_stats("other"); + } - $this->send(StatsDInterface::$stats, 1.0); - StatsDInterface::$stats = array(); - } + $this->send(StatsDInterface::$stats, 1.0); + StatsDInterface::$stats = []; + } - public function onUserCreation(UserCreationEvent $event) { - StatsDInterface::$stats["shimmie_events.user_creations"] = "1|c"; - } + public function onUserCreation(UserCreationEvent $event) + { + StatsDInterface::$stats["shimmie_events.user_creations"] = "1|c"; + } - public function onDataUpload(DataUploadEvent $event) { - StatsDInterface::$stats["shimmie_events.uploads"] = "1|c"; - } + public function onDataUpload(DataUploadEvent $event) + { + StatsDInterface::$stats["shimmie_events.uploads"] = "1|c"; + } - public function onCommentPosting(CommentPostingEvent $event) { - StatsDInterface::$stats["shimmie_events.comments"] = "1|c"; - } + public function onCommentPosting(CommentPostingEvent $event) + { + StatsDInterface::$stats["shimmie_events.comments"] = "1|c"; + } - public function onImageInfoSet(ImageInfoSetEvent $event) { - StatsDInterface::$stats["shimmie_events.info-sets"] = "1|c"; - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + StatsDInterface::$stats["shimmie_events.info-sets"] = "1|c"; + } - public function get_priority(): int {return 99;} + public function get_priority(): int + { + return 99; + } - private function send(array $data, int $sampleRate=1) { - if (!STATSD_HOST) { return; } + private function send(array $data, int $sampleRate=1) + { + if (!STATSD_HOST) { + return; + } // sampling - $sampledData = array(); + $sampledData = []; if ($sampleRate < 1) { foreach ($data as $stat => $value) { @@ -98,7 +106,9 @@ class StatsDInterface extends Extension { $sampledData = $data; } - if (empty($sampledData)) { return; } + if (empty($sampledData)) { + return; + } // Wrap this in a try/catch - failures in any of this should be silently ignored try { @@ -106,7 +116,9 @@ class StatsDInterface extends Extension { $host = $parts[0]; $port = $parts[1]; $fp = fsockopen("udp://$host", $port, $errno, $errstr); - if (! $fp) { return; } + if (! $fp) { + return; + } foreach ($sampledData as $stat => $value) { fwrite($fp, "$stat:$value"); } diff --git a/ext/tag_categories/main.php b/ext/tag_categories/main.php index e1dca36e..e3f702e8 100644 --- a/ext/tag_categories/main.php +++ b/ext/tag_categories/main.php @@ -6,153 +6,166 @@ * Description: Let tags be split into 'categories', like Danbooru's tagging */ -class TagCategories extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; - - // whether we split out separate categories on post view by default - // note: only takes effect if /post/view shows the image's exact tags - $config->set_default_bool("tag_categories_split_on_view", true); +class TagCategories extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; + + // whether we split out separate categories on post view by default + // note: only takes effect if /post/view shows the image's exact tags + $config->set_default_bool("tag_categories_split_on_view", true); - if($config->get_int("ext_tag_categories_version") < 1) { - // primary extension database, holds all our stuff! - $database->create_table('image_tag_categories', - 'category VARCHAR(60) PRIMARY KEY, + if ($config->get_int("ext_tag_categories_version") < 1) { + // primary extension database, holds all our stuff! + $database->create_table( + 'image_tag_categories', + 'category VARCHAR(60) PRIMARY KEY, display_singular VARCHAR(60), display_multiple VARCHAR(60), - color VARCHAR(7)'); + color VARCHAR(7)' + ); $config->set_int("ext_tag_categories_version", 1); log_info("tag_categories", "extension installed"); - } + } - // if empty, add our default values - $number_of_db_rows = $database->execute('SELECT COUNT(*) FROM image_tag_categories;')->fetchColumn(); + // if empty, add our default values + $number_of_db_rows = $database->execute('SELECT COUNT(*) FROM image_tag_categories;')->fetchColumn(); - if ($number_of_db_rows == 0) { - $database->execute( - 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', - array("artist", "Artist", "Artists", "#BB6666") - ); - $database->execute( - 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', - array("series", "Series", "Series", "#AA00AA") - ); - $database->execute( - 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', - array("character", "Character", "Characters", "#66BB66") - ); - } - } + if ($number_of_db_rows == 0) { + $database->execute( + 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', + ["artist", "Artist", "Artists", "#BB6666"] + ); + $database->execute( + 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', + ["series", "Series", "Series", "#AA00AA"] + ); + $database->execute( + 'INSERT INTO image_tag_categories VALUES (?, ?, ?, ?)', + ["character", "Character", "Characters", "#66BB66"] + ); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("tags/categories")) { - if($user->is_admin()) { - $this->page_update(); - $this->show_tag_categories($page); - } - } - } + if ($event->page_matches("tags/categories")) { + if ($user->is_admin()) { + $this->page_update(); + $this->show_tag_categories($page); + } + } + } - public function onSearchTermParse(SearchTermParseEvent $event) { - $matches = array(); + public function onSearchTermParse(SearchTermParseEvent $event) + { + $matches = []; - if(preg_match("/^(.+)tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9]+)$/i", $event->term, $matches)) { - global $database; - $type = $matches[1]; - $cmp = ltrim($matches[2], ":") ?: "="; - $count = $matches[3]; + if (preg_match("/^(.+)tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9]+)$/i", $event->term, $matches)) { + global $database; + $type = $matches[1]; + $cmp = ltrim($matches[2], ":") ?: "="; + $count = $matches[3]; - $types = $database->get_col('SELECT category FROM image_tag_categories'); - if(in_array($type, $types)) { - $event->add_querylet( - new Querylet("EXISTS ( + $types = $database->get_col('SELECT category FROM image_tag_categories'); + if (in_array($type, $types)) { + $event->add_querylet( + new Querylet("EXISTS ( SELECT 1 FROM image_tags it LEFT JOIN tags t ON it.tag_id = t.id WHERE images.id = it.image_id GROUP BY image_id HAVING SUM(CASE WHEN t.tag LIKE '$type:%' THEN 1 ELSE 0 END) $cmp $count - )")); - } - } - } + )") + ); + } + } + } - public function getDict() { - global $database; + public function getDict() + { + global $database; - $tc_dict = $database->get_all('SELECT * FROM image_tag_categories;'); + $tc_dict = $database->get_all('SELECT * FROM image_tag_categories;'); - return $tc_dict; - } + return $tc_dict; + } - public function getKeyedDict($key_with = 'category') { - $tc_dict = $this->getDict(); - $tc_keyed_dict = array(); + public function getKeyedDict($key_with = 'category') + { + $tc_dict = $this->getDict(); + $tc_keyed_dict = []; - foreach ($tc_dict as $row) { - $key = $row[$key_with]; - $tc_keyed_dict[$key] = $row; - } + foreach ($tc_dict as $row) { + $key = $row[$key_with]; + $tc_keyed_dict[$key] = $row; + } - return $tc_keyed_dict; - } + return $tc_keyed_dict; + } - public function page_update() { - global $user, $database; + public function page_update() + { + global $user, $database; - if(!$user->is_admin()) { - return false; - } + if (!$user->is_admin()) { + return false; + } - if(!isset($_POST['tc_status']) and - !isset($_POST['tc_category']) and - !isset($_POST['tc_display_singular']) and - !isset($_POST['tc_display_multiple']) and - !isset($_POST['tc_color'])) { - return false; - } + if (!isset($_POST['tc_status']) and + !isset($_POST['tc_category']) and + !isset($_POST['tc_display_singular']) and + !isset($_POST['tc_display_multiple']) and + !isset($_POST['tc_color'])) { + return false; + } - if($_POST['tc_status'] == 'edit') { - $is_success = $database->execute('UPDATE image_tag_categories + if ($_POST['tc_status'] == 'edit') { + $is_success = $database->execute( + 'UPDATE image_tag_categories SET display_singular=:display_singular, display_multiple=:display_multiple, color=:color WHERE category=:category', - array( - 'category' => $_POST['tc_category'], - 'display_singular' => $_POST['tc_display_singular'], - 'display_multiple' => $_POST['tc_display_multiple'], - 'color' => $_POST['tc_color'], - )); - } - else if($_POST['tc_status'] == 'new') { - $is_success = $database->execute('INSERT INTO image_tag_categories + [ + 'category' => $_POST['tc_category'], + 'display_singular' => $_POST['tc_display_singular'], + 'display_multiple' => $_POST['tc_display_multiple'], + 'color' => $_POST['tc_color'], + ] + ); + } elseif ($_POST['tc_status'] == 'new') { + $is_success = $database->execute( + 'INSERT INTO image_tag_categories VALUES (:category, :display_singular, :display_multiple, :color)', - array( - 'category' => $_POST['tc_category'], - 'display_singular' => $_POST['tc_display_singular'], - 'display_multiple' => $_POST['tc_display_multiple'], - 'color' => $_POST['tc_color'], - )); - } - else if($_POST['tc_status'] == 'delete') { - $is_success = $database->execute('DELETE FROM image_tag_categories + [ + 'category' => $_POST['tc_category'], + 'display_singular' => $_POST['tc_display_singular'], + 'display_multiple' => $_POST['tc_display_multiple'], + 'color' => $_POST['tc_color'], + ] + ); + } elseif ($_POST['tc_status'] == 'delete') { + $is_success = $database->execute( + 'DELETE FROM image_tag_categories WHERE category=:category', - array( - 'category' => $_POST['tc_category'] - )); - } + [ + 'category' => $_POST['tc_category'] + ] + ); + } - return $is_success; - } + return $is_success; + } - public function show_tag_categories($page) { - $this->theme->show_tag_categories($page, $this->getDict()); - } + public function show_tag_categories($page) + { + $this->theme->show_tag_categories($page, $this->getDict()); + } } - - diff --git a/ext/tag_categories/theme.php b/ext/tag_categories/theme.php index cb98b7e3..50e6ef25 100644 --- a/ext/tag_categories/theme.php +++ b/ext/tag_categories/theme.php @@ -1,10 +1,12 @@ image = $image; - $this->owner = $owner; - } + public function __construct(Image $image, User $owner) + { + $this->image = $image; + $this->owner = $owner; + } } -class SourceSetEvent extends Event { - /** @var \Image */ - public $image; - /** @var string */ - public $source; +class SourceSetEvent extends Event +{ + /** @var \Image */ + public $image; + /** @var string */ + public $source; - public function __construct(Image $image, string $source=null) { - $this->image = $image; - $this->source = $source; - } + public function __construct(Image $image, string $source=null) + { + $this->image = $image; + $this->source = $source; + } } -class TagSetEvent extends Event { - /** @var \Image */ - public $image; - public $tags; - public $metatags; +class TagSetEvent extends Event +{ + /** @var \Image */ + public $image; + public $tags; + public $metatags; - /** - * #param string[] $tags - */ - public function __construct(Image $image, array $tags) { - $this->image = $image; + /** + * #param string[] $tags + */ + public function __construct(Image $image, array $tags) + { + $this->image = $image; - $this->tags = array(); - $this->metatags = array(); + $this->tags = []; + $this->metatags = []; - foreach($tags as $tag) { - if((strpos($tag, ':') === FALSE) && (strpos($tag, '=') === FALSE)) { - //Tag doesn't contain : or =, meaning it can't possibly be a metatag. - //This should help speed wise, as it avoids running every single tag through a bunch of preg_match instead. - array_push($this->tags, $tag); - continue; - } + foreach ($tags as $tag) { + if ((strpos($tag, ':') === false) && (strpos($tag, '=') === false)) { + //Tag doesn't contain : or =, meaning it can't possibly be a metatag. + //This should help speed wise, as it avoids running every single tag through a bunch of preg_match instead. + array_push($this->tags, $tag); + continue; + } - $ttpe = new TagTermParseEvent($tag, $this->image->id, FALSE); //Only check for metatags, don't parse. Parsing is done after set_tags. - send_event($ttpe); + $ttpe = new TagTermParseEvent($tag, $this->image->id, false); //Only check for metatags, don't parse. Parsing is done after set_tags. + send_event($ttpe); - //seperate tags from metatags - if(!$ttpe->is_metatag()) { - array_push($this->tags, $tag); - }else{ - array_push($this->metatags, $tag); - } - } - } + //seperate tags from metatags + if (!$ttpe->is_metatag()) { + array_push($this->tags, $tag); + } else { + array_push($this->metatags, $tag); + } + } + } } -class LockSetEvent extends Event { - /** @var \Image */ - public $image; - /** @var bool */ - public $locked; +class LockSetEvent extends Event +{ + /** @var \Image */ + public $image; + /** @var bool */ + public $locked; - public function __construct(Image $image, bool $locked) { - $this->image = $image; - $this->locked = $locked; - } + public function __construct(Image $image, bool $locked) + { + $this->image = $image; + $this->locked = $locked; + } } /* * TagTermParseEvent: * Signal that a tag term needs parsing */ -class TagTermParseEvent extends Event { - public $term = NULL; //tag - public $id = NULL; //image_id - /** @var bool */ - public $metatag = FALSE; - /** @var bool */ - public $parse = TRUE; //marks the tag to be parsed, and not just checked if valid metatag +class TagTermParseEvent extends Event +{ + public $term = null; //tag + public $id = null; //image_id + /** @var bool */ + public $metatag = false; + /** @var bool */ + public $parse = true; //marks the tag to be parsed, and not just checked if valid metatag - public function __construct(string $term, int $id, bool $parse) { - $this->term = $term; - $this->id = $id; - $this->parse = $parse; - } + public function __construct(string $term, int $id, bool $parse) + { + $this->term = $term; + $this->id = $id; + $this->parse = $parse; + } - public function is_metatag(): bool { - return $this->metatag; - } + public function is_metatag(): bool + { + return $this->metatag; + } } -class TagEdit extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $user, $page; - if($event->page_matches("tag_edit")) { - if($event->get_arg(0) == "replace") { - if($user->can("mass_tag_edit") && isset($_POST['search']) && isset($_POST['replace'])) { - $search = $_POST['search']; - $replace = $_POST['replace']; - $this->mass_tag_edit($search, $replace); - $page->set_mode("redirect"); - $page->set_redirect(make_link("admin")); - } - } - if($event->get_arg(0) == "mass_source_set") { - if($user->can("mass_tag_edit") && isset($_POST['tags']) && isset($_POST['source'])) { - $this->mass_source_edit($_POST['tags'], $_POST['source']); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/list")); - } - } - } - } +class TagEdit extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $user, $page; + if ($event->page_matches("tag_edit")) { + if ($event->get_arg(0) == "replace") { + if ($user->can("mass_tag_edit") && isset($_POST['search']) && isset($_POST['replace'])) { + $search = $_POST['search']; + $replace = $_POST['replace']; + $this->mass_tag_edit($search, $replace); + $page->set_mode("redirect"); + $page->set_redirect(make_link("admin")); + } + } + if ($event->get_arg(0) == "mass_source_set") { + if ($user->can("mass_tag_edit") && isset($_POST['tags']) && isset($_POST['source'])) { + $this->mass_source_edit($_POST['tags'], $_POST['source']); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/list")); + } + } + } + } - public function onPostListBuilding(PostListBuildingEvent $event) { - global $user; - if($user->can("bulk_edit_image_source") && !empty($event->search_terms)) { - $event->add_control($this->theme->mss_html(Tag::implode($event->search_terms))); - } - } + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $user; + if ($user->can("bulk_edit_image_source") && !empty($event->search_terms)) { + $event->add_control($this->theme->mss_html(Tag::implode($event->search_terms))); + } + } - public function onImageInfoSet(ImageInfoSetEvent $event) { - global $user; - if($user->can("edit_image_owner") && isset($_POST['tag_edit__owner'])) { - $owner = User::by_name($_POST['tag_edit__owner']); - if ($owner instanceof User) { - send_event(new OwnerSetEvent($event->image, $owner)); - } else { - throw new NullUserException("Error: No user with that name was found."); - } - } - if($this->can_tag($event->image) && isset($_POST['tag_edit__tags'])) { - send_event(new TagSetEvent($event->image, Tag::explode($_POST['tag_edit__tags']))); - } - if($this->can_source($event->image) && isset($_POST['tag_edit__source'])) { - if(isset($_POST['tag_edit__tags']) ? !preg_match('/source[=|:]/', $_POST["tag_edit__tags"]) : TRUE){ - send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source'])); - } - } - if($user->can("edit_image_lock")) { - $locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on"; - send_event(new LockSetEvent($event->image, $locked)); - } - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + global $user; + if ($user->can("edit_image_owner") && isset($_POST['tag_edit__owner'])) { + $owner = User::by_name($_POST['tag_edit__owner']); + if ($owner instanceof User) { + send_event(new OwnerSetEvent($event->image, $owner)); + } else { + throw new NullUserException("Error: No user with that name was found."); + } + } + if ($this->can_tag($event->image) && isset($_POST['tag_edit__tags'])) { + send_event(new TagSetEvent($event->image, Tag::explode($_POST['tag_edit__tags']))); + } + if ($this->can_source($event->image) && isset($_POST['tag_edit__source'])) { + if (isset($_POST['tag_edit__tags']) ? !preg_match('/source[=|:]/', $_POST["tag_edit__tags"]) : true) { + send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source'])); + } + } + if ($user->can("edit_image_lock")) { + $locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on"; + send_event(new LockSetEvent($event->image, $locked)); + } + } - public function onOwnerSet(OwnerSetEvent $event) { - global $user; - if($user->can("edit_image_owner") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { - $event->image->set_owner($event->owner); - } - } + public function onOwnerSet(OwnerSetEvent $event) + { + global $user; + if ($user->can("edit_image_owner") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { + $event->image->set_owner($event->owner); + } + } - public function onTagSet(TagSetEvent $event) { - global $user; - if($user->can("edit_image_tag") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { - $event->image->set_tags($event->tags); - } - $event->image->parse_metatags($event->metatags, $event->image->id); - } + public function onTagSet(TagSetEvent $event) + { + global $user; + if ($user->can("edit_image_tag") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { + $event->image->set_tags($event->tags); + } + $event->image->parse_metatags($event->metatags, $event->image->id); + } - public function onSourceSet(SourceSetEvent $event) { - global $user; - if($user->can("edit_image_source") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { - $event->image->set_source($event->source); - } - } + public function onSourceSet(SourceSetEvent $event) + { + global $user; + if ($user->can("edit_image_source") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) { + $event->image->set_source($event->source); + } + } - public function onLockSet(LockSetEvent $event) { - global $user; - if($user->can("edit_image_lock")) { - $event->image->set_locked($event->locked); - } - } + public function onLockSet(LockSetEvent $event) + { + global $user; + if ($user->can("edit_image_lock")) { + $event->image->set_locked($event->locked); + } + } - public function onImageDeletion(ImageDeletionEvent $event) { - $event->image->delete_tags_from_image(); - } + public function onImageDeletion(ImageDeletionEvent $event) + { + $event->image->delete_tags_from_image(); + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_mass_editor(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_mass_editor(); + } - /** - * When an alias is added, oldtag becomes inaccessible. - */ - public function onAddAlias(AddAliasEvent $event) { - $this->mass_tag_edit($event->oldtag, $event->newtag); - } + /** + * When an alias is added, oldtag becomes inaccessible. + */ + public function onAddAlias(AddAliasEvent $event) + { + $this->mass_tag_edit($event->oldtag, $event->newtag); + } - public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { - $event->add_part($this->theme->get_user_editor_html($event->image), 39); - $event->add_part($this->theme->get_tag_editor_html($event->image), 40); - $event->add_part($this->theme->get_source_editor_html($event->image), 41); - $event->add_part($this->theme->get_lock_editor_html($event->image), 42); - } + public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) + { + $event->add_part($this->theme->get_user_editor_html($event->image), 39); + $event->add_part($this->theme->get_tag_editor_html($event->image), 40); + $event->add_part($this->theme->get_source_editor_html($event->image), 41); + $event->add_part($this->theme->get_lock_editor_html($event->image), 42); + } - public function onTagTermParse(TagTermParseEvent $event) { - $matches = array(); + public function onTagTermParse(TagTermParseEvent $event) + { + $matches = []; - if(preg_match("/^source[=|:](.*)$/i", $event->term, $matches) && $event->parse) { - $source = ($matches[1] !== "none" ? $matches[1] : null); - send_event(new SourceSetEvent(Image::by_id($event->id), $source)); - } + if (preg_match("/^source[=|:](.*)$/i", $event->term, $matches) && $event->parse) { + $source = ($matches[1] !== "none" ? $matches[1] : null); + send_event(new SourceSetEvent(Image::by_id($event->id), $source)); + } - if(!empty($matches)) $event->metatag = true; - } + if (!empty($matches)) { + $event->metatag = true; + } + } - private function can_tag(Image $image): bool { - global $user; - return ($user->can("edit_image_tag") || !$image->is_locked()); - } + private function can_tag(Image $image): bool + { + global $user; + return ($user->can("edit_image_tag") || !$image->is_locked()); + } - private function can_source(Image $image): bool { - global $user; - return ($user->can("edit_image_source") || !$image->is_locked()); - } + private function can_source(Image $image): bool + { + global $user; + return ($user->can("edit_image_source") || !$image->is_locked()); + } - private function mass_tag_edit(string $search, string $replace) { - global $database; + private function mass_tag_edit(string $search, string $replace) + { + global $database; - $search_set = Tag::explode(strtolower($search), false); - $replace_set = Tag::explode(strtolower($replace), false); + $search_set = Tag::explode(strtolower($search), false); + $replace_set = Tag::explode(strtolower($replace), false); - log_info("tag_edit", "Mass editing tags: '$search' -> '$replace'"); + log_info("tag_edit", "Mass editing tags: '$search' -> '$replace'"); - if(count($search_set) == 1 && count($replace_set) == 1) { - $images = Image::find_images(0, 10, $replace_set); - if(count($images) == 0) { - log_info("tag_edit", "No images found with target tag, doing in-place rename"); - $database->execute("DELETE FROM tags WHERE tag=:replace", - array("replace" => $replace_set[0])); - $database->execute("UPDATE tags SET tag=:replace WHERE tag=:search", - array("replace" => $replace_set[0], "search" => $search_set[0])); - return; - } - } + if (count($search_set) == 1 && count($replace_set) == 1) { + $images = Image::find_images(0, 10, $replace_set); + if (count($images) == 0) { + log_info("tag_edit", "No images found with target tag, doing in-place rename"); + $database->execute( + "DELETE FROM tags WHERE tag=:replace", + ["replace" => $replace_set[0]] + ); + $database->execute( + "UPDATE tags SET tag=:replace WHERE tag=:search", + ["replace" => $replace_set[0], "search" => $search_set[0]] + ); + return; + } + } - $last_id = -1; - while(true) { - // make sure we don't look at the same images twice. - // search returns high-ids first, so we want to look - // at images with lower IDs than the previous. - $search_forward = $search_set; - $search_forward[] = "order=id_desc"; //Default order can be changed, so make sure we order high > low ID - if($last_id >= 0){ - $search_forward[] = "id<$last_id"; - } + $last_id = -1; + while (true) { + // make sure we don't look at the same images twice. + // search returns high-ids first, so we want to look + // at images with lower IDs than the previous. + $search_forward = $search_set; + $search_forward[] = "order=id_desc"; //Default order can be changed, so make sure we order high > low ID + if ($last_id >= 0) { + $search_forward[] = "id<$last_id"; + } - $images = Image::find_images(0, 100, $search_forward); - if(count($images) == 0) break; + $images = Image::find_images(0, 100, $search_forward); + if (count($images) == 0) { + break; + } - foreach($images as $image) { - // remove the search'ed tags - $before = array_map('strtolower', $image->get_tag_array()); - $after = array(); - foreach($before as $tag) { - if(!in_array($tag, $search_set)) { - $after[] = $tag; - } - } + foreach ($images as $image) { + // remove the search'ed tags + $before = array_map('strtolower', $image->get_tag_array()); + $after = []; + foreach ($before as $tag) { + if (!in_array($tag, $search_set)) { + $after[] = $tag; + } + } - // add the replace'd tags - foreach($replace_set as $tag) { - $after[] = $tag; - } + // add the replace'd tags + foreach ($replace_set as $tag) { + $after[] = $tag; + } - // replace'd tag may already exist in tag set, so remove dupes to avoid integrity constraint violations. - $after = array_unique($after); + // replace'd tag may already exist in tag set, so remove dupes to avoid integrity constraint violations. + $after = array_unique($after); - $image->set_tags($after); + $image->set_tags($after); - $last_id = $image->id; - } - } - } + $last_id = $image->id; + } + } + } - private function mass_source_edit(string $tags, string $source) { - $tags = Tag::explode($tags); + private function mass_source_edit(string $tags, string $source) + { + $tags = Tag::explode($tags); - $last_id = -1; - while(true) { - // make sure we don't look at the same images twice. - // search returns high-ids first, so we want to look - // at images with lower IDs than the previous. - $search_forward = $tags; - if($last_id >= 0) $search_forward[] = "id<$last_id"; + $last_id = -1; + while (true) { + // make sure we don't look at the same images twice. + // search returns high-ids first, so we want to look + // at images with lower IDs than the previous. + $search_forward = $tags; + if ($last_id >= 0) { + $search_forward[] = "id<$last_id"; + } - $images = Image::find_images(0, 100, $search_forward); - if(count($images) == 0) break; + $images = Image::find_images(0, 100, $search_forward); + if (count($images) == 0) { + break; + } - foreach($images as $image) { - $image->set_source($source); - $last_id = $image->id; - } - } - } + foreach ($images as $image) { + $image->set_source($source); + $last_id = $image->id; + } + } + } } - diff --git a/ext/tag_edit/test.php b/ext/tag_edit/test.php index 8099a702..ba36ebf7 100644 --- a/ext/tag_edit/test.php +++ b/ext/tag_edit/test.php @@ -1,84 +1,88 @@ log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pbx"); +class TagEditTest extends ShimmiePHPUnitTestCase +{ + public function testTagEdit() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pbx"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field("tag_edit__tags", "new"); - $this->click("Set"); - $this->assert_title("Image $image_id: new"); - $this->set_field("tag_edit__tags", ""); - $this->click("Set"); - $this->assert_title("Image $image_id: tagme"); - $this->log_out(); + $this->set_field("tag_edit__tags", "new"); + $this->click("Set"); + $this->assert_title("Image $image_id: new"); + $this->set_field("tag_edit__tags", ""); + $this->click("Set"); + $this->assert_title("Image $image_id: tagme"); + $this->log_out(); - $this->log_in_as_admin(); - $this->delete_image($image_id); - $this->log_out(); - } + $this->log_in_as_admin(); + $this->delete_image($image_id); + $this->log_out(); + } - public function testTagEdit_tooLong() { - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", str_repeat("a", 500)); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: tagme"); - } + public function testTagEdit_tooLong() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", str_repeat("a", 500)); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: tagme"); + } - public function testSourceEdit() { - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pbx"); + public function testSourceEdit() + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pbx"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field("tag_edit__source", "example.com"); - $this->click("Set"); - $this->click("example.com"); - $this->assert_title("Example Domain"); - $this->back(); + $this->set_field("tag_edit__source", "example.com"); + $this->click("Set"); + $this->click("example.com"); + $this->assert_title("Example Domain"); + $this->back(); - $this->set_field("tag_edit__source", "http://example.com"); - $this->click("Set"); - $this->click("example.com"); - $this->assert_title("Example Domain"); - $this->back(); + $this->set_field("tag_edit__source", "http://example.com"); + $this->click("Set"); + $this->click("example.com"); + $this->assert_title("Example Domain"); + $this->back(); - $this->log_out(); + $this->log_out(); - $this->log_in_as_admin(); - $this->delete_image($image_id); - $this->log_out(); - } + $this->log_in_as_admin(); + $this->delete_image($image_id); + $this->log_out(); + } - /* - * FIXME: Mass Tagger seems to be broken, and this test case always fails. - */ - public function testMassEdit() { - $this->markTestIncomplete(); + /* + * FIXME: Mass Tagger seems to be broken, and this test case always fails. + */ + public function testMassEdit() + { + $this->markTestIncomplete(); - $this->log_in_as_admin(); + $this->log_in_as_admin(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pbx"); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("admin"); - $this->assert_text("Mass Tag Edit"); - $this->set_field("search", "pbx"); - $this->set_field("replace", "pox"); - $this->click("Replace"); + $this->get_page("admin"); + $this->assert_text("Mass Tag Edit"); + $this->set_field("search", "pbx"); + $this->set_field("replace", "pox"); + $this->click("Replace"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pox"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pox"); - $this->delete_image($image_id); + $this->delete_image($image_id); - $this->log_out(); - } + $this->log_out(); + } } - diff --git a/ext/tag_edit/theme.php b/ext/tag_edit/theme.php index fc0f0d45..ee978e42 100644 --- a/ext/tag_edit/theme.php +++ b/ext/tag_edit/theme.php @@ -1,13 +1,15 @@ Search @@ -16,34 +18,36 @@ class TagEditTheme extends Themelet { "; - $page->add_block(new Block("Mass Tag Edit", $html)); - } + $page->add_block(new Block("Mass Tag Edit", $html)); + } - public function mss_html($terms): string { - $h_terms = html_escape($terms); - $html = make_form(make_link("tag_edit/mass_source_set"), "POST") . " + public function mss_html($terms): string + { + $h_terms = html_escape($terms); + $html = make_form(make_link("tag_edit/mass_source_set"), "POST") . " "; - return $html; - } + return $html; + } - public function get_tag_editor_html(Image $image): string { - global $user; + public function get_tag_editor_html(Image $image): string + { + global $user; - $tag_links = array(); - foreach($image->get_tag_array() as $tag) { - $h_tag = html_escape($tag); - $u_tag = url_escape($tag); - $h_link = make_link("post/list/$u_tag/1"); - $tag_links[] = "$h_tag"; - } - $h_tag_links = Tag::implode($tag_links); - $h_tags = html_escape($image->get_tag_list()); + $tag_links = []; + foreach ($image->get_tag_array() as $tag) { + $h_tag = html_escape($tag); + $u_tag = url_escape($tag); + $h_link = make_link("post/list/$u_tag/1"); + $tag_links[] = "$h_tag"; + } + $h_tag_links = Tag::implode($tag_links); + $h_tags = html_escape($image->get_tag_list()); - return " + return " Tags @@ -56,15 +60,16 @@ class TagEditTheme extends Themelet { "; - } + } - public function get_user_editor_html(Image $image): string { - global $user; - $h_owner = html_escape($image->get_owner()->name); - $h_av = $image->get_owner()->get_avatar_html(); - $h_date = autodate($image->posted); - $h_ip = $user->can("view_ip") ? " (".show_ip($image->owner_ip, "Image posted {$image->posted}").")" : ""; - return " + public function get_user_editor_html(Image $image): string + { + global $user; + $h_owner = html_escape($image->get_owner()->name); + $h_av = $image->get_owner()->get_avatar_html(); + $h_date = autodate($image->posted); + $h_ip = $user->can("view_ip") ? " (".show_ip($image->owner_ip, "Image posted {$image->posted}").")" : ""; + return " Uploader @@ -78,14 +83,15 @@ class TagEditTheme extends Themelet { $h_av "; - } + } - public function get_source_editor_html(Image $image): string { - global $user; - $h_source = html_escape($image->get_source()); - $f_source = $this->format_source($image->get_source()); - $style = "overflow: hidden; white-space: nowrap; max-width: 350px; text-overflow: ellipsis;"; - return " + public function get_source_editor_html(Image $image): string + { + global $user; + $h_source = html_escape($image->get_source()); + $f_source = $this->format_source($image->get_source()); + $style = "overflow: hidden; white-space: nowrap; max-width: 350px; text-overflow: ellipsis;"; + return " Source @@ -98,29 +104,31 @@ class TagEditTheme extends Themelet { "; - } + } - protected function format_source(string $source=null): string { - if(!empty($source)) { - if(!startsWith($source, "http://") && !startsWith($source, "https://")) { - $source = "http://" . $source; - } - $proto_domain = explode("://", $source); - $h_source = html_escape($proto_domain[1]); - $u_source = html_escape($source); - if(endsWith($h_source, "/")) { - $h_source = substr($h_source, 0, -1); - } - return "$h_source"; - } - return "Unknown"; - } + protected function format_source(string $source=null): string + { + if (!empty($source)) { + if (!startsWith($source, "http://") && !startsWith($source, "https://")) { + $source = "http://" . $source; + } + $proto_domain = explode("://", $source); + $h_source = html_escape($proto_domain[1]); + $u_source = html_escape($source); + if (endsWith($h_source, "/")) { + $h_source = substr($h_source, 0, -1); + } + return "$h_source"; + } + return "Unknown"; + } - public function get_lock_editor_html(Image $image): string { - global $user; - $b_locked = $image->is_locked() ? "Yes (Only admins may edit these details)" : "No"; - $h_locked = $image->is_locked() ? " checked" : ""; - return " + public function get_lock_editor_html(Image $image): string + { + global $user; + $b_locked = $image->is_locked() ? "Yes (Only admins may edit these details)" : "No"; + $h_locked = $image->is_locked() ? " checked" : ""; + return " Locked @@ -133,6 +141,5 @@ class TagEditTheme extends Themelet { "; - } + } } - diff --git a/ext/tag_editcloud/main.php b/ext/tag_editcloud/main.php index 9b8cab24..198c05cf 100644 --- a/ext/tag_editcloud/main.php +++ b/ext/tag_editcloud/main.php @@ -11,81 +11,87 @@ * usepref(todo2: port userpref) * theme junk */ -class TagEditCloud extends Extension { - public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { - global $config; +class TagEditCloud extends Extension +{ + public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) + { + global $config; - if(!$config->get_bool("tageditcloud_disable") && $this->can_tag($event->image)) { - $html = $this->build_tag_map($event->image); - if(!is_null($html)) { - $event->add_part($html, 40); - } - } - } + if (!$config->get_bool("tageditcloud_disable") && $this->can_tag($event->image)) { + $html = $this->build_tag_map($event->image); + if (!is_null($html)) { + $event->add_part($html, 40); + } + } + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_bool("tageditcloud_disable", false); - $config->set_default_bool("tageditcloud_usedfirst", true); - $config->set_default_string("tageditcloud_sort", 'a'); - $config->set_default_int("tageditcloud_minusage", 2); - $config->set_default_int("tageditcloud_defcount", 40); - $config->set_default_int("tageditcloud_maxcount", 4096); - $config->set_default_string("tageditcloud_ignoretags", 'tagme'); - } + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_bool("tageditcloud_disable", false); + $config->set_default_bool("tageditcloud_usedfirst", true); + $config->set_default_string("tageditcloud_sort", 'a'); + $config->set_default_int("tageditcloud_minusage", 2); + $config->set_default_int("tageditcloud_defcount", 40); + $config->set_default_int("tageditcloud_maxcount", 4096); + $config->set_default_string("tageditcloud_ignoretags", 'tagme'); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sort_by = array('Alphabetical'=>'a','Popularity'=>'p','Relevance'=>'r'); + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sort_by = ['Alphabetical'=>'a','Popularity'=>'p','Relevance'=>'r']; - $sb = new SetupBlock("Tag Edit Cloud"); - $sb->add_bool_option("tageditcloud_disable", "Disable Tag Selection Cloud: "); - $sb->add_choice_option("tageditcloud_sort", $sort_by, "
    Sort the tags by:"); - $sb->add_bool_option("tageditcloud_usedfirst","
    Always show used tags first: "); - $sb->add_label("
    Alpha sort:
    Only show tags used at least "); - $sb->add_int_option("tageditcloud_minusage"); - $sb->add_label(" times.
    Popularity/Relevance sort:
    Show "); - $sb->add_int_option("tageditcloud_defcount"); - $sb->add_label(" tags by default.
    Show a maximum of "); - $sb->add_int_option("tageditcloud_maxcount"); - $sb->add_label(" tags."); - $sb->add_label("
    Relevance sort:
    Ignore tags (space separated): "); - $sb->add_text_option("tageditcloud_ignoretags"); + $sb = new SetupBlock("Tag Edit Cloud"); + $sb->add_bool_option("tageditcloud_disable", "Disable Tag Selection Cloud: "); + $sb->add_choice_option("tageditcloud_sort", $sort_by, "
    Sort the tags by:"); + $sb->add_bool_option("tageditcloud_usedfirst", "
    Always show used tags first: "); + $sb->add_label("
    Alpha sort:
    Only show tags used at least "); + $sb->add_int_option("tageditcloud_minusage"); + $sb->add_label(" times.
    Popularity/Relevance sort:
    Show "); + $sb->add_int_option("tageditcloud_defcount"); + $sb->add_label(" tags by default.
    Show a maximum of "); + $sb->add_int_option("tageditcloud_maxcount"); + $sb->add_label(" tags."); + $sb->add_label("
    Relevance sort:
    Ignore tags (space separated): "); + $sb->add_text_option("tageditcloud_ignoretags"); - $event->panel->add_block($sb); - } + $event->panel->add_block($sb); + } - private function build_tag_map(Image $image): string { - global $database, $config; + private function build_tag_map(Image $image): string + { + global $database, $config; - $html = ""; - $cloud = ""; - $precloud = ""; - $postcloud = ""; + $html = ""; + $cloud = ""; + $precloud = ""; + $postcloud = ""; - $sort_method = $config->get_string("tageditcloud_sort"); - $tags_min = $config->get_int("tageditcloud_minusage"); - $used_first = $config->get_bool("tageditcloud_usedfirst"); - $max_count = $config->get_int("tageditcloud_maxcount"); - $def_count = $config->get_int("tageditcloud_defcount"); + $sort_method = $config->get_string("tageditcloud_sort"); + $tags_min = $config->get_int("tageditcloud_minusage"); + $used_first = $config->get_bool("tageditcloud_usedfirst"); + $max_count = $config->get_int("tageditcloud_maxcount"); + $def_count = $config->get_int("tageditcloud_defcount"); - $ignore_tags = Tag::explode($config->get_string("tageditcloud_ignoretags")); + $ignore_tags = Tag::explode($config->get_string("tageditcloud_ignoretags")); - if(ext_is_live("TagCategories")) { - $categories = $database->get_all("SELECT category, color FROM image_tag_categories"); - $cat_color = array(); - foreach($categories as $row) { - $cat_color[$row['category']] = $row['color']; - } - } + if (ext_is_live("TagCategories")) { + $categories = $database->get_all("SELECT category, color FROM image_tag_categories"); + $cat_color = []; + foreach ($categories as $row) { + $cat_color[$row['category']] = $row['color']; + } + } - switch($sort_method) { - case 'r': - $relevant_tags = array_diff($image->get_tag_array(),$ignore_tags); - if(count($relevant_tags) == 0) { - return null; - } - $relevant_tags = implode(",",array_map(array($database,"escape"),$relevant_tags)); - $tag_data = $database->get_all(" + switch ($sort_method) { + case 'r': + $relevant_tags = array_diff($image->get_tag_array(), $ignore_tags); + if (count($relevant_tags) == 0) { + return null; + } + $relevant_tags = implode(",", array_map([$database,"escape"], $relevant_tags)); + $tag_data = $database->get_all( + " SELECT t2.tag AS tag, COUNT(image_id) AS count, FLOOR(LN(LN(COUNT(image_id) - :tag_min1 + 1)+1)*150)/200 AS scaled FROM image_tags it1 JOIN image_tags it2 USING(image_id) @@ -95,82 +101,85 @@ class TagEditCloud extends Extension { GROUP BY t2.tag ORDER BY count DESC LIMIT :limit", - array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); - break; - case 'a': - case 'p': - default: - $order_by = $sort_method == 'a' ? "tag" : "count DESC"; - $tag_data = $database->get_all(" + ["tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count] + ); + break; + case 'a': + case 'p': + default: + $order_by = $sort_method == 'a' ? "tag" : "count DESC"; + $tag_data = $database->get_all( + " SELECT tag, FLOOR(LN(LN(count - :tag_min1 + 1)+1)*150)/200 AS scaled, count FROM tags WHERE count >= :tag_min2 ORDER BY $order_by LIMIT :limit", - array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); - break; - } + ["tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count] + ); + break; + } - $counter = 1; - foreach($tag_data as $row) { - $full_tag = $row['tag']; + $counter = 1; + foreach ($tag_data as $row) { + $full_tag = $row['tag']; - if(ext_is_live("TagCategories")){ - $tc = explode(':',$row['tag']); - if(isset($tc[1]) && isset($cat_color[$tc[0]])){ - $h_tag = html_escape($tc[1]); - $color = '; color:'.$cat_color[$tc[0]]; - } else { - $h_tag = html_escape($row['tag']); - $color = ''; - } - } else { - $h_tag = html_escape($row['tag']); - $color = ''; - } + if (ext_is_live("TagCategories")) { + $tc = explode(':', $row['tag']); + if (isset($tc[1]) && isset($cat_color[$tc[0]])) { + $h_tag = html_escape($tc[1]); + $color = '; color:'.$cat_color[$tc[0]]; + } else { + $h_tag = html_escape($row['tag']); + $color = ''; + } + } else { + $h_tag = html_escape($row['tag']); + $color = ''; + } - $size = sprintf("%.2f", max($row['scaled'],0.5)); - $js = html_escape('tageditcloud_toggle_tag(this,'.json_encode($full_tag).')'); //Ugly, but it works + $size = sprintf("%.2f", max($row['scaled'], 0.5)); + $js = html_escape('tageditcloud_toggle_tag(this,'.json_encode($full_tag).')'); //Ugly, but it works - if(array_search($row['tag'],$image->get_tag_array()) !== FALSE) { - if($used_first) { - $precloud .= " {$h_tag} \n"; - continue; - } else { - $entry = " {$h_tag} \n"; - } - } else { - $entry = " {$h_tag} \n"; - } + if (array_search($row['tag'], $image->get_tag_array()) !== false) { + if ($used_first) { + $precloud .= " {$h_tag} \n"; + continue; + } else { + $entry = " {$h_tag} \n"; + } + } else { + $entry = " {$h_tag} \n"; + } - if($counter++ <= $def_count) { - $cloud .= $entry; - } else { - $postcloud .= $entry; - } - } + if ($counter++ <= $def_count) { + $cloud .= $entry; + } else { + $postcloud .= $entry; + } + } - if($precloud != '') { - $html .= "
    {$precloud}
    "; - } + if ($precloud != '') { + $html .= "
    {$precloud}
    "; + } - if($postcloud != '') { - $postcloud = ""; - } + if ($postcloud != '') { + $postcloud = ""; + } - $html .= "
    {$cloud}{$postcloud}
    "; + $html .= "
    {$cloud}{$postcloud}
    "; - if($sort_method != 'a' && $counter > $def_count) { - $rem = $counter - $def_count; - $html .= "
    [show {$rem} more tags]"; - } + if ($sort_method != 'a' && $counter > $def_count) { + $rem = $counter - $def_count; + $html .= "
    [show {$rem} more tags]"; + } - return "
    {$html}
    "; // FIXME: stupidasallhell - } + return "
    {$html}
    "; // FIXME: stupidasallhell + } - private function can_tag(Image $image): bool { - global $user; - return ($user->can("edit_image_tag") && (!$image->is_locked() || $user->can("edit_image_lock"))); - } + private function can_tag(Image $image): bool + { + global $user; + return ($user->can("edit_image_tag") && (!$image->is_locked() || $user->can("edit_image_lock"))); + } } - diff --git a/ext/tag_history/main.php b/ext/tag_history/main.php index 8817dc79..ad73f7ad 100644 --- a/ext/tag_history/main.php +++ b/ext/tag_history/main.php @@ -5,89 +5,97 @@ * Description: Keep a record of tag changes, and allows you to revert changes. */ -class Tag_History extends Extension { - // in before tags are actually set, so that "get current tags" works - public function get_priority(): int {return 40;} +class Tag_History extends Extension +{ + // in before tags are actually set, so that "get current tags" works + public function get_priority(): int + { + return 40; + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int("history_limit", -1); + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int("history_limit", -1); - // shimmie is being installed so call install to create the table. - if($config->get_int("ext_tag_history_version") < 3) { - $this->install(); - } - } + // shimmie is being installed so call install to create the table. + if ($config->get_int("ext_tag_history_version") < 3) { + $this->install(); + } + } - public function onAdminBuilding(AdminBuildingEvent $event) { - $this->theme->display_admin_block(); - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + $this->theme->display_admin_block(); + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("tag_history/revert")) { - // this is a request to revert to a previous version of the tags - if($user->can("edit_image_tag")) { - if(isset($_POST['revert'])) { - $this->process_revert_request($_POST['revert']); - } - } - } - else if($event->page_matches("tag_history/bulk_revert")) { - if($user->can("bulk_edit_image_tag") && $user->check_auth_token()) { - $this->process_bulk_revert_request(); - } - } - else if($event->page_matches("tag_history/all")) { - $page_id = int_escape($event->get_arg(0)); - $this->theme->display_global_page($page, $this->get_global_tag_history($page_id), $page_id); - } - else if($event->page_matches("tag_history") && $event->count_args() == 1) { - // must be an attempt to view a tag history - $image_id = int_escape($event->get_arg(0)); - $this->theme->display_history_page($page, $image_id, $this->get_tag_history_from_id($image_id)); - } - } - - public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { - $event->add_part(" + if ($event->page_matches("tag_history/revert")) { + // this is a request to revert to a previous version of the tags + if ($user->can("edit_image_tag")) { + if (isset($_POST['revert'])) { + $this->process_revert_request($_POST['revert']); + } + } + } elseif ($event->page_matches("tag_history/bulk_revert")) { + if ($user->can("bulk_edit_image_tag") && $user->check_auth_token()) { + $this->process_bulk_revert_request(); + } + } elseif ($event->page_matches("tag_history/all")) { + $page_id = int_escape($event->get_arg(0)); + $this->theme->display_global_page($page, $this->get_global_tag_history($page_id), $page_id); + } elseif ($event->page_matches("tag_history") && $event->count_args() == 1) { + // must be an attempt to view a tag history + $image_id = int_escape($event->get_arg(0)); + $this->theme->display_history_page($page, $image_id, $this->get_tag_history_from_id($image_id)); + } + } + + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) + { + $event->add_part("
    ", 20); - } + } - /* - // disk space is cheaper than manually rebuilding history, - // so let's default to -1 and the user can go advanced if - // they /really/ want to - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Tag History"); - $sb->add_label("Limit to "); - $sb->add_int_option("history_limit"); - $sb->add_label(" entires per image"); - $sb->add_label("
    (-1 for unlimited)"); - $event->panel->add_block($sb); - } - */ + /* + // disk space is cheaper than manually rebuilding history, + // so let's default to -1 and the user can go advanced if + // they /really/ want to + public function onSetupBuilding(SetupBuildingEvent $event) { + $sb = new SetupBlock("Tag History"); + $sb->add_label("Limit to "); + $sb->add_int_option("history_limit"); + $sb->add_label(" entires per image"); + $sb->add_label("
    (-1 for unlimited)"); + $event->panel->add_block($sb); + } + */ - public function onTagSet(TagSetEvent $event) { - $this->add_tag_history($event->image, $event->tags); - } + public function onTagSet(TagSetEvent $event) + { + $this->add_tag_history($event->image, $event->tags); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->can("bulk_edit_image_tag")) { - $event->add_link("Tag Changes", make_link("tag_history/all/1")); - } - } - - protected function install() { - global $database, $config; + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->can("bulk_edit_image_tag")) { + $event->add_link("Tag Changes", make_link("tag_history/all/1")); + } + } + + protected function install() + { + global $database, $config; - if($config->get_int("ext_tag_history_version") < 1) { - $database->create_table("tag_histories", " + if ($config->get_int("ext_tag_history_version") < 1) { + $database->create_table("tag_histories", " id SCORE_AIPK, image_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -97,182 +105,185 @@ class Tag_History extends Extension { FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE "); - $database->execute("CREATE INDEX tag_histories_image_id_idx ON tag_histories(image_id)", array()); - $config->set_int("ext_tag_history_version", 3); - } - - if($config->get_int("ext_tag_history_version") == 1) { - $database->Execute("ALTER TABLE tag_histories ADD COLUMN user_id INTEGER NOT NULL"); - $database->Execute($database->scoreql_to_sql("ALTER TABLE tag_histories ADD COLUMN date_set SCORE_DATETIME NOT NULL")); - $config->set_int("ext_tag_history_version", 2); - } + $database->execute("CREATE INDEX tag_histories_image_id_idx ON tag_histories(image_id)", []); + $config->set_int("ext_tag_history_version", 3); + } + + if ($config->get_int("ext_tag_history_version") == 1) { + $database->Execute("ALTER TABLE tag_histories ADD COLUMN user_id INTEGER NOT NULL"); + $database->Execute($database->scoreql_to_sql("ALTER TABLE tag_histories ADD COLUMN date_set SCORE_DATETIME NOT NULL")); + $config->set_int("ext_tag_history_version", 2); + } - if($config->get_int("ext_tag_history_version") == 2) { - $database->Execute("ALTER TABLE tag_histories ADD COLUMN user_ip CHAR(15) NOT NULL"); - $config->set_int("ext_tag_history_version", 3); - } - } + if ($config->get_int("ext_tag_history_version") == 2) { + $database->Execute("ALTER TABLE tag_histories ADD COLUMN user_ip CHAR(15) NOT NULL"); + $config->set_int("ext_tag_history_version", 3); + } + } - /** - * This function is called when a revert request is received. - */ - private function process_revert_request(int $revert_id) { - global $page; + /** + * This function is called when a revert request is received. + */ + private function process_revert_request(int $revert_id) + { + global $page; - $revert_id = int_escape($revert_id); + $revert_id = int_escape($revert_id); - // check for the nothing case - if($revert_id < 1) { - $page->set_mode("redirect"); - $page->set_redirect(make_link()); - return; - } - - // lets get this revert id assuming it exists - $result = $this->get_tag_history_from_revert($revert_id); - - if(empty($result)) { - // there is no history entry with that id so either the image was deleted - // while the user was viewing the history, someone is playing with form - // variables or we have messed up in code somewhere. - /* FIXME: calling die() is probably not a good idea, we should throw an Exception */ - die("Error: No tag history with specified id was found."); - } - - // lets get the values out of the result - $stored_image_id = int_escape($result['image_id']); - $stored_tags = $result['tags']; + // check for the nothing case + if ($revert_id < 1) { + $page->set_mode("redirect"); + $page->set_redirect(make_link()); + return; + } + + // lets get this revert id assuming it exists + $result = $this->get_tag_history_from_revert($revert_id); + + if (empty($result)) { + // there is no history entry with that id so either the image was deleted + // while the user was viewing the history, someone is playing with form + // variables or we have messed up in code somewhere. + /* FIXME: calling die() is probably not a good idea, we should throw an Exception */ + die("Error: No tag history with specified id was found."); + } + + // lets get the values out of the result + $stored_image_id = int_escape($result['image_id']); + $stored_tags = $result['tags']; - $image = Image::by_id($stored_image_id); - if ( ! $image instanceof Image) { - throw new ImageDoesNotExist("Error: cannot find any image with the ID = ". $stored_image_id); - } + $image = Image::by_id($stored_image_id); + if (! $image instanceof Image) { + throw new ImageDoesNotExist("Error: cannot find any image with the ID = ". $stored_image_id); + } - log_debug("tag_history", 'Reverting tags of Image #'.$stored_image_id.' to ['.$stored_tags.']'); - // all should be ok so we can revert by firing the SetUserTags event. - send_event(new TagSetEvent($image, Tag::explode($stored_tags))); - - // all should be done now so redirect the user back to the image - $page->set_mode("redirect"); - $page->set_redirect(make_link('post/view/'.$stored_image_id)); - } + log_debug("tag_history", 'Reverting tags of Image #'.$stored_image_id.' to ['.$stored_tags.']'); + // all should be ok so we can revert by firing the SetUserTags event. + send_event(new TagSetEvent($image, Tag::explode($stored_tags))); + + // all should be done now so redirect the user back to the image + $page->set_mode("redirect"); + $page->set_redirect(make_link('post/view/'.$stored_image_id)); + } - protected function process_bulk_revert_request() { - if (isset($_POST['revert_name']) && !empty($_POST['revert_name'])) { - $revert_name = $_POST['revert_name']; - } - else { - $revert_name = null; - } + protected function process_bulk_revert_request() + { + if (isset($_POST['revert_name']) && !empty($_POST['revert_name'])) { + $revert_name = $_POST['revert_name']; + } else { + $revert_name = null; + } - if (isset($_POST['revert_ip']) && !empty($_POST['revert_ip'])) { - $revert_ip = filter_var($_POST['revert_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE); - - if ($revert_ip === false) { - // invalid ip given. - $this->theme->display_admin_block('Invalid IP'); - return; - } - } - else { - $revert_ip = null; - } - - if (isset($_POST['revert_date']) && !empty($_POST['revert_date'])) { - if (isValidDate($_POST['revert_date']) ){ - $revert_date = addslashes($_POST['revert_date']); // addslashes is really unnecessary since we just checked if valid, but better safe. - } - else { - $this->theme->display_admin_block('Invalid Date'); - return; - } - } - else { - $revert_date = null; - } - - set_time_limit(0); // reverting changes can take a long time, disable php's timelimit if possible. - - // Call the revert function. - $this->process_revert_all_changes($revert_name, $revert_ip, $revert_date); - // output results - $this->theme->display_revert_ip_results(); - } + if (isset($_POST['revert_ip']) && !empty($_POST['revert_ip'])) { + $revert_ip = filter_var($_POST['revert_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE); + + if ($revert_ip === false) { + // invalid ip given. + $this->theme->display_admin_block('Invalid IP'); + return; + } + } else { + $revert_ip = null; + } + + if (isset($_POST['revert_date']) && !empty($_POST['revert_date'])) { + if (isValidDate($_POST['revert_date'])) { + $revert_date = addslashes($_POST['revert_date']); // addslashes is really unnecessary since we just checked if valid, but better safe. + } else { + $this->theme->display_admin_block('Invalid Date'); + return; + } + } else { + $revert_date = null; + } + + set_time_limit(0); // reverting changes can take a long time, disable php's timelimit if possible. + + // Call the revert function. + $this->process_revert_all_changes($revert_name, $revert_ip, $revert_date); + // output results + $this->theme->display_revert_ip_results(); + } - public function get_tag_history_from_revert(int $revert_id): ?array { - global $database; - $row = $database->get_row(" + public function get_tag_history_from_revert(int $revert_id): ?array + { + global $database; + $row = $database->get_row(" SELECT tag_histories.*, users.name FROM tag_histories JOIN users ON tag_histories.user_id = users.id - WHERE tag_histories.id = ?", array($revert_id)); - return ($row ? $row : null); - } + WHERE tag_histories.id = ?", [$revert_id]); + return ($row ? $row : null); + } - public function get_tag_history_from_id(int $image_id): array { - global $database; - $row = $database->get_all(" + public function get_tag_history_from_id(int $image_id): array + { + global $database; + $row = $database->get_all( + " SELECT tag_histories.*, users.name FROM tag_histories JOIN users ON tag_histories.user_id = users.id WHERE image_id = ? ORDER BY tag_histories.id DESC", - array($image_id)); - return ($row ? $row : array()); - } + [$image_id] + ); + return ($row ? $row : []); + } - public function get_global_tag_history(int $page_id): array { - global $database; - $row = $database->get_all(" + public function get_global_tag_history(int $page_id): array + { + global $database; + $row = $database->get_all(" SELECT tag_histories.*, users.name FROM tag_histories JOIN users ON tag_histories.user_id = users.id ORDER BY tag_histories.id DESC LIMIT 100 OFFSET :offset - ", array("offset" => ($page_id-1)*100)); - return ($row ? $row : array()); - } - - /** - * This function attempts to revert all changes by a given IP within an (optional) timeframe. - */ - public function process_revert_all_changes(string $name, string $ip, string $date) { - global $database; - - $select_code = array(); - $select_args = array(); + ", ["offset" => ($page_id-1)*100]); + return ($row ? $row : []); + } + + /** + * This function attempts to revert all changes by a given IP within an (optional) timeframe. + */ + public function process_revert_all_changes(string $name, string $ip, string $date) + { + global $database; + + $select_code = []; + $select_args = []; - if(!is_null($name)) { - $duser = User::by_name($name); - if(is_null($duser)) { - $this->theme->add_status($name, "user not found"); - return; - } - else { - $select_code[] = 'user_id = ?'; - $select_args[] = $duser->id; - } - } + if (!is_null($name)) { + $duser = User::by_name($name); + if (is_null($duser)) { + $this->theme->add_status($name, "user not found"); + return; + } else { + $select_code[] = 'user_id = ?'; + $select_args[] = $duser->id; + } + } - if(!is_null($date)) { - $select_code[] = 'date_set >= ?'; - $select_args[] = $date; - } + if (!is_null($date)) { + $select_code[] = 'date_set >= ?'; + $select_args[] = $date; + } - if(!is_null($ip)) { - $select_code[] = 'user_ip = ?'; - $select_args[] = $ip; - } + if (!is_null($ip)) { + $select_code[] = 'user_ip = ?'; + $select_args[] = $ip; + } - if(count($select_code) == 0) { - log_error("tag_history", "Tried to mass revert without any conditions"); - return; - } + if (count($select_code) == 0) { + log_error("tag_history", "Tried to mass revert without any conditions"); + return; + } - log_info("tag_history", 'Attempting to revert edits where '.implode(" and ", $select_code)." (".implode(" / ", $select_args).")"); - - // Get all the images that the given IP has changed tags on (within the timeframe) that were last edited by the given IP - $result = $database->get_col(' + log_info("tag_history", 'Attempting to revert edits where '.implode(" and ", $select_code)." (".implode(" / ", $select_args).")"); + + // Get all the images that the given IP has changed tags on (within the timeframe) that were last edited by the given IP + $result = $database->get_col(' SELECT t1.image_id FROM tag_histories t1 LEFT JOIN tag_histories t2 ON (t1.image_id = t2.image_id AND t1.date_set < t2.date_set) @@ -280,109 +291,117 @@ class Tag_History extends Extension { AND t1.image_id IN ( select image_id from tag_histories where '.implode(" AND ", $select_code).') ORDER BY t1.image_id ', $select_args); - - foreach($result as $image_id) { - // Get the first tag history that was done before the given IP edit - $row = $database->get_row(' + + foreach ($result as $image_id) { + // Get the first tag history that was done before the given IP edit + $row = $database->get_row(' SELECT id, tags FROM tag_histories WHERE image_id='.$image_id.' AND NOT ('.implode(" AND ", $select_code).') ORDER BY date_set DESC LIMIT 1 ', $select_args); - - if (empty($row)) { - // we can not revert this image based on the date restriction. - // Output a message perhaps? - } - else { - $revert_id = $row['id']; - $result = $this->get_tag_history_from_revert($revert_id); - - if(empty($result)) { - // there is no history entry with that id so either the image was deleted - // while the user was viewing the history, or something messed up - /* calling die() is probably not a good idea, we should throw an Exception */ - die('Error: No tag history with specified id ('.$revert_id.') was found in the database.'."\n\n". - 'Perhaps the image was deleted while processing this request.'); - } - - // lets get the values out of the result - $stored_result_id = int_escape($result['id']); - $stored_image_id = int_escape($result['image_id']); - $stored_tags = $result['tags']; + + if (empty($row)) { + // we can not revert this image based on the date restriction. + // Output a message perhaps? + } else { + $revert_id = $row['id']; + $result = $this->get_tag_history_from_revert($revert_id); + + if (empty($result)) { + // there is no history entry with that id so either the image was deleted + // while the user was viewing the history, or something messed up + /* calling die() is probably not a good idea, we should throw an Exception */ + die('Error: No tag history with specified id ('.$revert_id.') was found in the database.'."\n\n". + 'Perhaps the image was deleted while processing this request.'); + } + + // lets get the values out of the result + $stored_result_id = int_escape($result['id']); + $stored_image_id = int_escape($result['image_id']); + $stored_tags = $result['tags']; - $image = Image::by_id($stored_image_id); - if ( ! $image instanceof Image) { - continue; - //throw new ImageDoesNotExist("Error: cannot find any image with the ID = ". $stored_image_id); - } + $image = Image::by_id($stored_image_id); + if (! $image instanceof Image) { + continue; + //throw new ImageDoesNotExist("Error: cannot find any image with the ID = ". $stored_image_id); + } - log_debug("tag_history", 'Reverting tags of Image #'.$stored_image_id.' to ['.$stored_tags.']'); - // all should be ok so we can revert by firing the SetTags event. - send_event(new TagSetEvent($image, Tag::explode($stored_tags))); - $this->theme->add_status('Reverted Change','Reverted Image #'.$image_id.' to Tag History #'.$stored_result_id.' ('.$row['tags'].')'); - } - } + log_debug("tag_history", 'Reverting tags of Image #'.$stored_image_id.' to ['.$stored_tags.']'); + // all should be ok so we can revert by firing the SetTags event. + send_event(new TagSetEvent($image, Tag::explode($stored_tags))); + $this->theme->add_status('Reverted Change', 'Reverted Image #'.$image_id.' to Tag History #'.$stored_result_id.' ('.$row['tags'].')'); + } + } - log_info("tag_history", 'Reverted '.count($result).' edits.'); - } + log_info("tag_history", 'Reverted '.count($result).' edits.'); + } - /** - * This function is called just before an images tag are changed. - * - * #param string[] $tags - */ - private function add_tag_history(Image $image, array $tags) { - global $database, $config, $user; + /** + * This function is called just before an images tag are changed. + * + * #param string[] $tags + */ + private function add_tag_history(Image $image, array $tags) + { + global $database, $config, $user; - $new_tags = Tag::implode($tags); - $old_tags = $image->get_tag_list(); - - if($new_tags == $old_tags) { return; } - - if(empty($old_tags)) { - /* no old tags, so we are probably adding the image for the first time */ - log_debug("tag_history", "adding new tag history: [$new_tags]", false, array("image_id" => $image->id)); - } - else { - log_debug("tag_history", "adding tag history: [$old_tags] -> [$new_tags]", false, array("image_id" => $image->id)); - } - - $allowed = $config->get_int("history_limit"); - if($allowed == 0) { return; } - - // if the image has no history, make one with the old tags - $entries = $database->get_one("SELECT COUNT(*) FROM tag_histories WHERE image_id = ?", array($image->id)); - if($entries == 0 && !empty($old_tags)) { - $database->execute(" + $new_tags = Tag::implode($tags); + $old_tags = $image->get_tag_list(); + + if ($new_tags == $old_tags) { + return; + } + + if (empty($old_tags)) { + /* no old tags, so we are probably adding the image for the first time */ + log_debug("tag_history", "adding new tag history: [$new_tags]", false, ["image_id" => $image->id]); + } else { + log_debug("tag_history", "adding tag history: [$old_tags] -> [$new_tags]", false, ["image_id" => $image->id]); + } + + $allowed = $config->get_int("history_limit"); + if ($allowed == 0) { + return; + } + + // if the image has no history, make one with the old tags + $entries = $database->get_one("SELECT COUNT(*) FROM tag_histories WHERE image_id = ?", [$image->id]); + if ($entries == 0 && !empty($old_tags)) { + $database->execute( + " INSERT INTO tag_histories(image_id, tags, user_id, user_ip, date_set) VALUES (?, ?, ?, ?, now())", - array($image->id, $old_tags, $config->get_int('anon_id'), '127.0.0.1')); - $entries++; - } + [$image->id, $old_tags, $config->get_int('anon_id'), '127.0.0.1'] + ); + $entries++; + } - // add a history entry - $database->execute(" + // add a history entry + $database->execute( + " INSERT INTO tag_histories(image_id, tags, user_id, user_ip, date_set) VALUES (?, ?, ?, ?, now())", - array($image->id, $new_tags, $user->id, $_SERVER['REMOTE_ADDR'])); - $entries++; - - // if needed remove oldest one - if($allowed == -1) { return; } - if($entries > $allowed) { - // TODO: Make these queries better - /* - MySQL does NOT allow you to modify the same table which you use in the SELECT part. - Which means that these will probably have to stay as TWO separate queries... - - http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html - http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause - */ - $min_id = $database->get_one("SELECT MIN(id) FROM tag_histories WHERE image_id = ?", array($image->id)); - $database->execute("DELETE FROM tag_histories WHERE id = ?", array($min_id)); - } - } + [$image->id, $new_tags, $user->id, $_SERVER['REMOTE_ADDR']] + ); + $entries++; + + // if needed remove oldest one + if ($allowed == -1) { + return; + } + if ($entries > $allowed) { + // TODO: Make these queries better + /* + MySQL does NOT allow you to modify the same table which you use in the SELECT part. + Which means that these will probably have to stay as TWO separate queries... + + http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html + http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause + */ + $min_id = $database->get_one("SELECT MIN(id) FROM tag_histories WHERE image_id = ?", [$image->id]); + $database->execute("DELETE FROM tag_histories WHERE id = ?", [$min_id]); + } + } } - diff --git a/ext/tag_history/test.php b/ext/tag_history/test.php index 4914be06..74182e40 100644 --- a/ext/tag_history/test.php +++ b/ext/tag_history/test.php @@ -1,24 +1,25 @@ log_in_as_admin(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $this->get_page("post/view/$image_id"); - $this->assert_title("Image $image_id: pbx"); +class TagHistoryTest extends ShimmiePHPUnitTestCase +{ + public function testTagHistory() + { + $this->log_in_as_admin(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $this->get_page("post/view/$image_id"); + $this->assert_title("Image $image_id: pbx"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - // FIXME - $this->set_field("tag_edit__tags", "new"); - $this->click("Set"); - $this->assert_title("Image $image_id: new"); - $this->click("View Tag History"); - $this->assert_text("new (Set by demo"); - $this->click("Revert To"); - $this->assert_title("Image $image_id: pbx"); + // FIXME + $this->set_field("tag_edit__tags", "new"); + $this->click("Set"); + $this->assert_title("Image $image_id: new"); + $this->click("View Tag History"); + $this->assert_text("new (Set by demo"); + $this->click("Revert To"); + $this->assert_title("Image $image_id: pbx"); - $this->get_page("tag_history/all/1"); - $this->assert_title("Global Tag History"); - } + $this->get_page("tag_history/all/1"); + $this->assert_title("Global Tag History"); + } } - diff --git a/ext/tag_history/theme.php b/ext/tag_history/theme.php index e1099e02..9d48abde 100644 --- a/ext/tag_history/theme.php +++ b/ext/tag_history/theme.php @@ -4,39 +4,40 @@ * Author: Bzchan , modified by jgen */ -class Tag_HistoryTheme extends Themelet { - private $messages = array(); +class Tag_HistoryTheme extends Themelet +{ + private $messages = []; - public function display_history_page(Page $page, int $image_id, array $history) { - global $user; - $start_string = " + public function display_history_page(Page $page, int $image_id, array $history) + { + global $user; + $start_string = "
    ".make_form(make_link("tag_history/revert"))."
      "; - $history_list = ""; - $n = 0; - foreach($history as $fields) - { - $n++; - $current_id = $fields['id']; - $current_tags = html_escape($fields['tags']); - $name = $fields['name']; - $date_set = autodate($fields['date_set']); - $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : ""; - $setter = "".html_escape($name)."$h_ip"; + $history_list = ""; + $n = 0; + foreach ($history as $fields) { + $n++; + $current_id = $fields['id']; + $current_tags = html_escape($fields['tags']); + $name = $fields['name']; + $date_set = autodate($fields['date_set']); + $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : ""; + $setter = "".html_escape($name)."$h_ip"; - $selected = ($n == 2) ? " checked" : ""; + $selected = ($n == 2) ? " checked" : ""; - $current_tags = Tag::explode($current_tags); - $taglinks = array(); - foreach($current_tags as $tag){ - $taglinks[] = "".$tag.""; - } - $current_tags = implode(' ', $taglinks); + $current_tags = Tag::explode($current_tags); + $taglinks = []; + foreach ($current_tags as $tag) { + $taglinks[] = "".$tag.""; + } + $current_tags = implode(' ', $taglinks); - $history_list .= " + $history_list .= "
    • "; - } + } - $end_string = " + $end_string = "
    "; - $history_html = $start_string . $history_list . $end_string; + $history_html = $start_string . $history_list . $end_string; - $page->set_title('Image '.$image_id.' Tag History'); - $page->set_heading('Tag History: '.$image_id); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Tag History", $history_html, "main", 10)); - } + $page->set_title('Image '.$image_id.' Tag History'); + $page->set_heading('Tag History: '.$image_id); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Tag History", $history_html, "main", 10)); + } - public function display_global_page(Page $page, array $history, int $page_number) { - $start_string = " + public function display_global_page(Page $page, array $history, int $page_number) + { + $start_string = "
    ".make_form(make_link("tag_history/revert"))."
      "; - $end_string = " + $end_string = "
    "; - global $user; - $history_list = ""; - foreach($history as $fields) - { - $current_id = $fields['id']; - $image_id = $fields['image_id']; - $current_tags = html_escape($fields['tags']); - $name = $fields['name']; - $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : ""; - $setter = "".html_escape($name)."$h_ip"; + global $user; + $history_list = ""; + foreach ($history as $fields) { + $current_id = $fields['id']; + $image_id = $fields['image_id']; + $current_tags = html_escape($fields['tags']); + $name = $fields['name']; + $h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : ""; + $setter = "".html_escape($name)."$h_ip"; - $history_list .= ' + $history_list .= '
  • '.$image_id.': '.$current_tags.' (Set by '.$setter.')
  • '; - } + } - $history_html = $start_string . $history_list . $end_string; - $page->set_title("Global Tag History"); - $page->set_heading("Global Tag History"); - $page->add_block(new Block("Tag History", $history_html, "main", 10)); + $history_html = $start_string . $history_list . $end_string; + $page->set_title("Global Tag History"); + $page->set_heading("Global Tag History"); + $page->add_block(new Block("Tag History", $history_html, "main", 10)); - $h_prev = ($page_number <= 1) ? "Prev" : - 'Prev'; - $h_index = "Index"; - $h_next = 'Next'; + $h_prev = ($page_number <= 1) ? "Prev" : + 'Prev'; + $h_index = "Index"; + $h_next = 'Next'; - $nav = $h_prev.' | '.$h_index.' | '.$h_next; - $page->add_block(new Block("Navigation", $nav, "left")); - } + $nav = $h_prev.' | '.$h_index.' | '.$h_next; + $page->add_block(new Block("Navigation", $nav, "left")); + } - /** - * Add a section to the admin page. - */ - public function display_admin_block(string $validation_msg='') { - global $page; - - if (!empty($validation_msg)) { - $validation_msg = '
    '. $validation_msg .''; - } - - $html = ' + /** + * Add a section to the admin page. + */ + public function display_admin_block(string $validation_msg='') + { + global $page; + + if (!empty($validation_msg)) { + $validation_msg = '
    '. $validation_msg .''; + } + + $html = ' Revert tag changes/edit by a specific IP address or username.
    You can restrict the time frame to revert these edits as well.
    (Date format: 2011-10-23) @@ -135,20 +137,21 @@ class Tag_HistoryTheme extends Themelet { "; - $page->add_block(new Block("Mass Tag Revert", $html)); - } - - /* - * Show a standard page for results to be put into - */ - public function display_revert_ip_results() { - global $page; - $html = implode($this->messages, "\n"); - $page->add_block(new Block("Bulk Revert Results", $html)); - } + $page->add_block(new Block("Mass Tag Revert", $html)); + } + + /* + * Show a standard page for results to be put into + */ + public function display_revert_ip_results() + { + global $page; + $html = implode($this->messages, "\n"); + $page->add_block(new Block("Bulk Revert Results", $html)); + } - public function add_status(string $title, string $body) { - $this->messages[] = '

    '. $title .'
    '. $body .'

    '; - } + public function add_status(string $title, string $body) + { + $this->messages[] = '

    '. $title .'
    '. $body .'

    '; + } } - diff --git a/ext/tag_list/main.php b/ext/tag_list/main.php index 2f763d91..85367686 100644 --- a/ext/tag_list/main.php +++ b/ext/tag_list/main.php @@ -6,213 +6,225 @@ * Description: Show the tags in various ways */ -class TagList extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int("tag_list_length", 15); - $config->set_default_int("popular_tag_list_length", 15); - $config->set_default_int("tags_min", 3); - $config->set_default_string("info_link", 'http://en.wikipedia.org/wiki/$tag'); - $config->set_default_string("tag_list_image_type", 'related'); - $config->set_default_string("tag_list_related_sort", 'alphabetical'); - $config->set_default_string("tag_list_popular_sort", 'tagcount'); - $config->set_default_bool("tag_list_pages", false); - } +class TagList extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int("tag_list_length", 15); + $config->set_default_int("popular_tag_list_length", 15); + $config->set_default_int("tags_min", 3); + $config->set_default_string("info_link", 'http://en.wikipedia.org/wiki/$tag'); + $config->set_default_string("tag_list_image_type", 'related'); + $config->set_default_string("tag_list_related_sort", 'alphabetical'); + $config->set_default_string("tag_list_popular_sort", 'tagcount'); + $config->set_default_bool("tag_list_pages", false); + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $database; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $database; - if($event->page_matches("tags")) { - $this->theme->set_navigation($this->build_navigation()); - switch($event->get_arg(0)) { - default: - case 'map': - $this->theme->set_heading("Tag Map"); - $this->theme->set_tag_list($this->build_tag_map()); - break; - case 'alphabetic': - $this->theme->set_heading("Alphabetic Tag List"); - $this->theme->set_tag_list($this->build_tag_alphabetic()); - break; - case 'popularity': - $this->theme->set_heading("Tag List by Popularity"); - $this->theme->set_tag_list($this->build_tag_popularity()); - break; - case 'categories': - $this->theme->set_heading("Popular Categories"); - $this->theme->set_tag_list($this->build_tag_list()); - break; - } - $this->theme->display_page($page); - } - else if($event->page_matches("api/internal/tag_list/complete")) { - if(!isset($_GET["s"]) || $_GET["s"] == "" || $_GET["s"] == "_") return; + if ($event->page_matches("tags")) { + $this->theme->set_navigation($this->build_navigation()); + switch ($event->get_arg(0)) { + default: + case 'map': + $this->theme->set_heading("Tag Map"); + $this->theme->set_tag_list($this->build_tag_map()); + break; + case 'alphabetic': + $this->theme->set_heading("Alphabetic Tag List"); + $this->theme->set_tag_list($this->build_tag_alphabetic()); + break; + case 'popularity': + $this->theme->set_heading("Tag List by Popularity"); + $this->theme->set_tag_list($this->build_tag_popularity()); + break; + case 'categories': + $this->theme->set_heading("Popular Categories"); + $this->theme->set_tag_list($this->build_tag_list()); + break; + } + $this->theme->display_page($page); + } elseif ($event->page_matches("api/internal/tag_list/complete")) { + if (!isset($_GET["s"]) || $_GET["s"] == "" || $_GET["s"] == "_") { + return; + } - //$limit = 0; - $cache_key = "autocomplete-" . strtolower($_GET["s"]); - $limitSQL = ""; - $SQLarr = array("search"=>$_GET["s"]."%"); - if(isset($_GET["limit"]) && $_GET["limit"] !== 0){ - $limitSQL = "LIMIT :limit"; - $SQLarr['limit'] = $_GET["limit"]; - $cache_key .= "-" . $_GET["limit"]; - } + //$limit = 0; + $cache_key = "autocomplete-" . strtolower($_GET["s"]); + $limitSQL = ""; + $SQLarr = ["search"=>$_GET["s"]."%"]; + if (isset($_GET["limit"]) && $_GET["limit"] !== 0) { + $limitSQL = "LIMIT :limit"; + $SQLarr['limit'] = $_GET["limit"]; + $cache_key .= "-" . $_GET["limit"]; + } - $res = null; - $database->cache->get($cache_key); - if(!$res) { - $res = $database->get_col($database->scoreql_to_sql(" + $res = null; + $database->cache->get($cache_key); + if (!$res) { + $res = $database->get_col($database->scoreql_to_sql(" SELECT tag FROM tags WHERE SCORE_STRNORM(tag) LIKE SCORE_STRNORM(:search) AND count > 0 $limitSQL "), $SQLarr); - $database->cache->set($cache_key, $res, 600); - } + $database->cache->set($cache_key, $res, 600); + } - $page->set_mode("data"); - $page->set_type("text/plain"); - $page->set_data(implode("\n", $res)); - } - } + $page->set_mode("data"); + $page->set_type("text/plain"); + $page->set_data(implode("\n", $res)); + } + } - public function onPostListBuilding(PostListBuildingEvent $event) { - global $config, $page; - if($config->get_int('tag_list_length') > 0) { - if(!empty($event->search_terms)) { - $this->add_refine_block($page, $event->search_terms); - } - else { - $this->add_popular_block($page); - } - } - } + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $config, $page; + if ($config->get_int('tag_list_length') > 0) { + if (!empty($event->search_terms)) { + $this->add_refine_block($page, $event->search_terms); + } else { + $this->add_popular_block($page); + } + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $config, $page; - if($config->get_int('tag_list_length') > 0) { - if($config->get_string('tag_list_image_type') == 'related') { - $this->add_related_block($page, $event->image); - } - else { - if(class_exists("TagCategories") and $config->get_bool('tag_categories_split_on_view')) { - $this->add_split_tags_block($page, $event->image); - } - else { - $this->add_tags_block($page, $event->image); - } - } - } - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $config, $page; + if ($config->get_int('tag_list_length') > 0) { + if ($config->get_string('tag_list_image_type') == 'related') { + $this->add_related_block($page, $event->image); + } else { + if (class_exists("TagCategories") and $config->get_bool('tag_categories_split_on_view')) { + $this->add_split_tags_block($page, $event->image); + } else { + $this->add_tags_block($page, $event->image); + } + } + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Tag Map Options"); - $sb->add_int_option("tags_min", "Only show tags used at least "); $sb->add_label(" times"); - $sb->add_bool_option("tag_list_pages", "
    Paged tag lists: "); - $event->panel->add_block($sb); + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Tag Map Options"); + $sb->add_int_option("tags_min", "Only show tags used at least "); + $sb->add_label(" times"); + $sb->add_bool_option("tag_list_pages", "
    Paged tag lists: "); + $event->panel->add_block($sb); - $sb = new SetupBlock("Popular / Related Tag List"); - $sb->add_int_option("tag_list_length", "Show top "); $sb->add_label(" related tags"); - $sb->add_int_option("popular_tag_list_length", "
    Show top "); $sb->add_label(" popular tags"); - $sb->add_text_option("info_link", "
    Tag info link: "); - $sb->add_choice_option("tag_list_image_type", array( - "Image's tags only" => "tags", - "Show related" => "related" - ), "
    Image tag list: "); - $sb->add_choice_option("tag_list_related_sort", array( - "Tag Count" => "tagcount", - "Alphabetical" => "alphabetical" - ), "
    Sort related list by: "); - $sb->add_choice_option("tag_list_popular_sort", array( - "Tag Count" => "tagcount", - "Alphabetical" => "alphabetical" - ), "
    Sort popular list by: "); - $sb->add_bool_option("tag_list_numbers", "
    Show tag counts: "); - $event->panel->add_block($sb); - } -// }}} -// misc {{{ - private function tag_link(string $tag): string { - $u_tag = url_escape($tag); - return make_link("post/list/$u_tag/1"); - } + $sb = new SetupBlock("Popular / Related Tag List"); + $sb->add_int_option("tag_list_length", "Show top "); + $sb->add_label(" related tags"); + $sb->add_int_option("popular_tag_list_length", "
    Show top "); + $sb->add_label(" popular tags"); + $sb->add_text_option("info_link", "
    Tag info link: "); + $sb->add_choice_option("tag_list_image_type", [ + "Image's tags only" => "tags", + "Show related" => "related" + ], "
    Image tag list: "); + $sb->add_choice_option("tag_list_related_sort", [ + "Tag Count" => "tagcount", + "Alphabetical" => "alphabetical" + ], "
    Sort related list by: "); + $sb->add_choice_option("tag_list_popular_sort", [ + "Tag Count" => "tagcount", + "Alphabetical" => "alphabetical" + ], "
    Sort popular list by: "); + $sb->add_bool_option("tag_list_numbers", "
    Show tag counts: "); + $event->panel->add_block($sb); + } + // }}} + // misc {{{ + private function tag_link(string $tag): string + { + $u_tag = url_escape($tag); + return make_link("post/list/$u_tag/1"); + } - /** - * Get the minimum number of times a tag needs to be used - * in order to be considered in the tag list. - */ - private function get_tags_min(): int { - if(isset($_GET['mincount'])) { - return int_escape($_GET['mincount']); - } - else { - global $config; - return $config->get_int('tags_min'); // get the default. - } - } + /** + * Get the minimum number of times a tag needs to be used + * in order to be considered in the tag list. + */ + private function get_tags_min(): int + { + if (isset($_GET['mincount'])) { + return int_escape($_GET['mincount']); + } else { + global $config; + return $config->get_int('tags_min'); // get the default. + } + } - private function get_starts_with(): string { - global $config; - if(isset($_GET['starts_with'])) { - return $_GET['starts_with'] . "%"; - } - else { - if($config->get_bool("tag_list_pages")) { - return "a%"; - } - else { - return "%"; - } - } - } + private function get_starts_with(): string + { + global $config; + if (isset($_GET['starts_with'])) { + return $_GET['starts_with'] . "%"; + } else { + if ($config->get_bool("tag_list_pages")) { + return "a%"; + } else { + return "%"; + } + } + } - private function build_az(): string { - global $database; + private function build_az(): string + { + global $database; - $tags_min = $this->get_tags_min(); + $tags_min = $this->get_tags_min(); - $tag_data = $database->get_col($database->scoreql_to_sql(" + $tag_data = $database->get_col($database->scoreql_to_sql(" SELECT DISTINCT SCORE_STRNORM(substr(tag, 1, 1)) FROM tags WHERE count >= :tags_min ORDER BY SCORE_STRNORM(substr(tag, 1, 1)) - "), array("tags_min"=>$tags_min)); + "), ["tags_min"=>$tags_min]); - $html = ""; - foreach($tag_data as $a) { - $html .= " $a"; - } - $html .= "\n


    "; + $html = ""; + foreach ($tag_data as $a) { + $html .= " $a"; + } + $html .= "\n


    "; - return $html; - } -// }}} -// maps {{{ + return $html; + } + // }}} + // maps {{{ - private function build_navigation(): string { - $h_index = "Index"; - $h_map = "Map"; - $h_alphabetic = "Alphabetic"; - $h_popularity = "Popularity"; - $h_cats = "Categories"; - $h_all = "Show All"; - return "$h_index
     
    $h_map
    $h_alphabetic
    $h_popularity
    $h_cats
     
    $h_all"; - } + private function build_navigation(): string + { + $h_index = "Index"; + $h_map = "Map"; + $h_alphabetic = "Alphabetic"; + $h_popularity = "Popularity"; + $h_cats = "Categories"; + $h_all = "Show All"; + return "$h_index
     
    $h_map
    $h_alphabetic
    $h_popularity
    $h_cats
     
    $h_all"; + } - private function build_tag_map(): string { - global $config, $database; + private function build_tag_map(): string + { + global $config, $database; - $tags_min = $this->get_tags_min(); - $starts_with = $this->get_starts_with(); - - // check if we have a cached version - $cache_key = warehouse_path("cache/tag_cloud", md5("tc" . $tags_min . $starts_with)); - if(file_exists($cache_key)) {return file_get_contents($cache_key);} + $tags_min = $this->get_tags_min(); + $starts_with = $this->get_starts_with(); + + // check if we have a cached version + $cache_key = warehouse_path("cache/tag_cloud", md5("tc" . $tags_min . $starts_with)); + if (file_exists($cache_key)) { + return file_get_contents($cache_key); + } - // SHIT: PDO/pgsql has problems using the same named param twice -_-;; - $tag_data = $database->get_all($database->scoreql_to_sql(" + // SHIT: PDO/pgsql has problems using the same named param twice -_-;; + $tag_data = $database->get_all($database->scoreql_to_sql(" SELECT tag, FLOOR(LOG(2.7, LOG(2.7, count - :tags_min2 + 1)+1)*1.5*100)/100 AS scaled @@ -220,149 +232,177 @@ class TagList extends Extension { WHERE count >= :tags_min AND tag SCORE_ILIKE :starts_with ORDER BY SCORE_STRNORM(tag) - "), array("tags_min"=>$tags_min, "tags_min2"=>$tags_min, "starts_with"=>$starts_with)); + "), ["tags_min"=>$tags_min, "tags_min2"=>$tags_min, "starts_with"=>$starts_with]); - $html = ""; - if($config->get_bool("tag_list_pages")) $html .= $this->build_az(); - foreach($tag_data as $row) { - $h_tag = html_escape($row['tag']); - $size = sprintf("%.2f", (float)$row['scaled']); - $link = $this->tag_link($row['tag']); - if($size<0.5) $size = 0.5; - $h_tag_no_underscores = str_replace("_", " ", $h_tag); - $html .= " $h_tag_no_underscores \n"; - } + $html = ""; + if ($config->get_bool("tag_list_pages")) { + $html .= $this->build_az(); + } + foreach ($tag_data as $row) { + $h_tag = html_escape($row['tag']); + $size = sprintf("%.2f", (float)$row['scaled']); + $link = $this->tag_link($row['tag']); + if ($size<0.5) { + $size = 0.5; + } + $h_tag_no_underscores = str_replace("_", " ", $h_tag); + $html .= " $h_tag_no_underscores \n"; + } - if(SPEED_HAX) {file_put_contents($cache_key, $html);} + if (SPEED_HAX) { + file_put_contents($cache_key, $html); + } - return $html; - } + return $html; + } - private function build_tag_alphabetic(): string { - global $config, $database; + private function build_tag_alphabetic(): string + { + global $config, $database; - $tags_min = $this->get_tags_min(); - $starts_with = $this->get_starts_with(); - - // check if we have a cached version - $cache_key = warehouse_path("cache/tag_alpha", md5("ta" . $tags_min . $starts_with)); - if(file_exists($cache_key)) {return file_get_contents($cache_key);} + $tags_min = $this->get_tags_min(); + $starts_with = $this->get_starts_with(); + + // check if we have a cached version + $cache_key = warehouse_path("cache/tag_alpha", md5("ta" . $tags_min . $starts_with)); + if (file_exists($cache_key)) { + return file_get_contents($cache_key); + } - $tag_data = $database->get_pairs($database->scoreql_to_sql(" + $tag_data = $database->get_pairs($database->scoreql_to_sql(" SELECT tag, count FROM tags WHERE count >= :tags_min AND tag SCORE_ILIKE :starts_with ORDER BY SCORE_STRNORM(tag) - "), array("tags_min"=>$tags_min, "starts_with"=>$starts_with)); + "), ["tags_min"=>$tags_min, "starts_with"=>$starts_with]); - $html = ""; - if($config->get_bool("tag_list_pages")) $html .= $this->build_az(); - - /* - strtolower() vs. mb_strtolower() - ( See http://www.php.net/manual/en/function.mb-strtolower.php for more info ) - - PHP5's strtolower function does not support Unicode (UTF-8) properly, so - you have to use another function, mb_strtolower, to handle UTF-8 strings. - - What's worse is that mb_strtolower is horribly SLOW. - - It would probably be better to have a config option for the Tag List that - would allow you to specify if there are UTF-8 tags. - - */ - mb_internal_encoding('UTF-8'); - - $lastLetter = ""; - # postres utf8 string sort ignores punctuation, so we get "aza, a-zb, azc" - # which breaks down into "az, a-, az" :( - ksort($tag_data, SORT_STRING | SORT_FLAG_CASE); - foreach($tag_data as $tag => $count) { - if($lastLetter != mb_strtolower(substr($tag, 0, count($starts_with)+1))) { - $lastLetter = mb_strtolower(substr($tag, 0, count($starts_with)+1)); - $h_lastLetter = html_escape($lastLetter); - $html .= "

    $h_lastLetter
    "; - } - $link = $this->tag_link($tag); - $h_tag = html_escape($tag); - $html .= "$h_tag ($count)\n"; - } + $html = ""; + if ($config->get_bool("tag_list_pages")) { + $html .= $this->build_az(); + } + + /* + strtolower() vs. mb_strtolower() + ( See http://www.php.net/manual/en/function.mb-strtolower.php for more info ) - if(SPEED_HAX) {file_put_contents($cache_key, $html);} + PHP5's strtolower function does not support Unicode (UTF-8) properly, so + you have to use another function, mb_strtolower, to handle UTF-8 strings. - return $html; - } + What's worse is that mb_strtolower is horribly SLOW. - private function build_tag_popularity(): string { - global $database; + It would probably be better to have a config option for the Tag List that + would allow you to specify if there are UTF-8 tags. - $tags_min = $this->get_tags_min(); - - // Make sure that the value of $tags_min is at least 1. - // Otherwise the database will complain if you try to do: LOG(0) - if ($tags_min < 1){ $tags_min = 1; } - - // check if we have a cached version - $cache_key = warehouse_path("cache/tag_popul", md5("tp" . $tags_min)); - if(file_exists($cache_key)) {return file_get_contents($cache_key);} + */ + mb_internal_encoding('UTF-8'); + + $lastLetter = ""; + # postres utf8 string sort ignores punctuation, so we get "aza, a-zb, azc" + # which breaks down into "az, a-, az" :( + ksort($tag_data, SORT_STRING | SORT_FLAG_CASE); + foreach ($tag_data as $tag => $count) { + if ($lastLetter != mb_strtolower(substr($tag, 0, count($starts_with)+1))) { + $lastLetter = mb_strtolower(substr($tag, 0, count($starts_with)+1)); + $h_lastLetter = html_escape($lastLetter); + $html .= "

    $h_lastLetter
    "; + } + $link = $this->tag_link($tag); + $h_tag = html_escape($tag); + $html .= "$h_tag ($count)\n"; + } - $tag_data = $database->get_all(" + if (SPEED_HAX) { + file_put_contents($cache_key, $html); + } + + return $html; + } + + private function build_tag_popularity(): string + { + global $database; + + $tags_min = $this->get_tags_min(); + + // Make sure that the value of $tags_min is at least 1. + // Otherwise the database will complain if you try to do: LOG(0) + if ($tags_min < 1) { + $tags_min = 1; + } + + // check if we have a cached version + $cache_key = warehouse_path("cache/tag_popul", md5("tp" . $tags_min)); + if (file_exists($cache_key)) { + return file_get_contents($cache_key); + } + + $tag_data = $database->get_all(" SELECT tag, count, FLOOR(LOG(count)) AS scaled FROM tags WHERE count >= :tags_min ORDER BY count DESC, tag ASC - ", array("tags_min"=>$tags_min)); + ", ["tags_min"=>$tags_min]); - $html = "Results grouped by log10(n)"; - $lastLog = ""; - foreach($tag_data as $row) { - $h_tag = html_escape($row['tag']); - $count = $row['count']; - $scaled = $row['scaled']; - if($lastLog != $scaled) { - $lastLog = $scaled; - $html .= "

    $lastLog
    "; - } - $link = $this->tag_link($row['tag']); - $html .= "$h_tag ($count)\n"; - } + $html = "Results grouped by log10(n)"; + $lastLog = ""; + foreach ($tag_data as $row) { + $h_tag = html_escape($row['tag']); + $count = $row['count']; + $scaled = $row['scaled']; + if ($lastLog != $scaled) { + $lastLog = $scaled; + $html .= "

    $lastLog
    "; + } + $link = $this->tag_link($row['tag']); + $html .= "$h_tag ($count)\n"; + } - if(SPEED_HAX) {file_put_contents($cache_key, $html);} + if (SPEED_HAX) { + file_put_contents($cache_key, $html); + } - return $html; - } + return $html; + } - private function build_tag_list(): string { - global $database; + private function build_tag_list(): string + { + global $database; - //$tags_min = $this->get_tags_min(); - $tag_data = $database->get_all("SELECT tag,count FROM tags ORDER BY count DESC, tag ASC LIMIT 9"); + //$tags_min = $this->get_tags_min(); + $tag_data = $database->get_all("SELECT tag,count FROM tags ORDER BY count DESC, tag ASC LIMIT 9"); - $html = ""; - $n = 0; - foreach($tag_data as $row) { - if($n%3==0) $html .= ""; - $h_tag = html_escape($row['tag']); - $link = $this->tag_link($row['tag']); - $image = Image::by_random(array($row['tag'])); - if(is_null($image)) continue; // one of the popular tags has no images - $thumb = $image->get_thumb_link(); - $tsize = get_thumbnail_size($image->width, $image->height); - $html .= "\n"; - if($n%3==2) $html .= ""; - $n++; - } - $html .= "

    $h_tag
    "; + $html = ""; + $n = 0; + foreach ($tag_data as $row) { + if ($n%3==0) { + $html .= ""; + } + $h_tag = html_escape($row['tag']); + $link = $this->tag_link($row['tag']); + $image = Image::by_random([$row['tag']]); + if (is_null($image)) { + continue; + } // one of the popular tags has no images + $thumb = $image->get_thumb_link(); + $tsize = get_thumbnail_size($image->width, $image->height); + $html .= "\n"; + if ($n%3==2) { + $html .= ""; + } + $n++; + } + $html .= "

    $h_tag
    "; - return $html; - } -// }}} -// blocks {{{ - private function add_related_block(Page $page, Image $image) { - global $database, $config; + return $html; + } + // }}} + // blocks {{{ + private function add_related_block(Page $page, Image $image) + { + global $database, $config; - $query = " + $query = " SELECT t3.tag AS tag, t3.count AS calc_count, it3.tag_id FROM image_tags AS it1, @@ -382,105 +422,115 @@ class TagList extends Extension { ORDER BY calc_count DESC LIMIT :tag_list_length "; - $args = array("image_id"=>$image->id, "tag_list_length"=>$config->get_int('tag_list_length')); + $args = ["image_id"=>$image->id, "tag_list_length"=>$config->get_int('tag_list_length')]; - $tags = $database->get_all($query, $args); - if(count($tags) > 0) { - $this->theme->display_related_block($page, $tags); - } - } + $tags = $database->get_all($query, $args); + if (count($tags) > 0) { + $this->theme->display_related_block($page, $tags); + } + } - private function add_split_tags_block(Page $page, Image $image) { - global $database; + private function add_split_tags_block(Page $page, Image $image) + { + global $database; - $query = " + $query = " SELECT tags.tag, tags.count as calc_count FROM tags, image_tags WHERE tags.id = image_tags.tag_id AND image_tags.image_id = :image_id ORDER BY calc_count DESC "; - $args = array("image_id"=>$image->id); + $args = ["image_id"=>$image->id]; - $tags = $database->get_all($query, $args); - if(count($tags) > 0) { - $this->theme->display_split_related_block($page, $tags); - } - } + $tags = $database->get_all($query, $args); + if (count($tags) > 0) { + $this->theme->display_split_related_block($page, $tags); + } + } - private function add_tags_block(Page $page, Image $image) { - global $database; + private function add_tags_block(Page $page, Image $image) + { + global $database; - $query = " + $query = " SELECT tags.tag, tags.count as calc_count FROM tags, image_tags WHERE tags.id = image_tags.tag_id AND image_tags.image_id = :image_id ORDER BY calc_count DESC "; - $args = array("image_id"=>$image->id); + $args = ["image_id"=>$image->id]; - $tags = $database->get_all($query, $args); - if(count($tags) > 0) { - $this->theme->display_related_block($page, $tags); - } - } + $tags = $database->get_all($query, $args); + if (count($tags) > 0) { + $this->theme->display_related_block($page, $tags); + } + } - private function add_popular_block(Page $page) { - global $database, $config; + private function add_popular_block(Page $page) + { + global $database, $config; - $tags = $database->cache->get("popular_tags"); - if(empty($tags)) { - $query = " + $tags = $database->cache->get("popular_tags"); + if (empty($tags)) { + $query = " SELECT tag, count as calc_count FROM tags WHERE count > 0 ORDER BY count DESC LIMIT :popular_tag_list_length "; - $args = array("popular_tag_list_length"=>$config->get_int('popular_tag_list_length')); + $args = ["popular_tag_list_length"=>$config->get_int('popular_tag_list_length')]; - $tags = $database->get_all($query, $args); - $database->cache->set("popular_tags", $tags, 600); - } - if(count($tags) > 0) { - $this->theme->display_popular_block($page, $tags); - } - } + $tags = $database->get_all($query, $args); + $database->cache->set("popular_tags", $tags, 600); + } + if (count($tags) > 0) { + $this->theme->display_popular_block($page, $tags); + } + } - /** - * #param string[] $search - */ - private function add_refine_block(Page $page, array $search) { - global $database, $config; + /** + * #param string[] $search + */ + private function add_refine_block(Page $page, array $search) + { + global $database, $config; - if(count($search) > 5) return; + if (count($search) > 5) { + return; + } - $wild_tags = $search; - $str_search = Tag::implode($search); - $related_tags = $database->cache->get("related_tags:$str_search"); + $wild_tags = $search; + $str_search = Tag::implode($search); + $related_tags = $database->cache->get("related_tags:$str_search"); - if(empty($related_tags)) { - // $search_tags = array(); + if (empty($related_tags)) { + // $search_tags = array(); - $tag_id_array = array(); - $tags_ok = true; - foreach($wild_tags as $tag) { - $tag = str_replace("*", "%", $tag); - $tag = str_replace("?", "_", $tag); - $tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag AND count < 25000", array("tag"=>$tag)); - // $search_tags = array_merge($search_tags, - // $database->get_col("SELECT tag FROM tags WHERE tag LIKE :tag", array("tag"=>$tag))); - $tag_id_array = array_merge($tag_id_array, $tag_ids); - $tags_ok = count($tag_ids) > 0; - if(!$tags_ok) break; - } - $tag_id_list = join(', ', $tag_id_array); + $tag_id_array = []; + $tags_ok = true; + foreach ($wild_tags as $tag) { + $tag = str_replace("*", "%", $tag); + $tag = str_replace("?", "_", $tag); + $tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag AND count < 25000", ["tag"=>$tag]); + // $search_tags = array_merge($search_tags, + // $database->get_col("SELECT tag FROM tags WHERE tag LIKE :tag", array("tag"=>$tag))); + $tag_id_array = array_merge($tag_id_array, $tag_ids); + $tags_ok = count($tag_ids) > 0; + if (!$tags_ok) { + break; + } + } + $tag_id_list = join(', ', $tag_id_array); - if(count($tag_id_array) > 5) return; + if (count($tag_id_array) > 5) { + return; + } - if($tags_ok) { - $query = " + if ($tags_ok) { + $query = " SELECT t2.tag AS tag, COUNT(it2.image_id) AS calc_count FROM image_tags AS it1, @@ -496,17 +546,16 @@ class TagList extends Extension { ORDER BY calc_count DESC LIMIT :limit "; - $args = array("limit"=>$config->get_int('tag_list_length')); + $args = ["limit"=>$config->get_int('tag_list_length')]; - $related_tags = $database->get_all($query, $args); - $database->cache->set("related_tags:$str_search", $related_tags, 60*60); - } - } + $related_tags = $database->get_all($query, $args); + $database->cache->set("related_tags:$str_search", $related_tags, 60*60); + } + } - if(!empty($related_tags)) { - $this->theme->display_refine_block($page, $related_tags, $wild_tags); - } - } -// }}} + if (!empty($related_tags)) { + $this->theme->display_refine_block($page, $related_tags, $wild_tags); + } + } + // }}} } - diff --git a/ext/tag_list/test.php b/ext/tag_list/test.php index 7fe82e72..8f56f76e 100644 --- a/ext/tag_list/test.php +++ b/ext/tag_list/test.php @@ -1,36 +1,39 @@ get_page('tags/map'); - $this->assert_title('Tag List'); + public function testTagList() + { + $this->get_page('tags/map'); + $this->assert_title('Tag List'); - $this->get_page('tags/alphabetic'); - $this->assert_title('Tag List'); + $this->get_page('tags/alphabetic'); + $this->assert_title('Tag List'); - $this->get_page('tags/popularity'); - $this->assert_title('Tag List'); + $this->get_page('tags/popularity'); + $this->assert_title('Tag List'); - $this->get_page('tags/categories'); - $this->assert_title('Tag List'); + $this->get_page('tags/categories'); + $this->assert_title('Tag List'); - # FIXME: test that these show the right stuff - } + # FIXME: test that these show the right stuff + } - public function testMinCount() { - foreach($this->pages as $page) { - $this->get_page("tags/$page?mincount=999999"); - $this->assert_title("Tag List"); + public function testMinCount() + { + foreach ($this->pages as $page) { + $this->get_page("tags/$page?mincount=999999"); + $this->assert_title("Tag List"); - $this->get_page("tags/$page?mincount=1"); - $this->assert_title("Tag List"); + $this->get_page("tags/$page?mincount=1"); + $this->assert_title("Tag List"); - $this->get_page("tags/$page?mincount=0"); - $this->assert_title("Tag List"); + $this->get_page("tags/$page?mincount=0"); + $this->assert_title("Tag List"); - $this->get_page("tags/$page?mincount=-1"); - $this->assert_title("Tag List"); - } - } + $this->get_page("tags/$page?mincount=-1"); + $this->assert_title("Tag List"); + } + } } diff --git a/ext/tag_list/theme.php b/ext/tag_list/theme.php index 9496262a..b162076f 100644 --- a/ext/tag_list/theme.php +++ b/ext/tag_list/theme.php @@ -1,288 +1,311 @@ heading = $text; - } + public function set_heading(string $text) + { + $this->heading = $text; + } - public function set_tag_list(string $list) { - $this->list = $list; - } + public function set_tag_list(string $list) + { + $this->list = $list; + } - public function set_navigation(string $nav) { - $this->navigation = $nav; - } + public function set_navigation(string $nav) + { + $this->navigation = $nav; + } - public function display_page(Page $page) { - $page->set_title("Tag List"); - $page->set_heading($this->heading); - $page->add_block(new Block("Tags", $this->list)); - $page->add_block(new Block("Navigation", $this->navigation, "left", 0)); - } + public function display_page(Page $page) + { + $page->set_title("Tag List"); + $page->set_heading($this->heading); + $page->add_block(new Block("Tags", $this->list)); + $page->add_block(new Block("Navigation", $this->navigation, "left", 0)); + } - // ======================================================================= + // ======================================================================= - protected function get_tag_list_preamble() { - global $config; + protected function get_tag_list_preamble() + { + global $config; - $tag_info_link_is_visible = !is_null($config->get_string('info_link')); - $tag_count_is_visible = $config->get_bool("tag_list_numbers"); + $tag_info_link_is_visible = !is_null($config->get_string('info_link')); + $tag_count_is_visible = $config->get_bool("tag_list_numbers"); - return ' + return ' ' . - ($tag_info_link_is_visible ? '' : '') . - ('') . - ($tag_count_is_visible ? '' : '') . ' + ($tag_info_link_is_visible ? '' : '') . + ('') . + ($tag_count_is_visible ? '' : '') . ' ' . - ($tag_info_link_is_visible ? '' : '') . - ('') . - ($tag_count_is_visible ? '' : '') . ' + ($tag_info_link_is_visible ? '' : '') . + ('') . + ($tag_count_is_visible ? '' : '') . ' '; - } + } - /* - * $tag_infos = array( - * array('tag' => $tag, 'count' => $number_of_uses), - * ... - * ) - */ - public function display_split_related_block(Page $page, $tag_infos) { - global $config; + /* + * $tag_infos = array( + * array('tag' => $tag, 'count' => $number_of_uses), + * ... + * ) + */ + public function display_split_related_block(Page $page, $tag_infos) + { + global $config; - if($config->get_string('tag_list_related_sort') == 'alphabetical') asort($tag_infos); + if ($config->get_string('tag_list_related_sort') == 'alphabetical') { + asort($tag_infos); + } - if(class_exists('TagCategories')) { - $this->tagcategories = new TagCategories; - $tag_category_dict = $this->tagcategories->getKeyedDict(); - } - else { - $tag_category_dict = array(); - } - $tag_categories_html = array(); - $tag_categories_count = array(); + if (class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); + } else { + $tag_category_dict = []; + } + $tag_categories_html = []; + $tag_categories_count = []; - foreach($tag_infos as $row) { - $split = self::return_tag($row, $tag_category_dict); - $category = $split[0]; - $tag_html = $split[1]; - if(!isset($tag_categories_html[$category])) { - $tag_categories_html[$category] = $this->get_tag_list_preamble(); - } - $tag_categories_html[$category] .= "$tag_html"; + foreach ($tag_infos as $row) { + $split = self::return_tag($row, $tag_category_dict); + $category = $split[0]; + $tag_html = $split[1]; + if (!isset($tag_categories_html[$category])) { + $tag_categories_html[$category] = $this->get_tag_list_preamble(); + } + $tag_categories_html[$category] .= "$tag_html"; - if(!isset($tag_categories_count[$category])) { - $tag_categories_count[$category] = 0; - } - $tag_categories_count[$category] += 1; - } + if (!isset($tag_categories_count[$category])) { + $tag_categories_count[$category] = 0; + } + $tag_categories_count[$category] += 1; + } - foreach(array_keys($tag_categories_html) as $category) { - $tag_categories_html[$category] .= '
    Tag#Tag#
    '; - } + foreach (array_keys($tag_categories_html) as $category) { + $tag_categories_html[$category] .= ''; + } - asort($tag_categories_html); - if(isset($tag_categories_html[' '])) $main_html = $tag_categories_html[' ']; else $main_html = null; - unset($tag_categories_html[' ']); + asort($tag_categories_html); + if (isset($tag_categories_html[' '])) { + $main_html = $tag_categories_html[' ']; + } else { + $main_html = null; + } + unset($tag_categories_html[' ']); - foreach(array_keys($tag_categories_html) as $category) { - if($tag_categories_count[$category] < 2) { - $category_display_name = html_escape($tag_category_dict[$category]['display_singular']); - } - else{ - $category_display_name = html_escape($tag_category_dict[$category]['display_multiple']); - } - $page->add_block(new Block($category_display_name, $tag_categories_html[$category], "left", 9)); - } + foreach (array_keys($tag_categories_html) as $category) { + if ($tag_categories_count[$category] < 2) { + $category_display_name = html_escape($tag_category_dict[$category]['display_singular']); + } else { + $category_display_name = html_escape($tag_category_dict[$category]['display_multiple']); + } + $page->add_block(new Block($category_display_name, $tag_categories_html[$category], "left", 9)); + } - if($config->get_string('tag_list_image_type')=="tags") { - $page->add_block(new Block("Tags", $main_html, "left", 10)); - } - else { - $page->add_block(new Block("Related Tags", $main_html, "left", 10)); - } - } + if ($config->get_string('tag_list_image_type')=="tags") { + $page->add_block(new Block("Tags", $main_html, "left", 10)); + } else { + $page->add_block(new Block("Related Tags", $main_html, "left", 10)); + } + } - /* - * $tag_infos = array( - * array('tag' => $tag, 'count' => $number_of_uses), - * ... - * ) - */ - private function get_tag_list_html($tag_infos, $sort) { - if($sort == 'alphabetical') asort($tag_infos); + /* + * $tag_infos = array( + * array('tag' => $tag, 'count' => $number_of_uses), + * ... + * ) + */ + private function get_tag_list_html($tag_infos, $sort) + { + if ($sort == 'alphabetical') { + asort($tag_infos); + } - if(class_exists('TagCategories')) { - $this->tagcategories = new TagCategories; - $tag_category_dict = $this->tagcategories->getKeyedDict(); - } - else { - $tag_category_dict = array(); - } - $main_html = $this->get_tag_list_preamble(); + if (class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); + } else { + $tag_category_dict = []; + } + $main_html = $this->get_tag_list_preamble(); - foreach($tag_infos as $row) { - $split = $this->return_tag($row, $tag_category_dict); - //$category = $split[0]; - $tag_html = $split[1]; - $main_html .= "$tag_html"; - } + foreach ($tag_infos as $row) { + $split = $this->return_tag($row, $tag_category_dict); + //$category = $split[0]; + $tag_html = $split[1]; + $main_html .= "$tag_html"; + } - $main_html .= ''; + $main_html .= ''; - return $main_html; - } + return $main_html; + } - /* - * $tag_infos = array( - * array('tag' => $tag, 'count' => $number_of_uses), - * ... - * ) - */ - public function display_related_block(Page $page, $tag_infos) { - global $config; + /* + * $tag_infos = array( + * array('tag' => $tag, 'count' => $number_of_uses), + * ... + * ) + */ + public function display_related_block(Page $page, $tag_infos) + { + global $config; - $main_html = $this->get_tag_list_html( - $tag_infos, $config->get_string('tag_list_related_sort')); + $main_html = $this->get_tag_list_html( + $tag_infos, + $config->get_string('tag_list_related_sort') + ); - if($config->get_string('tag_list_image_type')=="tags") { - $page->add_block(new Block("Tags", $main_html, "left", 10)); - } - else { - $page->add_block(new Block("Related Tags", $main_html, "left", 10)); - } - } + if ($config->get_string('tag_list_image_type')=="tags") { + $page->add_block(new Block("Tags", $main_html, "left", 10)); + } else { + $page->add_block(new Block("Related Tags", $main_html, "left", 10)); + } + } - /* - * $tag_infos = array( - * array('tag' => $tag, 'count' => $number_of_uses), - * ... - * ) - */ - public function display_popular_block(Page $page, $tag_infos) { - global $config; + /* + * $tag_infos = array( + * array('tag' => $tag, 'count' => $number_of_uses), + * ... + * ) + */ + public function display_popular_block(Page $page, $tag_infos) + { + global $config; - $main_html = $this->get_tag_list_html( - $tag_infos, $config->get_string('tag_list_popular_sort')); - $main_html .= " 
    Full List\n"; + $main_html = $this->get_tag_list_html( + $tag_infos, + $config->get_string('tag_list_popular_sort') + ); + $main_html .= " 
    Full List\n"; - $page->add_block(new Block("Popular Tags", $main_html, "left", 60)); - } + $page->add_block(new Block("Popular Tags", $main_html, "left", 60)); + } - /* - * $tag_infos = array( - * array('tag' => $tag), - * ... - * ) - * $search = the current array of tags being searched for - */ - public function display_refine_block(Page $page, $tag_infos, $search) { - global $config; + /* + * $tag_infos = array( + * array('tag' => $tag), + * ... + * ) + * $search = the current array of tags being searched for + */ + public function display_refine_block(Page $page, $tag_infos, $search) + { + global $config; - $main_html = $this->get_tag_list_html( - $tag_infos, $config->get_string('tag_list_popular_sort')); - $main_html .= " 
    Full List\n"; + $main_html = $this->get_tag_list_html( + $tag_infos, + $config->get_string('tag_list_popular_sort') + ); + $main_html .= " 
    Full List\n"; - $page->add_block(new Block("refine Search", $main_html, "left", 60)); - } + $page->add_block(new Block("refine Search", $main_html, "left", 60)); + } - public function return_tag($row, $tag_category_dict) { - global $config; + public function return_tag($row, $tag_category_dict) + { + global $config; - $display_html = ''; - $tag = $row['tag']; - $h_tag = html_escape($tag); - - $tag_category_css = ''; - $tag_category_style = ''; - $h_tag_split = explode(':', html_escape($tag), 2); - $category = ' '; + $display_html = ''; + $tag = $row['tag']; + $h_tag = html_escape($tag); + + $tag_category_css = ''; + $tag_category_style = ''; + $h_tag_split = explode(':', html_escape($tag), 2); + $category = ' '; - // we found a tag, see if it's valid! - if((count($h_tag_split) > 1) and array_key_exists($h_tag_split[0], $tag_category_dict)) { - $category = $h_tag_split[0]; - $h_tag = $h_tag_split[1]; - $tag_category_css .= ' tag_category_'.$category; - $tag_category_style .= 'style="color:'.html_escape($tag_category_dict[$category]['color']).';" '; - } + // we found a tag, see if it's valid! + if ((count($h_tag_split) > 1) and array_key_exists($h_tag_split[0], $tag_category_dict)) { + $category = $h_tag_split[0]; + $h_tag = $h_tag_split[1]; + $tag_category_css .= ' tag_category_'.$category; + $tag_category_style .= 'style="color:'.html_escape($tag_category_dict[$category]['color']).';" '; + } - $h_tag_no_underscores = str_replace("_", " ", $h_tag); - $count = $row['calc_count']; - // if($n++) $display_html .= "\n
    "; - if(!is_null($config->get_string('info_link'))) { - $link = html_escape(str_replace('$tag', url_escape($tag), $config->get_string('info_link'))); - $display_html .= ' ?'; - } - $link = $this->tag_link($row['tag']); - $display_html .= ' '.$h_tag_no_underscores.''; + $h_tag_no_underscores = str_replace("_", " ", $h_tag); + $count = $row['calc_count']; + // if($n++) $display_html .= "\n
    "; + if (!is_null($config->get_string('info_link'))) { + $link = html_escape(str_replace('$tag', url_escape($tag), $config->get_string('info_link'))); + $display_html .= ' ?'; + } + $link = $this->tag_link($row['tag']); + $display_html .= ' '.$h_tag_no_underscores.''; - if($config->get_bool("tag_list_numbers")) { - $display_html .= " $count"; - } + if ($config->get_bool("tag_list_numbers")) { + $display_html .= " $count"; + } - return array($category, $display_html); - } + return [$category, $display_html]; + } - protected function ars(string $tag, array $tags): string { - // FIXME: a better fix would be to make sure the inputs are correct - $tag = strtolower($tag); - $tags = array_map("strtolower", $tags); - $html = ""; - $html .= " ("; - $html .= $this->get_add_link($tags, $tag); - $html .= $this->get_remove_link($tags, $tag); - $html .= $this->get_subtract_link($tags, $tag); - $html .= ")"; - return $html; - } + protected function ars(string $tag, array $tags): string + { + // FIXME: a better fix would be to make sure the inputs are correct + $tag = strtolower($tag); + $tags = array_map("strtolower", $tags); + $html = ""; + $html .= " ("; + $html .= $this->get_add_link($tags, $tag); + $html .= $this->get_remove_link($tags, $tag); + $html .= $this->get_subtract_link($tags, $tag); + $html .= ")"; + return $html; + } - protected function get_remove_link(array $tags, string $tag): string { - if(!in_array($tag, $tags) && !in_array("-$tag", $tags)) { - return ""; - } - else { - $tags = array_remove($tags, $tag); - $tags = array_remove($tags, "-$tag"); - return "R"; - } - } + protected function get_remove_link(array $tags, string $tag): string + { + if (!in_array($tag, $tags) && !in_array("-$tag", $tags)) { + return ""; + } else { + $tags = array_remove($tags, $tag); + $tags = array_remove($tags, "-$tag"); + return "R"; + } + } - protected function get_add_link(array $tags, string $tag): string { - if(in_array($tag, $tags)) { - return ""; - } - else { - $tags = array_remove($tags, "-$tag"); - $tags = array_add($tags, $tag); - return "A"; - } - } + protected function get_add_link(array $tags, string $tag): string + { + if (in_array($tag, $tags)) { + return ""; + } else { + $tags = array_remove($tags, "-$tag"); + $tags = array_add($tags, $tag); + return "A"; + } + } - protected function get_subtract_link(array $tags, string $tag): string { - if(in_array("-$tag", $tags)) { - return ""; - } - else { - $tags = array_remove($tags, $tag); - $tags = array_add($tags, "-$tag"); - return "S"; - } - } + protected function get_subtract_link(array $tags, string $tag): string + { + if (in_array("-$tag", $tags)) { + return ""; + } else { + $tags = array_remove($tags, $tag); + $tags = array_add($tags, "-$tag"); + return "S"; + } + } - protected function tag_link(string $tag): string { - $u_tag = url_escape($tag); - return make_link("post/list/$u_tag/1"); - } + protected function tag_link(string $tag): string + { + $u_tag = url_escape($tag); + return make_link("post/list/$u_tag/1"); + } } diff --git a/ext/tagger/main.php b/ext/tagger/main.php index 84404e5a..69dc5f62 100644 --- a/ext/tagger/main.php +++ b/ext/tagger/main.php @@ -6,137 +6,156 @@ * Do not remove this notice. */ -class Tagger extends Extension { - public function onDisplayingImage(DisplayingImageEvent $event) { - global $page, $user; +class Tagger extends Extension +{ + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $page, $user; - if($user->can("edit_image_tag") && ($event->image->is_locked() || $user->can("edit_image_lock"))) { - $this->theme->build_tagger($page,$event); - } - } + if ($user->can("edit_image_tag") && ($event->image->is_locked() || $user->can("edit_image_lock"))) { + $this->theme->build_tagger($page, $event); + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Tagger"); - $sb->add_int_option("ext_tagger_search_delay", "Delay queries by "); - $sb->add_label(" milliseconds."); - $sb->add_label("
    Limit queries returning more than "); - $sb->add_int_option("ext_tagger_tag_max"); - $sb->add_label(" tags to "); - $sb->add_int_option("ext_tagger_limit"); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Tagger"); + $sb->add_int_option("ext_tagger_search_delay", "Delay queries by "); + $sb->add_label(" milliseconds."); + $sb->add_label("
    Limit queries returning more than "); + $sb->add_int_option("ext_tagger_tag_max"); + $sb->add_label(" tags to "); + $sb->add_int_option("ext_tagger_limit"); + $event->panel->add_block($sb); + } } // Tagger AJAX back-end -class TaggerXML extends Extension { - public function get_priority(): int {return 10;} +class TaggerXML extends Extension +{ + public function get_priority(): int + { + return 10; + } - public function onPageRequest(PageRequestEvent $event) { - if($event->page_matches("tagger/tags")) { - global $page; + public function onPageRequest(PageRequestEvent $event) + { + if ($event->page_matches("tagger/tags")) { + global $page; - //$match_tags = null; - //$image_tags = null; - $tags=null; - if (isset($_GET['s'])) { // tagger/tags[/...]?s=$string - // return matching tags in XML form - $tags = $this->match_tag_list($_GET['s']); - } else if($event->get_arg(0)) { // tagger/tags/$int - // return arg[1] AS image_id's tag list in XML form - $tags = $this->image_tag_list($event->get_arg(0)); - } + //$match_tags = null; + //$image_tags = null; + $tags=null; + if (isset($_GET['s'])) { // tagger/tags[/...]?s=$string + // return matching tags in XML form + $tags = $this->match_tag_list($_GET['s']); + } elseif ($event->get_arg(0)) { // tagger/tags/$int + // return arg[1] AS image_id's tag list in XML form + $tags = $this->image_tag_list($event->get_arg(0)); + } - $xml = "\n". - "". - $tags. - ""; + $xml = "\n". + "". + $tags. + ""; - $page->set_mode("data"); - $page->set_type("text/xml"); - $page->set_data($xml); - } - } + $page->set_mode("data"); + $page->set_type("text/xml"); + $page->set_data($xml); + } + } - private function match_tag_list (string $s) { - global $database, $config; + private function match_tag_list(string $s) + { + global $database, $config; - $max_rows = $config->get_int("ext_tagger_tag_max",30); - $limit_rows = $config->get_int("ext_tagger_limit",30); + $max_rows = $config->get_int("ext_tagger_tag_max", 30); + $limit_rows = $config->get_int("ext_tagger_limit", 30); - $values = array(); + $values = []; - // Match - $p = strlen($s) == 1? " ":"\_"; - $sq = "%".$p.sql_escape($s)."%"; - $match = "concat(?,tag) LIKE ?"; - array_push($values,$p,$sq); - // Exclude -// $exclude = $event->get_arg(1)? "AND NOT IN ".$this->image_tags($event->get_arg(1)) : null; + // Match + $p = strlen($s) == 1? " ":"\_"; + $sq = "%".$p.sql_escape($s)."%"; + $match = "concat(?,tag) LIKE ?"; + array_push($values, $p, $sq); + // Exclude + // $exclude = $event->get_arg(1)? "AND NOT IN ".$this->image_tags($event->get_arg(1)) : null; - // Hidden Tags - $hidden = $config->get_string('ext-tagger_show-hidden','N')=='N' ? - "AND substring(tag,1,1) != '.'" : null; + // Hidden Tags + $hidden = $config->get_string('ext-tagger_show-hidden', 'N')=='N' ? + "AND substring(tag,1,1) != '.'" : null; - $q_where = "WHERE {$match} {$hidden} AND count > 0"; + $q_where = "WHERE {$match} {$hidden} AND count > 0"; - // FROM based on return count - $count = $this->count($q_where,$values); - if ($count > $max_rows) { - $q_from = "FROM (SELECT * FROM `tags` {$q_where} ". - "ORDER BY count DESC LIMIT 0, {$limit_rows}) AS `c_tags`"; - $q_where = null; - $count = array("max"=>$count); - } else { - $q_from = "FROM `tags`"; - $count = null; - } + // FROM based on return count + $count = $this->count($q_where, $values); + if ($count > $max_rows) { + $q_from = "FROM (SELECT * FROM `tags` {$q_where} ". + "ORDER BY count DESC LIMIT 0, {$limit_rows}) AS `c_tags`"; + $q_where = null; + $count = ["max"=>$count]; + } else { + $q_from = "FROM `tags`"; + $count = null; + } - $tags = $database->Execute(" + $tags = $database->Execute( + " SELECT * {$q_from} {$q_where} ORDER BY tag", - $values); + $values + ); - return $this->list_to_xml($tags,"search",$s,$count); - } + return $this->list_to_xml($tags, "search", $s, $count); + } - private function image_tag_list (int $image_id) { - global $database; - $tags = $database->Execute(" + private function image_tag_list(int $image_id) + { + global $database; + $tags = $database->Execute(" SELECT tags.* FROM image_tags JOIN tags ON image_tags.tag_id = tags.id - WHERE image_id=? ORDER BY tag", array($image_id)); - return $this->list_to_xml($tags,"image",$image_id); - } + WHERE image_id=? ORDER BY tag", [$image_id]); + return $this->list_to_xml($tags, "image", $image_id); + } - private function list_to_xml (PDOStatement $tags, string $type, string $query, ?array$misc=null): string { - $r = $tags->_numOfRows; + private function list_to_xml(PDOStatement $tags, string $type, string $query, ?array$misc=null): string + { + $r = $tags->_numOfRows; - $s_misc = ""; - if(!is_null($misc)) - foreach($misc as $attr => $val) $s_misc .= " ".$attr."=\"".$val."\""; + $s_misc = ""; + if (!is_null($misc)) { + foreach ($misc as $attr => $val) { + $s_misc .= " ".$attr."=\"".$val."\""; + } + } - $result = ""; - foreach($tags as $tag) { - $result .= $this->tag_to_xml($tag); - } - return $result.""; - } + $result = ""; + foreach ($tags as $tag) { + $result .= $this->tag_to_xml($tag); + } + return $result.""; + } - private function tag_to_xml (string $tag): string { - return - "". - html_escape($tag['tag']). - ""; - } - - private function count(string $query, $values) { - global $database; - return $database->Execute( - "SELECT COUNT(*) FROM `tags` $query",$values)->fields['COUNT(*)']; - } -} + private function tag_to_xml(string $tag): string + { + return + "". + html_escape($tag['tag']). + ""; + } + private function count(string $query, $values) + { + global $database; + return $database->Execute( + "SELECT COUNT(*) FROM `tags` $query", + $values + )->fields['COUNT(*)']; + } +} diff --git a/ext/tagger/theme.php b/ext/tagger/theme.php index 5b446382..d2f65efa 100644 --- a/ext/tagger/theme.php +++ b/ext/tagger/theme.php @@ -5,38 +5,46 @@ * Do not remove this notice. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -class taggerTheme extends Themelet { - public function build_tagger (Page $page, $event) { - // Initialization code - $base_href = get_base_href(); - // TODO: AJAX test and fallback. +class taggerTheme extends Themelet +{ + public function build_tagger(Page $page, $event) + { + // Initialization code + $base_href = get_base_href(); + // TODO: AJAX test and fallback. - $page->add_html_header(""); - $page->add_block(new Block(null, - ""); + $page->add_block(new Block( + null, + "","main",1000)); + ", + "main", + 1000 + )); - // Tagger block - $page->add_block( new Block( - null, - $this->html($event->get_image()), - "main")); - } - private function html(Image $image) { - global $config; - $i_image_id = int_escape($image->id); - $h_source = html_escape($image->source); - $h_query = isset($_GET['search'])? $h_query= "search=".url_escape($_GET['search']) : ""; + // Tagger block + $page->add_block(new Block( + null, + $this->html($event->get_image()), + "main" + )); + } + private function html(Image $image) + { + global $config; + $i_image_id = int_escape($image->id); + $h_source = html_escape($image->source); + $h_query = isset($_GET['search'])? $h_query= "search=".url_escape($_GET['search']) : ""; - $delay = $config->get_string("ext_tagger_search_delay","250"); + $delay = $config->get_string("ext_tagger_search_delay", "250"); - $url_form = make_link("tag_edit/set"); + $url_form = make_link("tag_edit/set"); - // TODO: option for initial Tagger window placement. - $html = <<< EOD + // TODO: option for initial Tagger window placement. + $html = <<< EOD

    EOD; - return $html; - } + return $html; + } } - diff --git a/ext/tips/main.php b/ext/tips/main.php index da13eda5..f4f7d619 100644 --- a/ext/tips/main.php +++ b/ext/tips/main.php @@ -8,149 +8,161 @@ * Formatting is done with HTML */ -class Tips extends Extension { - protected $db_support = ['mysql', 'sqlite']; // rand() ? +class Tips extends Extension +{ + protected $db_support = ['mysql', 'sqlite']; // rand() ? - public function onInitExt(InitExtEvent $event) { - global $config, $database; + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - if ($config->get_int("ext_tips_version") < 1){ - $database->create_table("tips", " + if ($config->get_int("ext_tips_version") < 1) { + $database->create_table("tips", " id SCORE_AIPK, enable SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, image TEXT NOT NULL, text TEXT NOT NULL, "); - $database->execute(" + $database->execute( + " INSERT INTO tips (enable, image, text) VALUES (?, ?, ?)", - array("Y", "coins.png", "Do you like this extension? Please support us for developing new ones. Donate through paypal.")); + ["Y", "coins.png", "Do you like this extension? Please support us for developing new ones. Donate through paypal."] + ); - $config->set_int("ext_tips_version", 1); - log_info("tips", "extension installed"); - } - } + $config->set_int("ext_tips_version", 1); + log_info("tips", "extension installed"); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - $this->getTip(); + $this->getTip(); - if($event->page_matches("tips") && $user->is_admin()) { - switch($event->get_arg(0)) { - case "list": - $this->manageTips(); - $this->getAll(); - break; - case "save": - if($user->check_auth_token()) { - $this->saveTip(); - $page->set_mode("redirect"); - $page->set_redirect(make_link("tips/list")); - } - break; - case "status": - // FIXME: HTTP GET CSRF - $tipID = int_escape($event->get_arg(1)); - $this->setStatus($tipID); - $page->set_mode("redirect"); - $page->set_redirect(make_link("tips/list")); - break; - case "delete": - // FIXME: HTTP GET CSRF - $tipID = int_escape($event->get_arg(1)); - $this->deleteTip($tipID); - $page->set_mode("redirect"); - $page->set_redirect(make_link("tips/list")); - break; - } - } - } + if ($event->page_matches("tips") && $user->is_admin()) { + switch ($event->get_arg(0)) { + case "list": + $this->manageTips(); + $this->getAll(); + break; + case "save": + if ($user->check_auth_token()) { + $this->saveTip(); + $page->set_mode("redirect"); + $page->set_redirect(make_link("tips/list")); + } + break; + case "status": + // FIXME: HTTP GET CSRF + $tipID = int_escape($event->get_arg(1)); + $this->setStatus($tipID); + $page->set_mode("redirect"); + $page->set_redirect(make_link("tips/list")); + break; + case "delete": + // FIXME: HTTP GET CSRF + $tipID = int_escape($event->get_arg(1)); + $this->deleteTip($tipID); + $page->set_mode("redirect"); + $page->set_redirect(make_link("tips/list")); + break; + } + } + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - if($user->is_admin()) { - $event->add_link("Tips Editor", make_link("tips/list")); - } - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + if ($user->is_admin()) { + $event->add_link("Tips Editor", make_link("tips/list")); + } + } - private function manageTips() { - $data_href = get_base_href(); - $url = $data_href."/ext/tips/images/"; + private function manageTips() + { + $data_href = get_base_href(); + $url = $data_href."/ext/tips/images/"; - $dirPath = dir('./ext/tips/images'); - $images = array(); - while(($file = $dirPath->read()) !== false) { - if($file[0] != ".") { - $images[] = trim($file); - } - } - $dirPath->close(); - sort($images); + $dirPath = dir('./ext/tips/images'); + $images = []; + while (($file = $dirPath->read()) !== false) { + if ($file[0] != ".") { + $images[] = trim($file); + } + } + $dirPath->close(); + sort($images); - $this->theme->manageTips($url, $images); - } + $this->theme->manageTips($url, $images); + } - private function saveTip() { - global $database; + private function saveTip() + { + global $database; - $enable = isset($_POST["enable"]) ? "Y" : "N"; - $image = html_escape($_POST["image"]); - $text = $_POST["text"]; + $enable = isset($_POST["enable"]) ? "Y" : "N"; + $image = html_escape($_POST["image"]); + $text = $_POST["text"]; - $database->execute(" + $database->execute( + " INSERT INTO tips (enable, image, text) VALUES (?, ?, ?)", - array($enable, $image, $text)); + [$enable, $image, $text] + ); + } - } + private function getTip() + { + global $database; - private function getTip() { - global $database; + $data_href = get_base_href(); + $url = $data_href."/ext/tips/images/"; - $data_href = get_base_href(); - $url = $data_href."/ext/tips/images/"; + $tip = $database->get_row("SELECT * ". + "FROM tips ". + "WHERE enable = 'Y' ". + "ORDER BY RAND() ". + "LIMIT 1"); - $tip = $database->get_row("SELECT * ". - "FROM tips ". - "WHERE enable = 'Y' ". - "ORDER BY RAND() ". - "LIMIT 1"); + if ($tip) { + $this->theme->showTip($url, $tip); + } + } - if($tip) { - $this->theme->showTip($url, $tip); - } - } + private function getAll() + { + global $database; - private function getAll() { - global $database; + $data_href = get_base_href(); + $url = $data_href."/ext/tips/images/"; - $data_href = get_base_href(); - $url = $data_href."/ext/tips/images/"; + $tips = $database->get_all("SELECT * FROM tips ORDER BY id ASC"); - $tips = $database->get_all("SELECT * FROM tips ORDER BY id ASC"); + $this->theme->showAll($url, $tips); + } - $this->theme->showAll($url, $tips); - } + private function setStatus(int $tipID) + { + global $database; - private function setStatus(int $tipID) { - global $database; + $tip = $database->get_row("SELECT * FROM tips WHERE id = ? ", [int_escape($tipID)]); - $tip = $database->get_row("SELECT * FROM tips WHERE id = ? ", array(int_escape($tipID))); + if (bool_escape($tip['enable'])) { + $enable = "N"; + } else { + $enable = "Y"; + } - if (bool_escape($tip['enable'])) { - $enable = "N"; - } else { - $enable = "Y"; - } + $database->execute("UPDATE tips SET enable = ? WHERE id = ?", [$enable, int_escape($tipID)]); + } - $database->execute("UPDATE tips SET enable = ? WHERE id = ?", array ($enable, int_escape($tipID))); - } - - private function deleteTip(int $tipID) { - global $database; - $database->execute("DELETE FROM tips WHERE id = ?", array(int_escape($tipID))); - } + private function deleteTip(int $tipID) + { + global $database; + $database->execute("DELETE FROM tips WHERE id = ?", [int_escape($tipID)]); + } } - diff --git a/ext/tips/test.php b/ext/tips/test.php index e95fb5d8..ccb2b225 100644 --- a/ext/tips/test.php +++ b/ext/tips/test.php @@ -1,85 +1,89 @@ log_in_as_admin(); - $this->get_page("tips/list"); + $this->log_in_as_admin(); + $this->get_page("tips/list"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - // get rid of the default data if it's there - if(strpos($raw, "Delete")) { - $this->click("Delete"); - } - $this->log_out(); - } + // get rid of the default data if it's there + if (strpos($raw, "Delete")) { + $this->click("Delete"); + } + $this->log_out(); + } - public function testImageless() { - $this->log_in_as_admin(); + public function testImageless() + { + $this->log_in_as_admin(); - $this->get_page("tips/list"); - $this->assert_title("Tips List"); + $this->get_page("tips/list"); + $this->assert_title("Tips List"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field("image", ""); - $this->set_field("text", "an imageless tip"); - $this->click("Submit"); - $this->assert_title("Tips List"); + $this->set_field("image", ""); + $this->set_field("text", "an imageless tip"); + $this->click("Submit"); + $this->assert_title("Tips List"); - $this->get_page("post/list"); - $this->assert_text("an imageless tip"); + $this->get_page("post/list"); + $this->assert_text("an imageless tip"); - $this->get_page("tips/list"); - $this->click("Delete"); + $this->get_page("tips/list"); + $this->click("Delete"); - $this->log_out(); - } + $this->log_out(); + } - public function testImaged() { - $this->log_in_as_admin(); + public function testImaged() + { + $this->log_in_as_admin(); - $this->get_page("tips/list"); - $this->assert_title("Tips List"); + $this->get_page("tips/list"); + $this->assert_title("Tips List"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field("image", "coins.png"); - $this->set_field("text", "an imaged tip"); - $this->click("Submit"); - $this->assert_title("Tips List"); + $this->set_field("image", "coins.png"); + $this->set_field("text", "an imaged tip"); + $this->click("Submit"); + $this->assert_title("Tips List"); - $this->get_page("post/list"); - $this->assert_text("an imaged tip"); + $this->get_page("post/list"); + $this->assert_text("an imaged tip"); - $this->get_page("tips/list"); - $this->click("Delete"); + $this->get_page("tips/list"); + $this->click("Delete"); - $this->log_out(); - } + $this->log_out(); + } - public function testDisabled() { - $this->log_in_as_admin(); + public function testDisabled() + { + $this->log_in_as_admin(); - $this->get_page("tips/list"); - $this->assert_title("Tips List"); + $this->get_page("tips/list"); + $this->assert_title("Tips List"); - $this->markTestIncomplete(); + $this->markTestIncomplete(); - $this->set_field("image", "coins.png"); - $this->set_field("text", "an imaged tip"); - $this->click("Submit"); - $this->click("Yes"); - $this->assert_title("Tips List"); + $this->set_field("image", "coins.png"); + $this->set_field("text", "an imaged tip"); + $this->click("Submit"); + $this->click("Yes"); + $this->assert_title("Tips List"); - $this->get_page("post/list"); - $this->assert_no_text("an imaged tip"); + $this->get_page("post/list"); + $this->assert_no_text("an imaged tip"); - $this->get_page("tips/list"); - $this->click("Delete"); + $this->get_page("tips/list"); + $this->click("Delete"); - $this->log_out(); - } + $this->log_out(); + } } - diff --git a/ext/tips/theme.php b/ext/tips/theme.php index d724ca7c..fd9cd5bb 100644 --- a/ext/tips/theme.php +++ b/ext/tips/theme.php @@ -1,16 +1,18 @@ "; +class TipsTheme extends Themelet +{ + public function manageTips($url, $images) + { + global $page; + $select = ""; + $select .= ""; - $html = " + $html = " ".make_form(make_link("tips/save"))." @@ -32,64 +34,65 @@ class TipsTheme extends Themelet { "; - $page->set_title("Tips List"); - $page->set_heading("Tips List"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Add Tip", $html, "main", 10)); - } + $page->set_title("Tips List"); + $page->set_heading("Tips List"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Add Tip", $html, "main", 10)); + } - public function showTip($url, $tip) { - global $page; + public function showTip($url, $tip) + { + global $page; - $img = ""; - if(!empty($tip['image'])) { - $img = " "; - } - $html = "
    ".$img.$tip['text']."
    "; - $page->add_block(new Block(null, $html, "subheading", 10)); - } + $img = ""; + if (!empty($tip['image'])) { + $img = " "; + } + $html = "
    ".$img.$tip['text']."
    "; + $page->add_block(new Block(null, $html, "subheading", 10)); + } - public function showAll($url, $tips){ - global $user, $page; + public function showAll($url, $tips) + { + global $user, $page; - $html = "
    ". - "". - "". - "". - "". - ""; + $html = "
    IDEnabledImageText
    ". + "". + "". + "". + "". + ""; - if($user->is_admin()){ - $html .= ""; - } + if ($user->is_admin()) { + $html .= ""; + } - $html .= ""; + $html .= ""; - foreach ($tips as $tip) { - $tip_enable = ($tip['enable'] == "Y") ? "Yes" : "No"; - $set_link = "".$tip_enable.""; + foreach ($tips as $tip) { + $tip_enable = ($tip['enable'] == "Y") ? "Yes" : "No"; + $set_link = "".$tip_enable.""; - $html .= "". - "". - "". - ( - empty($tip['image']) ? - "" : - "" - ). - ""; + $html .= "". + "". + "". + ( + empty($tip['image']) ? + "" : + "" + ). + ""; - $del_link = "Delete"; + $del_link = "Delete"; - if($user->is_admin()){ - $html .= ""; - } + if ($user->is_admin()) { + $html .= ""; + } - $html .= ""; - } - $html .= "
    IDEnabledImageTextActionAction
    ".$tip['id']."".$set_link."".$tip['text']."
    ".$tip['id']."".$set_link."".$tip['text']."".$del_link."".$del_link."
    "; + $html .= ""; + } + $html .= ""; - $page->add_block(new Block("All Tips", $html, "main", 20)); - } + $page->add_block(new Block("All Tips", $html, "main", 20)); + } } - diff --git a/ext/update/main.php b/ext/update/main.php index 653c4176..cf995c10 100644 --- a/ext/update/main.php +++ b/ext/update/main.php @@ -6,106 +6,120 @@ * License: GPLv2 * Description: Shimmie updater! (Requires admin panel extension & transload engine (cURL/fopen/Wget)) */ -class Update extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_string("update_guserrepo", "shish/shimmie2"); - $config->set_default_string("commit_hash", "unknown"); - $config->set_default_string("update_time", "01/01/1970"); - } +class Update extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_string("update_guserrepo", "shish/shimmie2"); + $config->set_default_string("commit_hash", "unknown"); + $config->set_default_string("update_time", "01/01/1970"); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Update"); - $sb->add_text_option("update_guserrepo", "User/Repo: "); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Update"); + $sb->add_text_option("update_guserrepo", "User/Repo: "); + $event->panel->add_block($sb); + } - public function onAdminBuilding(AdminBuildingEvent $event) { - global $config; - if($config->get_string('transload_engine') !== "none"){ - $this->theme->display_admin_block(); - } - } + public function onAdminBuilding(AdminBuildingEvent $event) + { + global $config; + if ($config->get_string('transload_engine') !== "none") { + $this->theme->display_admin_block(); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $user, $page; - if($user->is_admin() && isset($_GET['sha'])){ - if($event->page_matches("update/download")){ - $ok = $this->download_shimmie(); + public function onPageRequest(PageRequestEvent $event) + { + global $user, $page; + if ($user->is_admin() && isset($_GET['sha'])) { + if ($event->page_matches("update/download")) { + $ok = $this->download_shimmie(); - $page->set_mode("redirect"); - if($ok) $page->set_redirect(make_link("update/update", "sha=".$_GET['sha'])); - else $page->set_redirect(make_link("admin")); //TODO: Show error? - }elseif($event->page_matches("update/update")){ - $ok = $this->update_shimmie(); + $page->set_mode("redirect"); + if ($ok) { + $page->set_redirect(make_link("update/update", "sha=".$_GET['sha'])); + } else { + $page->set_redirect(make_link("admin")); + } //TODO: Show error? + } elseif ($event->page_matches("update/update")) { + $ok = $this->update_shimmie(); - $page->set_mode("redirect"); - if($ok) $page->set_redirect(make_link("admin")); //TODO: Show success? - else $page->set_redirect(make_link("admin")); //TODO: Show error? - } - } - } + $page->set_mode("redirect"); + if ($ok) { + $page->set_redirect(make_link("admin")); + } //TODO: Show success? + else { + $page->set_redirect(make_link("admin")); + } //TODO: Show error? + } + } + } - private function download_shimmie(): bool { - global $config; + private function download_shimmie(): bool + { + global $config; - $commitSHA = $_GET['sha']; - $g_userrepo = $config->get_string('update_guserrepo'); + $commitSHA = $_GET['sha']; + $g_userrepo = $config->get_string('update_guserrepo'); - $url = "https://codeload.github.com/".$g_userrepo."/zip/".$commitSHA; - $filename = "./data/update_{$commitSHA}.zip"; + $url = "https://codeload.github.com/".$g_userrepo."/zip/".$commitSHA; + $filename = "./data/update_{$commitSHA}.zip"; - log_info("update", "Attempting to download Shimmie commit: ".$commitSHA); - if($headers = transload($url, $filename)){ - if(($headers['Content-Type'] !== "application/zip") || ((int) $headers['Content-Length'] !== filesize($filename))){ - unlink("./data/update_{$commitSHA}.zip"); - log_warning("update", "Download failed: not zip / not same size as remote file."); - return false; - } + log_info("update", "Attempting to download Shimmie commit: ".$commitSHA); + if ($headers = transload($url, $filename)) { + if (($headers['Content-Type'] !== "application/zip") || ((int) $headers['Content-Length'] !== filesize($filename))) { + unlink("./data/update_{$commitSHA}.zip"); + log_warning("update", "Download failed: not zip / not same size as remote file."); + return false; + } - return true; - } + return true; + } - log_warning("update", "Download failed to download."); - return false; - } + log_warning("update", "Download failed to download."); + return false; + } - private function update_shimmie(): bool { - global $config; + private function update_shimmie(): bool + { + global $config; - $commitSHA = $_GET['sha']; + $commitSHA = $_GET['sha']; - log_info("update", "Download succeeded. Attempting to update Shimmie."); - $config->set_bool("in_upgrade", TRUE); - $ok = FALSE; + log_info("update", "Download succeeded. Attempting to update Shimmie."); + $config->set_bool("in_upgrade", true); + $ok = false; - /** TODO: Backup all folders (except /data, /images, /thumbs) before attempting this? - Either that or point to https://github.com/shish/shimmie2/blob/master/README.txt -> Upgrade from 2.3.X **/ + /** TODO: Backup all folders (except /data, /images, /thumbs) before attempting this? + Either that or point to https://github.com/shish/shimmie2/blob/master/README.txt -> Upgrade from 2.3.X **/ - $zip = new ZipArchive; - if ($zip->open("./data/update_$commitSHA.zip") === TRUE) { - for($i = 1; $i < $zip->numFiles; $i++) { - $filename = $zip->getNameIndex($i); + $zip = new ZipArchive; + if ($zip->open("./data/update_$commitSHA.zip") === true) { + for ($i = 1; $i < $zip->numFiles; $i++) { + $filename = $zip->getNameIndex($i); - if(substr($filename, -1) !== "/"){ - copy("zip://".dirname(dirname(__DIR__)).'/'."./data/update_$commitSHA.zip"."#".$filename, substr($filename, 50)); - } - } - $ok = TRUE; //TODO: Do proper checking to see if everything copied properly - }else{ log_warning("update", "Update failed to open ZIP."); } + if (substr($filename, -1) !== "/") { + copy("zip://".dirname(dirname(__DIR__)).'/'."./data/update_$commitSHA.zip"."#".$filename, substr($filename, 50)); + } + } + $ok = true; //TODO: Do proper checking to see if everything copied properly + } else { + log_warning("update", "Update failed to open ZIP."); + } - $zip->close(); - unlink("./data/update_$commitSHA.zip"); - $config->set_bool("in_upgrade", FALSE); + $zip->close(); + unlink("./data/update_$commitSHA.zip"); + $config->set_bool("in_upgrade", false); - if($ok){ - $config->set_string("commit_hash", $commitSHA); - $config->set_string("update_time", date('d-m-Y')); - log_info("update", "Update succeeded?"); - } + if ($ok) { + $config->set_string("commit_hash", $commitSHA); + $config->set_string("update_time", date('d-m-Y')); + log_info("update", "Update succeeded?"); + } - return $ok; - } + return $ok; + } } - - diff --git a/ext/update/theme.php b/ext/update/theme.php index e3dffb6a..fe29b6a1 100644 --- a/ext/update/theme.php +++ b/ext/update/theme.php @@ -1,14 +1,15 @@ Current Commit: ".$config->get_string('commit_hash')." | (".$config->get_string('update_time').")". - "
    Latest Commit: Loading...". - "
    "; - //TODO: Show warning before use. - $page->add_block(new Block("Software Update", $html, "main", 75)); - } + $html = "". + "Current Commit: ".$config->get_string('commit_hash')." | (".$config->get_string('update_time').")". + "
    Latest Commit: Loading...". + "
    "; + //TODO: Show warning before use. + $page->add_block(new Block("Software Update", $html, "main", 75)); + } } - diff --git a/ext/upgrade/main.php b/ext/upgrade/main.php index 24d0e5bc..3321b409 100644 --- a/ext/upgrade/main.php +++ b/ext/upgrade/main.php @@ -7,128 +7,132 @@ * Visibility: admin */ -class Upgrade extends Extension { - public function onInitExt(InitExtEvent $event) { - global $config, $database; +class Upgrade extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $config, $database; - if($config->get_bool("in_upgrade")) return; + if ($config->get_bool("in_upgrade")) { + return; + } - if(!is_numeric($config->get_string("db_version"))) { - $config->set_int("db_version", 2); - } + if (!is_numeric($config->get_string("db_version"))) { + $config->set_int("db_version", 2); + } - if($config->get_int("db_version") < 6) { - // cry :S - } + if ($config->get_int("db_version") < 6) { + // cry :S + } - // v7 is convert to innodb with adodb - // now done again as v9 with PDO + // v7 is convert to innodb with adodb + // now done again as v9 with PDO - if($config->get_int("db_version") < 8) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 8); + if ($config->get_int("db_version") < 8) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 8); - $database->execute($database->scoreql_to_sql( - "ALTER TABLE images ADD COLUMN locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N" - )); + $database->execute($database->scoreql_to_sql( + "ALTER TABLE images ADD COLUMN locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N" + )); - log_info("upgrade", "Database at version 8"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Database at version 8"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 9) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 9); + if ($config->get_int("db_version") < 9) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 9); - if($database->get_driver_name() == 'mysql') { - $tables = $database->get_col("SHOW TABLES"); - foreach($tables as $table) { - log_info("upgrade", "converting $table to innodb"); - $database->execute("ALTER TABLE $table ENGINE=INNODB"); - } - } + if ($database->get_driver_name() == 'mysql') { + $tables = $database->get_col("SHOW TABLES"); + foreach ($tables as $table) { + log_info("upgrade", "converting $table to innodb"); + $database->execute("ALTER TABLE $table ENGINE=INNODB"); + } + } - log_info("upgrade", "Database at version 9"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Database at version 9"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 10) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 10); + if ($config->get_int("db_version") < 10) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 10); - log_info("upgrade", "Adding foreign keys to images"); - $database->Execute("ALTER TABLE images ADD FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT"); - - log_info("upgrade", "Database at version 10"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Adding foreign keys to images"); + $database->Execute("ALTER TABLE images ADD FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT"); + + log_info("upgrade", "Database at version 10"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 11) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 11); + if ($config->get_int("db_version") < 11) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 11); - log_info("upgrade", "Converting user flags to classes"); - $database->execute("ALTER TABLE users ADD COLUMN class VARCHAR(32) NOT NULL default :user", array("user" => "user")); - $database->execute("UPDATE users SET class = :name WHERE id=:id", array("name"=>"anonymous", "id"=>$config->get_int('anon_id'))); - $database->execute("UPDATE users SET class = :name WHERE admin=:admin", array("name"=>"admin", "admin"=>'Y')); + log_info("upgrade", "Converting user flags to classes"); + $database->execute("ALTER TABLE users ADD COLUMN class VARCHAR(32) NOT NULL default :user", ["user" => "user"]); + $database->execute("UPDATE users SET class = :name WHERE id=:id", ["name"=>"anonymous", "id"=>$config->get_int('anon_id')]); + $database->execute("UPDATE users SET class = :name WHERE admin=:admin", ["name"=>"admin", "admin"=>'Y']); - log_info("upgrade", "Database at version 11"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Database at version 11"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 12) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 12); + if ($config->get_int("db_version") < 12) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 12); - if($database->get_driver_name() == 'pgsql') { - log_info("upgrade", "Changing ext column to VARCHAR"); - $database->execute("ALTER TABLE images ALTER COLUMN ext SET DATA TYPE VARCHAR(4)"); - } + if ($database->get_driver_name() == 'pgsql') { + log_info("upgrade", "Changing ext column to VARCHAR"); + $database->execute("ALTER TABLE images ALTER COLUMN ext SET DATA TYPE VARCHAR(4)"); + } - log_info("upgrade", "Lowering case of all exts"); - $database->execute("UPDATE images SET ext = LOWER(ext)"); + log_info("upgrade", "Lowering case of all exts"); + $database->execute("UPDATE images SET ext = LOWER(ext)"); - log_info("upgrade", "Database at version 12"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Database at version 12"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 13) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 13); + if ($config->get_int("db_version") < 13) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 13); - log_info("upgrade", "Changing password column to VARCHAR(250)"); - if($database->get_driver_name() == 'pgsql') { - $database->execute("ALTER TABLE users ALTER COLUMN pass SET DATA TYPE VARCHAR(250)"); - } - else if($database->get_driver_name() == 'mysql') { - $database->execute("ALTER TABLE users CHANGE pass pass VARCHAR(250)"); - } + log_info("upgrade", "Changing password column to VARCHAR(250)"); + if ($database->get_driver_name() == 'pgsql') { + $database->execute("ALTER TABLE users ALTER COLUMN pass SET DATA TYPE VARCHAR(250)"); + } elseif ($database->get_driver_name() == 'mysql') { + $database->execute("ALTER TABLE users CHANGE pass pass VARCHAR(250)"); + } - log_info("upgrade", "Database at version 13"); - $config->set_bool("in_upgrade", false); - } + log_info("upgrade", "Database at version 13"); + $config->set_bool("in_upgrade", false); + } - if($config->get_int("db_version") < 14) { - $config->set_bool("in_upgrade", true); - $config->set_int("db_version", 14); + if ($config->get_int("db_version") < 14) { + $config->set_bool("in_upgrade", true); + $config->set_int("db_version", 14); - log_info("upgrade", "Changing tag column to VARCHAR(255)"); - if($database->get_driver_name() == 'pgsql') { - $database->execute('ALTER TABLE tags ALTER COLUMN tag SET DATA TYPE VARCHAR(255)'); - $database->execute('ALTER TABLE aliases ALTER COLUMN oldtag SET DATA TYPE VARCHAR(255)'); - $database->execute('ALTER TABLE aliases ALTER COLUMN newtag SET DATA TYPE VARCHAR(255)'); - } - else if($database->get_driver_name() == 'mysql') { - $database->execute('ALTER TABLE tags MODIFY COLUMN tag VARCHAR(255) NOT NULL'); - $database->execute('ALTER TABLE aliases MODIFY COLUMN oldtag VARCHAR(255) NOT NULL'); - $database->execute('ALTER TABLE aliases MODIFY COLUMN newtag VARCHAR(255) NOT NULL'); - } + log_info("upgrade", "Changing tag column to VARCHAR(255)"); + if ($database->get_driver_name() == 'pgsql') { + $database->execute('ALTER TABLE tags ALTER COLUMN tag SET DATA TYPE VARCHAR(255)'); + $database->execute('ALTER TABLE aliases ALTER COLUMN oldtag SET DATA TYPE VARCHAR(255)'); + $database->execute('ALTER TABLE aliases ALTER COLUMN newtag SET DATA TYPE VARCHAR(255)'); + } elseif ($database->get_driver_name() == 'mysql') { + $database->execute('ALTER TABLE tags MODIFY COLUMN tag VARCHAR(255) NOT NULL'); + $database->execute('ALTER TABLE aliases MODIFY COLUMN oldtag VARCHAR(255) NOT NULL'); + $database->execute('ALTER TABLE aliases MODIFY COLUMN newtag VARCHAR(255) NOT NULL'); + } - log_info("upgrade", "Database at version 14"); - $config->set_bool("in_upgrade", false); - } - } + log_info("upgrade", "Database at version 14"); + $config->set_bool("in_upgrade", false); + } + } - public function get_priority(): int {return 5;} + public function get_priority(): int + { + return 5; + } } - diff --git a/ext/upload/main.php b/ext/upload/main.php index 64715808..84279727 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -9,407 +9,424 @@ /** * Occurs when some data is being uploaded. */ -class DataUploadEvent extends Event { - /** @var string */ - public $tmpname; - /** @var array */ - public $metadata; - /** @var string */ - public $hash; - /** @var string */ - public $type; - /** @var int */ - public $image_id = -1; +class DataUploadEvent extends Event +{ + /** @var string */ + public $tmpname; + /** @var array */ + public $metadata; + /** @var string */ + public $hash; + /** @var string */ + public $type; + /** @var int */ + public $image_id = -1; - /** - * Some data is being uploaded. - * This should be caught by a file handler. - * $metadata should contain at least "filename", "extension", "tags" and "source". - */ - public function __construct(string $tmpname, array $metadata) { - assert(file_exists($tmpname)); - assert(is_string($metadata["filename"])); - assert(is_string($metadata["extension"])); - assert(is_array($metadata["tags"])); - assert(is_string($metadata["source"]) || is_null($metadata["source"])); + /** + * Some data is being uploaded. + * This should be caught by a file handler. + * $metadata should contain at least "filename", "extension", "tags" and "source". + */ + public function __construct(string $tmpname, array $metadata) + { + assert(file_exists($tmpname)); + assert(is_string($metadata["filename"])); + assert(is_string($metadata["extension"])); + assert(is_array($metadata["tags"])); + assert(is_string($metadata["source"]) || is_null($metadata["source"])); - $this->tmpname = $tmpname; + $this->tmpname = $tmpname; - $this->metadata = $metadata; - $this->metadata['hash'] = md5_file($tmpname); - $this->metadata['size'] = filesize($tmpname); + $this->metadata = $metadata; + $this->metadata['hash'] = md5_file($tmpname); + $this->metadata['size'] = filesize($tmpname); - // useful for most file handlers, so pull directly into fields - $this->hash = $this->metadata['hash']; - $this->type = strtolower($metadata['extension']); - } + // useful for most file handlers, so pull directly into fields + $this->hash = $this->metadata['hash']; + $this->type = strtolower($metadata['extension']); + } } -class UploadException extends SCoreException {} +class UploadException extends SCoreException +{ +} /** * Main upload class. * All files that are uploaded to the site are handled through this class. * This also includes transloaded files as well. */ -class Upload extends Extension { - /** @var bool */ - public $is_full; +class Upload extends Extension +{ + /** @var bool */ + public $is_full; - /** - * Early, so it can stop the DataUploadEvent before any data handlers see it. - */ - public function get_priority(): int {return 40;} + /** + * Early, so it can stop the DataUploadEvent before any data handlers see it. + */ + public function get_priority(): int + { + return 40; + } - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_int('upload_count', 3); - $config->set_default_int('upload_size', parse_shorthand_int('1MB')); - $config->set_default_int('upload_min_free_space', parse_shorthand_int('100MB')); - $config->set_default_bool('upload_tlsource', TRUE); + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_int('upload_count', 3); + $config->set_default_int('upload_size', parse_shorthand_int('1MB')); + $config->set_default_int('upload_min_free_space', parse_shorthand_int('100MB')); + $config->set_default_bool('upload_tlsource', true); - $this->is_full = false; + $this->is_full = false; - $min_free_space = $config->get_int("upload_min_free_space"); - if($min_free_space > 0) { - // SHIT: fucking PHP "security" measures -_-;;; - $free_num = @disk_free_space(realpath("./images/")); - if($free_num !== FALSE) { - $this->is_full = $free_num < $min_free_space; - } - } - } + $min_free_space = $config->get_int("upload_min_free_space"); + if ($min_free_space > 0) { + // SHIT: fucking PHP "security" measures -_-;;; + $free_num = @disk_free_space(realpath("./images/")); + if ($free_num !== false) { + $this->is_full = $free_num < $min_free_space; + } + } + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $tes = array(); - $tes["Disabled"] = "none"; - if(function_exists("curl_init")) { - $tes["cURL"] = "curl"; - } - $tes["fopen"] = "fopen"; - $tes["WGet"] = "wget"; + public function onSetupBuilding(SetupBuildingEvent $event) + { + $tes = []; + $tes["Disabled"] = "none"; + if (function_exists("curl_init")) { + $tes["cURL"] = "curl"; + } + $tes["fopen"] = "fopen"; + $tes["WGet"] = "wget"; - $sb = new SetupBlock("Upload"); - $sb->position = 10; - // Output the limits from PHP so the user has an idea of what they can set. - $sb->add_int_option("upload_count", "Max uploads: "); - $sb->add_label("PHP Limit = ".ini_get('max_file_uploads').""); - $sb->add_shorthand_int_option("upload_size", "
    Max size per file: "); - $sb->add_label("PHP Limit = ".ini_get('upload_max_filesize').""); - $sb->add_choice_option("transload_engine", $tes, "
    Transload: "); - $sb->add_bool_option("upload_tlsource", "
    Use transloaded URL as source if none is provided: "); - $event->panel->add_block($sb); - } + $sb = new SetupBlock("Upload"); + $sb->position = 10; + // Output the limits from PHP so the user has an idea of what they can set. + $sb->add_int_option("upload_count", "Max uploads: "); + $sb->add_label("PHP Limit = ".ini_get('max_file_uploads').""); + $sb->add_shorthand_int_option("upload_size", "
    Max size per file: "); + $sb->add_label("PHP Limit = ".ini_get('upload_max_filesize').""); + $sb->add_choice_option("transload_engine", $tes, "
    Transload: "); + $sb->add_bool_option("upload_tlsource", "
    Use transloaded URL as source if none is provided: "); + $event->panel->add_block($sb); + } - public function onDataUpload(DataUploadEvent $event) { - global $config; - if($this->is_full) { - throw new UploadException("Upload failed; disk nearly full"); - } - if(filesize($event->tmpname) > $config->get_int('upload_size')) { - $size = to_shorthand_int(filesize($event->tmpname)); - $limit = to_shorthand_int($config->get_int('upload_size')); - throw new UploadException("File too large ($size > $limit)"); - } - } + public function onDataUpload(DataUploadEvent $event) + { + global $config; + if ($this->is_full) { + throw new UploadException("Upload failed; disk nearly full"); + } + if (filesize($event->tmpname) > $config->get_int('upload_size')) { + $size = to_shorthand_int(filesize($event->tmpname)); + $limit = to_shorthand_int($config->get_int('upload_size')); + throw new UploadException("File too large ($size > $limit)"); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $database, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $database, $page, $user; - if($user->can("create_image")) { - if($this->is_full) { - $this->theme->display_full($page); - } - else { - $this->theme->display_block($page); - } - } + if ($user->can("create_image")) { + if ($this->is_full) { + $this->theme->display_full($page); + } else { + $this->theme->display_block($page); + } + } - if($event->page_matches("upload/replace")) { - // check if the user is an administrator and can upload files. - if(!$user->can("replace_image")) { - $this->theme->display_permission_denied(); - } - else { - if($this->is_full) { - throw new UploadException("Can not replace Image: disk nearly full"); - } - // Try to get the image ID - $image_id = int_escape($event->get_arg(0)); - if(empty($image_id)) { - $image_id = isset($_POST['image_id']) ? $_POST['image_id'] : null; - } - if(empty($image_id)) { - throw new UploadException("Can not replace Image: No valid Image ID given."); - } + if ($event->page_matches("upload/replace")) { + // check if the user is an administrator and can upload files. + if (!$user->can("replace_image")) { + $this->theme->display_permission_denied(); + } else { + if ($this->is_full) { + throw new UploadException("Can not replace Image: disk nearly full"); + } + // Try to get the image ID + $image_id = int_escape($event->get_arg(0)); + if (empty($image_id)) { + $image_id = isset($_POST['image_id']) ? $_POST['image_id'] : null; + } + if (empty($image_id)) { + throw new UploadException("Can not replace Image: No valid Image ID given."); + } - $image_old = Image::by_id($image_id); - if(is_null($image_old)) { - $this->theme->display_error(404, "Image not found", "No image in the database has the ID #$image_id"); - } + $image_old = Image::by_id($image_id); + if (is_null($image_old)) { + $this->theme->display_error(404, "Image not found", "No image in the database has the ID #$image_id"); + } - if(count($_FILES) + count($_POST) > 0) { - if(count($_FILES) > 1) { - throw new UploadException("Can not upload more than one image for replacing."); - } - - $source = isset($_POST['source']) ? $_POST['source'] : null; - $tags = array(); // Tags aren't changed when replacing. Set to empty to stop PHP warnings. - - $ok = false; - if(count($_FILES)) { - foreach($_FILES as $file) { - $ok = $this->try_upload($file, $tags, $source, $image_id); - break; // leave the foreach loop. - } - } - else { - foreach($_POST as $name => $value) { - if(substr($name, 0, 3) == "url" && strlen($value) > 0) { - $ok = $this->try_transload($value, $tags, $source, $image_id); - break; // leave the foreach loop. - } - } - } - $database->cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $ok); - } - else if(!empty($_GET['url'])) { - $url = $_GET['url']; - $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : 'tagme'; - $source = isset($_GET['source']) ? $_GET['source'] : $url; - $ok = $this->try_transload($url, $tags, $source, $image_id); - $database->cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $ok); - } - else { - $this->theme->display_replace_page($page, $image_id); - } - } - } - else if($event->page_matches("upload")) { - if(!$user->can("create_image")) { - $this->theme->display_permission_denied(); - } - else { - /* Regular Upload Image */ - if(count($_FILES) + count($_POST) > 0) { - $ok = true; - foreach($_FILES as $name => $file) { - $tags = $this->tags_for_upload_slot(int_escape(substr($name, 4))); - $source = isset($_POST['source']) ? $_POST['source'] : null; - $ok = $ok & $this->try_upload($file, $tags, $source); - } - foreach($_POST as $name => $value) { - if(substr($name, 0, 3) == "url" && strlen($value) > 0) { - $tags = $this->tags_for_upload_slot(int_escape(substr($name, 3))); - $source = isset($_POST['source']) ? $_POST['source'] : $value; - $ok = $ok & $this->try_transload($value, $tags, $source); - } - } + if (count($_FILES) + count($_POST) > 0) { + if (count($_FILES) > 1) { + throw new UploadException("Can not upload more than one image for replacing."); + } + + $source = isset($_POST['source']) ? $_POST['source'] : null; + $tags = []; // Tags aren't changed when replacing. Set to empty to stop PHP warnings. + + $ok = false; + if (count($_FILES)) { + foreach ($_FILES as $file) { + $ok = $this->try_upload($file, $tags, $source, $image_id); + break; // leave the foreach loop. + } + } else { + foreach ($_POST as $name => $value) { + if (substr($name, 0, 3) == "url" && strlen($value) > 0) { + $ok = $this->try_transload($value, $tags, $source, $image_id); + break; // leave the foreach loop. + } + } + } + $database->cache->delete("thumb-block:{$image_id}"); + $this->theme->display_upload_status($page, $ok); + } elseif (!empty($_GET['url'])) { + $url = $_GET['url']; + $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : 'tagme'; + $source = isset($_GET['source']) ? $_GET['source'] : $url; + $ok = $this->try_transload($url, $tags, $source, $image_id); + $database->cache->delete("thumb-block:{$image_id}"); + $this->theme->display_upload_status($page, $ok); + } else { + $this->theme->display_replace_page($page, $image_id); + } + } + } elseif ($event->page_matches("upload")) { + if (!$user->can("create_image")) { + $this->theme->display_permission_denied(); + } else { + /* Regular Upload Image */ + if (count($_FILES) + count($_POST) > 0) { + $ok = true; + foreach ($_FILES as $name => $file) { + $tags = $this->tags_for_upload_slot(int_escape(substr($name, 4))); + $source = isset($_POST['source']) ? $_POST['source'] : null; + $ok = $ok & $this->try_upload($file, $tags, $source); + } + foreach ($_POST as $name => $value) { + if (substr($name, 0, 3) == "url" && strlen($value) > 0) { + $tags = $this->tags_for_upload_slot(int_escape(substr($name, 3))); + $source = isset($_POST['source']) ? $_POST['source'] : $value; + $ok = $ok & $this->try_transload($value, $tags, $source); + } + } - $this->theme->display_upload_status($page, $ok); - } - else if(!empty($_GET['url'])) { - $url = $_GET['url']; - $source = isset($_GET['source']) ? $_GET['source'] : $url; - $tags = array('tagme'); - if(!empty($_GET['tags']) && $_GET['tags'] != "null") { - $tags = Tag::explode($_GET['tags']); - } - - $ok = $this->try_transload($url, $tags, $source); - $this->theme->display_upload_status($page, $ok); - } - else { - if ($this->is_full) { - $this->theme->display_full($page); - } else { - $this->theme->display_page($page); - } - } - } - } - } + $this->theme->display_upload_status($page, $ok); + } elseif (!empty($_GET['url'])) { + $url = $_GET['url']; + $source = isset($_GET['source']) ? $_GET['source'] : $url; + $tags = ['tagme']; + if (!empty($_GET['tags']) && $_GET['tags'] != "null") { + $tags = Tag::explode($_GET['tags']); + } + + $ok = $this->try_transload($url, $tags, $source); + $this->theme->display_upload_status($page, $ok); + } else { + if ($this->is_full) { + $this->theme->display_full($page); + } else { + $this->theme->display_page($page); + } + } + } + } + } - private function tags_for_upload_slot(int $id): array { - $post_tags = isset($_POST["tags"]) ? $_POST["tags"] : ""; + private function tags_for_upload_slot(int $id): array + { + $post_tags = isset($_POST["tags"]) ? $_POST["tags"] : ""; - if(isset($_POST["tags$id"])) { - # merge then explode, not explode then merge - else - # one of the merges may create a surplus "tagme" - $tags = Tag::explode($post_tags . " " . $_POST["tags$id"]); - } - else { - $tags = Tag::explode($post_tags); - } - return $tags; - } + if (isset($_POST["tags$id"])) { + # merge then explode, not explode then merge - else + # one of the merges may create a surplus "tagme" + $tags = Tag::explode($post_tags . " " . $_POST["tags$id"]); + } else { + $tags = Tag::explode($post_tags); + } + return $tags; + } -// do things {{{ + // do things {{{ - /** - * Returns a descriptive error message for the specified PHP error code. - * - * This is a helper function based on the one from the online PHP Documentation - * which is licensed under Creative Commons Attribution 3.0 License - * - * TODO: Make these messages user/admin editable - */ - private function upload_error_message(int $error_code): string { - switch ($error_code) { - case UPLOAD_ERR_INI_SIZE: - return 'The uploaded file exceeds the upload_max_filesize directive in php.ini'; - case UPLOAD_ERR_FORM_SIZE: - return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'; - case UPLOAD_ERR_PARTIAL: - return 'The uploaded file was only partially uploaded'; - case UPLOAD_ERR_NO_FILE: - return 'No file was uploaded'; - case UPLOAD_ERR_NO_TMP_DIR: - return 'Missing a temporary folder'; - case UPLOAD_ERR_CANT_WRITE: - return 'Failed to write file to disk'; - case UPLOAD_ERR_EXTENSION: - return 'File upload stopped by extension'; - default: - return 'Unknown upload error'; - } - } + /** + * Returns a descriptive error message for the specified PHP error code. + * + * This is a helper function based on the one from the online PHP Documentation + * which is licensed under Creative Commons Attribution 3.0 License + * + * TODO: Make these messages user/admin editable + */ + private function upload_error_message(int $error_code): string + { + switch ($error_code) { + case UPLOAD_ERR_INI_SIZE: + return 'The uploaded file exceeds the upload_max_filesize directive in php.ini'; + case UPLOAD_ERR_FORM_SIZE: + return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'; + case UPLOAD_ERR_PARTIAL: + return 'The uploaded file was only partially uploaded'; + case UPLOAD_ERR_NO_FILE: + return 'No file was uploaded'; + case UPLOAD_ERR_NO_TMP_DIR: + return 'Missing a temporary folder'; + case UPLOAD_ERR_CANT_WRITE: + return 'Failed to write file to disk'; + case UPLOAD_ERR_EXTENSION: + return 'File upload stopped by extension'; + default: + return 'Unknown upload error'; + } + } - /** - * Handle an upload. - * #param string[] $file - * #param string[] $tags - */ - private function try_upload(array $file, array $tags, ?string $source=null, int $replace=-1): bool { - global $page; + /** + * Handle an upload. + * #param string[] $file + * #param string[] $tags + */ + private function try_upload(array $file, array $tags, ?string $source=null, int $replace=-1): bool + { + global $page; - if(empty($source)) $source = null; + if (empty($source)) { + $source = null; + } - $ok = true; + $ok = true; - // blank file boxes cause empty uploads, no need for error message - if (!empty($file['name'])) { - try { - // check if the upload was successful - if ($file['error'] !== UPLOAD_ERR_OK) { - throw new UploadException($this->upload_error_message($file['error'])); - } - - $pathinfo = pathinfo($file['name']); - $metadata = array(); - $metadata['filename'] = $pathinfo['basename']; - $metadata['extension'] = $pathinfo['extension']; - $metadata['tags'] = $tags; - $metadata['source'] = $source; - - /* check if we have been given an image ID to replace */ - if ($replace >= 0) { - $metadata['replace'] = $replace; - } - - $event = new DataUploadEvent($file['tmp_name'], $metadata); - send_event($event); - if($event->image_id == -1) { - throw new UploadException("File type not recognised"); - } - $page->add_http_header("X-Shimmie-Image-ID: ".int_escape($event->image_id)); - } - catch(UploadException $ex) { - $this->theme->display_upload_error($page, "Error with ".html_escape($file['name']), - $ex->getMessage()); - $ok = false; - } - } + // blank file boxes cause empty uploads, no need for error message + if (!empty($file['name'])) { + try { + // check if the upload was successful + if ($file['error'] !== UPLOAD_ERR_OK) { + throw new UploadException($this->upload_error_message($file['error'])); + } + + $pathinfo = pathinfo($file['name']); + $metadata = []; + $metadata['filename'] = $pathinfo['basename']; + $metadata['extension'] = $pathinfo['extension']; + $metadata['tags'] = $tags; + $metadata['source'] = $source; + + /* check if we have been given an image ID to replace */ + if ($replace >= 0) { + $metadata['replace'] = $replace; + } + + $event = new DataUploadEvent($file['tmp_name'], $metadata); + send_event($event); + if ($event->image_id == -1) { + throw new UploadException("File type not recognised"); + } + $page->add_http_header("X-Shimmie-Image-ID: ".int_escape($event->image_id)); + } catch (UploadException $ex) { + $this->theme->display_upload_error( + $page, + "Error with ".html_escape($file['name']), + $ex->getMessage() + ); + $ok = false; + } + } - return $ok; - } + return $ok; + } - private function try_transload(string $url, array $tags, string $source=null, int $replace=-1): bool { - global $page, $config, $user; + private function try_transload(string $url, array $tags, string $source=null, int $replace=-1): bool + { + global $page, $config, $user; - $ok = true; + $ok = true; - // Checks if user is admin > check if you want locked. - if($user->can("edit_image_lock") && !empty($_GET['locked'])){ - $locked = bool_escape($_GET['locked']); - } - - // Checks if url contains rating, also checks if the rating extension is enabled. - if($config->get_string("transload_engine", "none") != "none" && ext_is_live("Ratings") && !empty($_GET['rating'])) { - // Rating event will validate that this is s/q/e/u - $rating = strtolower($_GET['rating']); - $rating = $rating[0]; - }else{ - $rating = ""; - } + // Checks if user is admin > check if you want locked. + if ($user->can("edit_image_lock") && !empty($_GET['locked'])) { + $locked = bool_escape($_GET['locked']); + } + + // Checks if url contains rating, also checks if the rating extension is enabled. + if ($config->get_string("transload_engine", "none") != "none" && ext_is_live("Ratings") && !empty($_GET['rating'])) { + // Rating event will validate that this is s/q/e/u + $rating = strtolower($_GET['rating']); + $rating = $rating[0]; + } else { + $rating = ""; + } - $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); + $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); - // transload() returns Array or Bool, depending on the transload_engine. - $headers = transload($url, $tmp_filename); - - $s_filename = is_array($headers) ? findHeader($headers, 'Content-Disposition') : null; - $h_filename = ($s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null); - $filename = $h_filename ?: basename($url); + // transload() returns Array or Bool, depending on the transload_engine. + $headers = transload($url, $tmp_filename); + + $s_filename = is_array($headers) ? findHeader($headers, 'Content-Disposition') : null; + $h_filename = ($s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null); + $filename = $h_filename ?: basename($url); - if(!$headers) { - $this->theme->display_upload_error($page, "Error with ".html_escape($filename), - "Error reading from ".html_escape($url)); - return false; - } + if (!$headers) { + $this->theme->display_upload_error( + $page, + "Error with ".html_escape($filename), + "Error reading from ".html_escape($url) + ); + return false; + } - if(filesize($tmp_filename) == 0) { - $this->theme->display_upload_error($page, "Error with ".html_escape($filename), - "No data found -- perhaps the site has hotlink protection?"); - $ok = false; - }else{ - $pathinfo = pathinfo($url); - $metadata = array(); - $metadata['filename'] = $filename; - $metadata['tags'] = $tags; - $metadata['source'] = (($url == $source) && !$config->get_bool('upload_tlsource') ? "" : $source); - - $ext = false; - if (is_array($headers)) { - $ext = getExtension(findHeader($headers, 'Content-Type')); - } - if ($ext === false) { - $ext = $pathinfo['extension']; - } - $metadata['extension'] = $ext; - - /* check for locked > adds to metadata if it has */ - if(!empty($locked)){ - $metadata['locked'] = $locked ? "on" : ""; - } + if (filesize($tmp_filename) == 0) { + $this->theme->display_upload_error( + $page, + "Error with ".html_escape($filename), + "No data found -- perhaps the site has hotlink protection?" + ); + $ok = false; + } else { + $pathinfo = pathinfo($url); + $metadata = []; + $metadata['filename'] = $filename; + $metadata['tags'] = $tags; + $metadata['source'] = (($url == $source) && !$config->get_bool('upload_tlsource') ? "" : $source); + + $ext = false; + if (is_array($headers)) { + $ext = getExtension(findHeader($headers, 'Content-Type')); + } + if ($ext === false) { + $ext = $pathinfo['extension']; + } + $metadata['extension'] = $ext; + + /* check for locked > adds to metadata if it has */ + if (!empty($locked)) { + $metadata['locked'] = $locked ? "on" : ""; + } - /* check for rating > adds to metadata if it has */ - if(!empty($rating)){ - $metadata['rating'] = $rating; - } - - /* check if we have been given an image ID to replace */ - if ($replace >= 0) { - $metadata['replace'] = $replace; - } - - $event = new DataUploadEvent($tmp_filename, $metadata); - try { - send_event($event); - } - catch(UploadException $ex) { - $this->theme->display_upload_error($page, "Error with ".html_escape($url), - $ex->getMessage()); - $ok = false; - } - } + /* check for rating > adds to metadata if it has */ + if (!empty($rating)) { + $metadata['rating'] = $rating; + } + + /* check if we have been given an image ID to replace */ + if ($replace >= 0) { + $metadata['replace'] = $replace; + } + + $event = new DataUploadEvent($tmp_filename, $metadata); + try { + send_event($event); + } catch (UploadException $ex) { + $this->theme->display_upload_error( + $page, + "Error with ".html_escape($url), + $ex->getMessage() + ); + $ok = false; + } + } - unlink($tmp_filename); + unlink($tmp_filename); - return $ok; - } -// }}} + return $ok; + } + // }}} } - diff --git a/ext/upload/test.php b/ext/upload/test.php index b1044202..8b4eb618 100644 --- a/ext/upload/test.php +++ b/ext/upload/test.php @@ -1,47 +1,50 @@ log_in_as_user(); +class UploadTest extends ShimmiePHPUnitTestCase +{ + public function testUploadPage() + { + $this->log_in_as_user(); - $this->get_page("upload"); - $this->assert_title("Upload"); - } + $this->get_page("upload"); + $this->assert_title("Upload"); + } - public function testUpload() { - $this->log_in_as_user(); - $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - } + public function testUpload() + { + $this->log_in_as_user(); + $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + } - public function testRejectDupe() { - $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + public function testRejectDupe() + { + $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - try { - $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - } - catch(UploadException $e) { - $this->assertContains("already has hash", $e->getMessage()); - } - } + try { + $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + } catch (UploadException $e) { + $this->assertContains("already has hash", $e->getMessage()); + } + } - public function testRejectUnknownFiletype() { - try { - $this->post_image("index.php", "test"); - } - catch(UploadException $e) { - $this->assertContains("Invalid or corrupted file", $e->getMessage()); - } - } + public function testRejectUnknownFiletype() + { + try { + $this->post_image("index.php", "test"); + } catch (UploadException $e) { + $this->assertContains("Invalid or corrupted file", $e->getMessage()); + } + } - public function testRejectHuge() { - $this->markTestIncomplete(); + public function testRejectHuge() + { + $this->markTestIncomplete(); - // FIXME: huge.dat is rejected for other reasons; manual testing shows that this works - file_put_contents("huge.dat", file_get_contents("tests/pbx_screenshot.jpg") . str_repeat("U", 1024*1024*3)); - $this->post_image("index.php", "test"); - $this->assert_response(200); - $this->assert_title("Upload Status"); - $this->assert_text("File too large"); - unlink("huge.dat"); - } + // FIXME: huge.dat is rejected for other reasons; manual testing shows that this works + file_put_contents("huge.dat", file_get_contents("tests/pbx_screenshot.jpg") . str_repeat("U", 1024*1024*3)); + $this->post_image("index.php", "test"); + $this->assert_response(200); + $this->assert_title("Upload Status"); + $this->assert_text("File too large"); + unlink("huge.dat"); + } } - diff --git a/ext/upload/theme.php b/ext/upload/theme.php index 934a1f91..6f0c11da 100644 --- a/ext/upload/theme.php +++ b/ext/upload/theme.php @@ -1,23 +1,27 @@ add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); - } +class UploadTheme extends Themelet +{ + public function display_block(Page $page) + { + $page->add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); + } - public function display_full(Page $page) { - $page->add_block(new Block("Upload", "Disk nearly full, uploads disabled", "left", 20)); - } + public function display_full(Page $page) + { + $page->add_block(new Block("Upload", "Disk nearly full, uploads disabled", "left", 20)); + } - public function display_page(Page $page) { - global $config, $page; + public function display_page(Page $page) + { + global $config, $page; - $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); - $max_size = $config->get_int('upload_size'); - $max_kb = to_shorthand_int($max_size); - $upload_list = $this->h_upload_list_1(); - $html = " - ".make_form(make_link("upload"), "POST", $multipart=True, 'file_upload')." + $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); + $max_size = $config->get_int('upload_size'); + $max_kb = to_shorthand_int($max_size); + $upload_list = $this->h_upload_list_1(); + $html = " + ".make_form(make_link("upload"), "POST", $multipart=true, 'file_upload')." @@ -27,24 +31,25 @@ class UploadTheme extends Themelet { (Max file size is $max_kb) "; - - $page->set_title("Upload"); - $page->set_heading("Upload"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Upload", $html, "main", 20)); - if($tl_enabled) { - $page->add_block(new Block("Bookmarklets", $this->h_bookmarklets(), "left", 20)); - } - } + + $page->set_title("Upload"); + $page->set_heading("Upload"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Upload", $html, "main", 20)); + if ($tl_enabled) { + $page->add_block(new Block("Bookmarklets", $this->h_bookmarklets(), "left", 20)); + } + } - protected function h_upload_list_1(): string { - global $config; - $upload_list = ""; - $upload_count = $config->get_int('upload_count'); - $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); + protected function h_upload_list_1(): string + { + global $config; + $upload_list = ""; + $upload_count = $config->get_int('upload_count'); + $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); - if($tl_enabled) { - $upload_list .= " + if ($tl_enabled) { + $upload_list .= " @@ -52,145 +57,145 @@ class UploadTheme extends Themelet { "; - for($i=0; $i<$upload_count; $i++) { - $upload_list .= " + for ($i=0; $i<$upload_count; $i++) { + $upload_list .= " "; - } - } - else { - $upload_list .= " + } + } else { + $upload_list .= " "; - for($i=0; $i<$upload_count; $i++) { - $upload_list .= " + for ($i=0; $i<$upload_count; $i++) { + $upload_list .= " "; - } - } + } + } - return $upload_list; - } + return $upload_list; + } - protected function h_upload_List_2(): string { - global $config; + protected function h_upload_List_2(): string + { + global $config; - $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); - // Uploader 2.0! - $upload_list = ""; - $upload_count = $config->get_int('upload_count'); - - for($i=0; $i<$upload_count; $i++) { - $a = $i+1; - $s = $i-1; - - if($i != 0) { - $upload_list .=""; - }else{ - $upload_list .= ""; - } - - $upload_list .= ""; + } else { + $upload_list .= ""; + } + + $upload_list .= ""; - - $js2 = 'javascript:$(function() { + + $upload_list .= + "". + ""; + } + $upload_list .= ""; + } + $upload_list .= ""; + + $js2 = 'javascript:$(function() { $("#url'.$i.'").hide(); $("#url'.$i.'").val(""); $("#data'.$i.'").show(); });'; - $upload_list .= " + $upload_list .= " + + $upload_list .= + " URL"; - } else { - $upload_list .= " + } else { + $upload_list .= " "; - } - - $upload_list .= " + } + + $upload_list .= " "; - } + } - return $upload_list; - } + return $upload_list; + } - protected function h_bookmarklets(): string { - global $config; - $link = make_http(make_link("upload")); - $main_page = make_http(make_link()); - $title = $config->get_string('title'); - $max_size = $config->get_int('upload_size'); - $max_kb = to_shorthand_int($max_size); - $delimiter = $config->get_bool('nice_urls') ? '?' : '&'; - $html = ''; + protected function h_bookmarklets(): string + { + global $config; + $link = make_http(make_link("upload")); + $main_page = make_http(make_link()); + $title = $config->get_string('title'); + $max_size = $config->get_int('upload_size'); + $max_kb = to_shorthand_int($max_size); + $delimiter = $config->get_bool('nice_urls') ? '?' : '&'; + $html = ''; - $js='javascript:( + $js='javascript:( function() { if(typeof window=="undefined" || !window.location || window.location.href=="about:blank") { window.location = "'. $main_page .'"; @@ -210,19 +215,29 @@ class UploadTheme extends Themelet { } } )();'; - $html .= 'Upload to '.$title.''; - $html .= ' (Drag & drop onto your bookmarks toolbar, then click when looking at an image)'; + $html .= 'Upload to '.$title.''; + $html .= ' (Drag & drop onto your bookmarks toolbar, then click when looking at an image)'; - // Bookmarklet checks if shimmie supports ext. If not, won't upload to site/shows alert saying not supported. - $supported_ext = "jpg jpeg gif png"; - if(class_exists("FlashFileHandler")){$supported_ext .= " swf";} - if(class_exists("ICOFileHandler")){$supported_ext .= " ico ani cur";} - if(class_exists("MP3FileHandler")){$supported_ext .= " mp3";} - if(class_exists("SVGFileHandler")){$supported_ext .= " svg";} - if(class_exists("VideoFileHandler")){$supported_ext .= " flv mp4 ogv webm m4v";} - $title = "Booru to " . $config->get_string('title'); - // CA=0: Ask to use current or new tags | CA=1: Always use current tags | CA=2: Always use new tags - $html .= '

    get_string('title'); + // CA=0: Ask to use current or new tags | CA=1: Always use current tags | CA=2: Always use new tags + $html .= '

    '. $title . ' (Click when looking at an image page. Works on sites running Shimmie / Danbooru / Gelbooru. (This also grabs the tags / rating / source!))'; - return $html; - } + return $html; + } - /** - * Only allows 1 file to be uploaded - for replacing another image file. - */ - public function display_replace_page(Page $page, int $image_id) { - global $config, $page; - $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); + /** + * Only allows 1 file to be uploaded - for replacing another image file. + */ + public function display_replace_page(Page $page, int $image_id) + { + global $config, $page; + $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); - $upload_list = " + $upload_list = "

    "; - if($tl_enabled) { - $upload_list .=" + if ($tl_enabled) { + $upload_list .=" "; - } + } - $max_size = $config->get_int('upload_size'); - $max_kb = to_shorthand_int($max_size); - - $image = Image::by_id($image_id); - $thumbnail = $this->build_thumb_html($image); - - $html = " + $max_size = $config->get_int('upload_size'); + $max_kb = to_shorthand_int($max_size); + + $image = Image::by_id($image_id); + $thumbnail = $this->build_thumb_html($image); + + $html = "

    Replacing Image ID ".$image_id."
    Please note: You will have to refresh the image page, or empty your browser cache.

    " - .$thumbnail."
    " - .make_form(make_link("upload/replace/".$image_id), "POST", $multipart=True)." + .$thumbnail."
    " + .make_form(make_link("upload/replace/".$image_id), "POST", $multipart=true)."
    Common Tags
    Common Source
    Files URLs
    Files Image-Specific Tags
    "; - - if($i == 0) { - $js = 'javascript:$(function() { + $tl_enabled = ($config->get_string("transload_engine", "none") != "none"); + // Uploader 2.0! + $upload_list = ""; + $upload_count = $config->get_int('upload_count'); + + for ($i=0; $i<$upload_count; $i++) { + $a = $i+1; + $s = $i-1; + + if ($i != 0) { + $upload_list .="
    "; + + if ($i == 0) { + $js = 'javascript:$(function() { $("#row'.$a.'").show(); $("#hide'.$i.'").hide(); $("#hide'.$a.'").show();});'; - - $upload_list .= " + + $upload_list .= "
    "; - } else { - $js = 'javascript:$(function() { + } else { + $js = 'javascript:$(function() { $("#row'.$i.'").hide(); $("#hide'.$i.'").hide(); $("#hide'.$s.'").show(); $("#data'.$i.'").val(""); $("#url'.$i.'").val(""); });'; - - $upload_list .=" + + $upload_list .="
    "; - - if($a == $upload_count){ - $upload_list .=""; - } - else{ - $js1 = 'javascript:$(function() { + + if ($a == $upload_count) { + $upload_list .=""; + } else { + $js1 = 'javascript:$(function() { $("#row'.$a.'").show(); $("#hide'.$i.'").hide(); $("#hide'.$a.'").show(); });'; - - $upload_list .= - "". - ""; - } - $upload_list .= "
    "; - } - $upload_list .= "
    File
    "; - - if($tl_enabled) { - $js = 'javascript:$(function() { + + if ($tl_enabled) { + $js = 'javascript:$(function() { $("#data'.$i.'").hide(); $("#data'.$i.'").val(""); $("#url'.$i.'").show(); });'; - - $upload_list .= - " URL
    File
    or URL
    $upload_list @@ -275,45 +291,51 @@ class UploadTheme extends Themelet { (Max file size is $max_kb) "; - $page->set_title("Replace Image"); - $page->set_heading("Replace Image"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Upload Replacement Image", $html, "main", 20)); - } + $page->set_title("Replace Image"); + $page->set_heading("Replace Image"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Upload Replacement Image", $html, "main", 20)); + } - public function display_upload_status(Page $page, bool $ok) { - if($ok) { - $page->set_mode("redirect"); - $page->set_redirect(make_link()); - } - else { - $page->set_title("Upload Status"); - $page->set_heading("Upload Status"); - $page->add_block(new NavBlock()); - } - } + public function display_upload_status(Page $page, bool $ok) + { + if ($ok) { + $page->set_mode("redirect"); + $page->set_redirect(make_link()); + } else { + $page->set_title("Upload Status"); + $page->set_heading("Upload Status"); + $page->add_block(new NavBlock()); + } + } - public function display_upload_error(Page $page, string $title, string $message) { - $page->add_block(new Block($title, $message)); - } + public function display_upload_error(Page $page, string $title, string $message) + { + $page->add_block(new Block($title, $message)); + } - protected function build_upload_block(): string { - global $config; + protected function build_upload_block(): string + { + global $config; - $upload_list = ""; - $upload_count = $config->get_int('upload_count'); - - for($i=0; $i<$upload_count; $i++) { - if($i == 0) $style = ""; // "style='display:visible'"; - else $style = "style='display:none'"; - $upload_list .= "\n"; - } - $max_size = $config->get_int('upload_size'); - $max_kb = to_shorthand_int($max_size); - // - return " + $upload_list = ""; + $upload_count = $config->get_int('upload_count'); + + for ($i=0; $i<$upload_count; $i++) { + if ($i == 0) { + $style = ""; + } // "style='display:visible'"; + else { + $style = "style='display:none'"; + } + $upload_list .= "\n"; + } + $max_size = $config->get_int('upload_size'); + $max_kb = to_shorthand_int($max_size); + // + return "
    - ".make_form(make_link("upload"), "POST", $multipart=True)." + ".make_form(make_link("upload"), "POST", $multipart=true)." $upload_list @@ -322,6 +344,5 @@ class UploadTheme extends Themelet {
    "; - } + } } - diff --git a/ext/user/main.php b/ext/user/main.php index b998469c..1d5033ff 100644 --- a/ext/user/main.php +++ b/ext/user/main.php @@ -5,563 +5,604 @@ * Description: Allows people to sign up to the website */ -class UserBlockBuildingEvent extends Event { - /** @var array */ - public $parts = array(); +class UserBlockBuildingEvent extends Event +{ + /** @var array */ + public $parts = []; - public function add_link(string $name, string $link, int $position=50) { - while(isset($this->parts[$position])) $position++; - $this->parts[$position] = array("name" => $name, "link" => $link); - } + public function add_link(string $name, string $link, int $position=50) + { + while (isset($this->parts[$position])) { + $position++; + } + $this->parts[$position] = ["name" => $name, "link" => $link]; + } } -class UserPageBuildingEvent extends Event { - /** @var \User */ - public $display_user; - /** @var array */ - public $stats = array(); +class UserPageBuildingEvent extends Event +{ + /** @var \User */ + public $display_user; + /** @var array */ + public $stats = []; - public function __construct(User $display_user) { - $this->display_user = $display_user; - } + public function __construct(User $display_user) + { + $this->display_user = $display_user; + } - public function add_stats(string $html, int $position=50) { - while(isset($this->stats[$position])) { $position++; } - $this->stats[$position] = $html; - } + public function add_stats(string $html, int $position=50) + { + while (isset($this->stats[$position])) { + $position++; + } + $this->stats[$position] = $html; + } } -class UserCreationEvent extends Event { - /** @var string */ - public $username; - /** @var string */ - public $password; - /** @var string */ - public $email; +class UserCreationEvent extends Event +{ + /** @var string */ + public $username; + /** @var string */ + public $password; + /** @var string */ + public $email; - public function __construct(string $name, string $pass, string $email) { - $this->username = $name; - $this->password = $pass; - $this->email = $email; - } + public function __construct(string $name, string $pass, string $email) + { + $this->username = $name; + $this->password = $pass; + $this->email = $email; + } } -class UserDeletionEvent extends Event { - /** @var int */ - public $id; +class UserDeletionEvent extends Event +{ + /** @var int */ + public $id; - public function __construct(int $id) { - $this->id = $id; - } + public function __construct(int $id) + { + $this->id = $id; + } } -class UserCreationException extends SCoreException {} +class UserCreationException extends SCoreException +{ +} -class NullUserException extends SCoreException {} +class NullUserException extends SCoreException +{ +} -class UserPage extends Extension { - /** @var UserPageTheme $theme */ - public $theme; +class UserPage extends Extension +{ + /** @var UserPageTheme $theme */ + public $theme; - public function onInitExt(InitExtEvent $event) { - global $config; - $config->set_default_bool("login_signup_enabled", true); - $config->set_default_int("login_memory", 365); - $config->set_default_string("avatar_host", "none"); - $config->set_default_int("avatar_gravatar_size", 80); - $config->set_default_string("avatar_gravatar_default", ""); - $config->set_default_string("avatar_gravatar_rating", "g"); - $config->set_default_bool("login_tac_bbcode", true); - } + public function onInitExt(InitExtEvent $event) + { + global $config; + $config->set_default_bool("login_signup_enabled", true); + $config->set_default_int("login_memory", 365); + $config->set_default_string("avatar_host", "none"); + $config->set_default_int("avatar_gravatar_size", 80); + $config->set_default_string("avatar_gravatar_default", ""); + $config->set_default_string("avatar_gravatar_rating", "g"); + $config->set_default_bool("login_tac_bbcode", true); + } - public function onPageRequest(PageRequestEvent $event) { - global $config, $database, $page, $user; + public function onPageRequest(PageRequestEvent $event) + { + global $config, $database, $page, $user; - $this->show_user_info(); + $this->show_user_info(); - if($event->page_matches("user_admin")) { - if($event->get_arg(0) == "login") { - if(isset($_POST['user']) && isset($_POST['pass'])) { - $this->page_login($_POST['user'], $_POST['pass']); - } - else { - $this->theme->display_login_page($page); - } - } - else if($event->get_arg(0) == "recover") { - $this->page_recover($_POST['username']); - } - else if($event->get_arg(0) == "create") { - $this->page_create(); - } - else if($event->get_arg(0) == "list") { - $limit = 50; + if ($event->page_matches("user_admin")) { + if ($event->get_arg(0) == "login") { + if (isset($_POST['user']) && isset($_POST['pass'])) { + $this->page_login($_POST['user'], $_POST['pass']); + } else { + $this->theme->display_login_page($page); + } + } elseif ($event->get_arg(0) == "recover") { + $this->page_recover($_POST['username']); + } elseif ($event->get_arg(0) == "create") { + $this->page_create(); + } elseif ($event->get_arg(0) == "list") { + $limit = 50; - $page_num = int_escape($event->get_arg(1)); - if($page_num <= 0) $page_num = 1; - $offset = ($page_num-1) * $limit; + $page_num = int_escape($event->get_arg(1)); + if ($page_num <= 0) { + $page_num = 1; + } + $offset = ($page_num-1) * $limit; - $q = "WHERE 1=1"; - $a = array(); + $q = "WHERE 1=1"; + $a = []; - if(@$_GET['username']) { - $q .= " AND SCORE_STRNORM(name) LIKE SCORE_STRNORM(:name)"; - $a["name"] = '%' . $_GET['username'] . '%'; - } + if (@$_GET['username']) { + $q .= " AND SCORE_STRNORM(name) LIKE SCORE_STRNORM(:name)"; + $a["name"] = '%' . $_GET['username'] . '%'; + } - if($user->can('delete_user') && @$_GET['email']) { - $q .= " AND SCORE_STRNORM(email) LIKE SCORE_STRNORM(:email)"; - $a["email"] = '%' . $_GET['email'] . '%'; - } + if ($user->can('delete_user') && @$_GET['email']) { + $q .= " AND SCORE_STRNORM(email) LIKE SCORE_STRNORM(:email)"; + $a["email"] = '%' . $_GET['email'] . '%'; + } - if(@$_GET['class']) { - $q .= " AND class LIKE :class"; - $a["class"] = $_GET['class']; - } - $where = $database->scoreql_to_sql($q); + if (@$_GET['class']) { + $q .= " AND class LIKE :class"; + $a["class"] = $_GET['class']; + } + $where = $database->scoreql_to_sql($q); - $count = $database->get_one("SELECT count(*) FROM users $where", $a); - $a["offset"] = $offset; - $a["limit"] = $limit; - $rows = $database->get_all("SELECT * FROM users $where LIMIT :limit OFFSET :offset", $a); - $users = array_map("_new_user", $rows); - $this->theme->display_user_list($page, $users, $user, $page_num, $count/$limit); - } - else if($event->get_arg(0) == "logout") { - $this->page_logout(); - } + $count = $database->get_one("SELECT count(*) FROM users $where", $a); + $a["offset"] = $offset; + $a["limit"] = $limit; + $rows = $database->get_all("SELECT * FROM users $where LIMIT :limit OFFSET :offset", $a); + $users = array_map("_new_user", $rows); + $this->theme->display_user_list($page, $users, $user, $page_num, $count/$limit); + } elseif ($event->get_arg(0) == "logout") { + $this->page_logout(); + } - if(!$user->check_auth_token()) { - return; - } + if (!$user->check_auth_token()) { + return; + } elseif ($event->get_arg(0) == "change_name") { + $input = validate_input([ + 'id' => 'user_id,exists', + 'name' => 'user_name', + ]); + $duser = User::by_id($input['id']); + $this->change_name_wrapper($duser, $input['name']); + } elseif ($event->get_arg(0) == "change_pass") { + $input = validate_input([ + 'id' => 'user_id,exists', + 'pass1' => 'password', + 'pass2' => 'password', + ]); + $duser = User::by_id($input['id']); + $this->change_password_wrapper($duser, $input['pass1'], $input['pass2']); + } elseif ($event->get_arg(0) == "change_email") { + $input = validate_input([ + 'id' => 'user_id,exists', + 'address' => 'email', + ]); + $duser = User::by_id($input['id']); + $this->change_email_wrapper($duser, $input['address']); + } elseif ($event->get_arg(0) == "change_class") { + $input = validate_input([ + 'id' => 'user_id,exists', + 'class' => 'user_class', + ]); + $duser = User::by_id($input['id']); + $this->change_class_wrapper($duser, $input['class']); + } elseif ($event->get_arg(0) == "delete_user") { + $this->delete_user($page, isset($_POST["with_images"]), isset($_POST["with_comments"])); + } + } - else if($event->get_arg(0) == "change_name") { - $input = validate_input(array( - 'id' => 'user_id,exists', - 'name' => 'user_name', - )); - $duser = User::by_id($input['id']); - $this->change_name_wrapper($duser, $input['name']); - } - else if($event->get_arg(0) == "change_pass") { - $input = validate_input(array( - 'id' => 'user_id,exists', - 'pass1' => 'password', - 'pass2' => 'password', - )); - $duser = User::by_id($input['id']); - $this->change_password_wrapper($duser, $input['pass1'], $input['pass2']); - } - else if($event->get_arg(0) == "change_email") { - $input = validate_input(array( - 'id' => 'user_id,exists', - 'address' => 'email', - )); - $duser = User::by_id($input['id']); - $this->change_email_wrapper($duser, $input['address']); - } - else if($event->get_arg(0) == "change_class") { - $input = validate_input(array( - 'id' => 'user_id,exists', - 'class' => 'user_class', - )); - $duser = User::by_id($input['id']); - $this->change_class_wrapper($duser, $input['class']); - } - else if($event->get_arg(0) == "delete_user") { - $this->delete_user($page, isset($_POST["with_images"]), isset($_POST["with_comments"])); - } - } + if ($event->page_matches("user")) { + $display_user = ($event->count_args() == 0) ? $user : User::by_name($event->get_arg(0)); + if ($event->count_args() == 0 && $user->is_anonymous()) { + $this->theme->display_error( + 401, + "Not Logged In", + "You aren't logged in. First do that, then you can see your stats." + ); + } elseif (!is_null($display_user) && ($display_user->id != $config->get_int("anon_id"))) { + $e = new UserPageBuildingEvent($display_user); + send_event($e); + $this->display_stats($e); + } else { + $this->theme->display_error( + 404, + "No Such User", + "If you typed the ID by hand, try again; if you came from a link on this ". + "site, it might be bug report time..." + ); + } + } + } - if($event->page_matches("user")) { - $display_user = ($event->count_args() == 0) ? $user : User::by_name($event->get_arg(0)); - if($event->count_args() == 0 && $user->is_anonymous()) { - $this->theme->display_error(401, "Not Logged In", - "You aren't logged in. First do that, then you can see your stats."); - } - else if(!is_null($display_user) && ($display_user->id != $config->get_int("anon_id"))) { - $e = new UserPageBuildingEvent($display_user); - send_event($e); - $this->display_stats($e); - } - else { - $this->theme->display_error(404, "No Such User", - "If you typed the ID by hand, try again; if you came from a link on this ". - "site, it might be bug report time..."); - } - } - } + public function onUserPageBuilding(UserPageBuildingEvent $event) + { + global $user, $config; - public function onUserPageBuilding(UserPageBuildingEvent $event) { - global $user, $config; + $h_join_date = autodate($event->display_user->join_date); + if ($event->display_user->can("hellbanned")) { + $h_class = $event->display_user->class->parent->name; + } else { + $h_class = $event->display_user->class->name; + } - $h_join_date = autodate($event->display_user->join_date); - if($event->display_user->can("hellbanned")) { - $h_class = $event->display_user->class->parent->name; - } - else { - $h_class = $event->display_user->class->name; - } + $event->add_stats("Joined: $h_join_date", 10); + $event->add_stats("Class: $h_class", 90); - $event->add_stats("Joined: $h_join_date", 10); - $event->add_stats("Class: $h_class", 90); + $av = $event->display_user->get_avatar_html(); + if ($av) { + $event->add_stats($av, 0); + } elseif (( + $config->get_string("avatar_host") == "gravatar" + ) && + ($user->id == $event->display_user->id) + ) { + $event->add_stats( + "No avatar? This gallery uses Gravatar for avatar hosting, use the". + "
    same email address here and there to have your avatar synced
    ", + 0 + ); + } + } - $av = $event->display_user->get_avatar_html(); - if($av) { - $event->add_stats($av, 0); - } - else if(( - $config->get_string("avatar_host") == "gravatar") && - ($user->id == $event->display_user->id) - ) { - $event->add_stats( - "No avatar? This gallery uses Gravatar for avatar hosting, use the". - "
    same email address here and there to have your avatar synced
    ", - 0 - ); - } - } + private function display_stats(UserPageBuildingEvent $event) + { + global $user, $page, $config; - private function display_stats(UserPageBuildingEvent $event) { - global $user, $page, $config; + ksort($event->stats); + $this->theme->display_user_page($event->display_user, $event->stats); + if ($user->id == $event->display_user->id) { + $ubbe = new UserBlockBuildingEvent(); + send_event($ubbe); + ksort($ubbe->parts); + $this->theme->display_user_links($page, $user, $ubbe->parts); + } + if ( + ($user->can("view_ip") || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user + ($event->display_user->id != $config->get_int('anon_id')) # don't show anon's IP list, it is le huge + ) { + $this->theme->display_ip_list( + $page, + $this->count_upload_ips($event->display_user), + $this->count_comment_ips($event->display_user), + $this->count_log_ips($event->display_user) + ); + } + } - ksort($event->stats); - $this->theme->display_user_page($event->display_user, $event->stats); - if($user->id == $event->display_user->id) { - $ubbe = new UserBlockBuildingEvent(); - send_event($ubbe); - ksort($ubbe->parts); - $this->theme->display_user_links($page, $user, $ubbe->parts); - } - if( - ($user->can("view_ip") || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user - ($event->display_user->id != $config->get_int('anon_id')) # don't show anon's IP list, it is le huge - ) { - $this->theme->display_ip_list( - $page, - $this->count_upload_ips($event->display_user), - $this->count_comment_ips($event->display_user), - $this->count_log_ips($event->display_user) - ); - } - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + global $config; - public function onSetupBuilding(SetupBuildingEvent $event) { - global $config; + $hosts = [ + "None" => "none", + "Gravatar" => "gravatar" + ]; - $hosts = array( - "None" => "none", - "Gravatar" => "gravatar" - ); + $sb = new SetupBlock("User Options"); + $sb->add_bool_option("login_signup_enabled", "Allow new signups: "); + $sb->add_longtext_option("login_tac", "
    Terms & Conditions:
    "); + $sb->add_choice_option("avatar_host", $hosts, "
    Avatars: "); - $sb = new SetupBlock("User Options"); - $sb->add_bool_option("login_signup_enabled", "Allow new signups: "); - $sb->add_longtext_option("login_tac", "
    Terms & Conditions:
    "); - $sb->add_choice_option("avatar_host", $hosts, "
    Avatars: "); + if ($config->get_string("avatar_host") == "gravatar") { + $sb->add_label("
     
    Gravatar Options"); + $sb->add_choice_option( + "avatar_gravatar_type", + [ + 'Default'=>'default', + 'Wavatar'=>'wavatar', + 'Monster ID'=>'monsterid', + 'Identicon'=>'identicon' + ], + "
    Type: " + ); + $sb->add_choice_option( + "avatar_gravatar_rating", + ['G'=>'g', 'PG'=>'pg', 'R'=>'r', 'X'=>'x'], + "
    Rating: " + ); + } - if($config->get_string("avatar_host") == "gravatar") { - $sb->add_label("
     
    Gravatar Options"); - $sb->add_choice_option("avatar_gravatar_type", - array( - 'Default'=>'default', - 'Wavatar'=>'wavatar', - 'Monster ID'=>'monsterid', - 'Identicon'=>'identicon' - ), - "
    Type: "); - $sb->add_choice_option("avatar_gravatar_rating", - array('G'=>'g', 'PG'=>'pg', 'R'=>'r', 'X'=>'x'), - "
    Rating: "); - } + $sb->add_choice_option( + "user_loginshowprofile", + [ + "return to previous page" => 0, // 0 is default + "send to user profile" => 1], + "
    When user logs in/out" + ); + $event->panel->add_block($sb); + } - $sb->add_choice_option("user_loginshowprofile", array( - "return to previous page" => 0, // 0 is default - "send to user profile" => 1), - "
    When user logs in/out"); - $event->panel->add_block($sb); - } + public function onUserBlockBuilding(UserBlockBuildingEvent $event) + { + global $user; + $event->add_link("My Profile", make_link("user")); + if ($user->can("edit_user_class")) { + $event->add_link("User List", make_link("user_admin/list"), 98); + } + $event->add_link("Log Out", make_link("user_admin/logout"), 99); + } - public function onUserBlockBuilding(UserBlockBuildingEvent $event) { - global $user; - $event->add_link("My Profile", make_link("user")); - if($user->can("edit_user_class")) { - $event->add_link("User List", make_link("user_admin/list"), 98); - } - $event->add_link("Log Out", make_link("user_admin/logout"), 99); - } + public function onUserCreation(UserCreationEvent $event) + { + $this->check_user_creation($event); + $this->create_user($event); + } - public function onUserCreation(UserCreationEvent $event) { - $this->check_user_creation($event); - $this->create_user($event); - } + public function onSearchTermParse(SearchTermParseEvent $event) + { + global $user; - public function onSearchTermParse(SearchTermParseEvent $event) { - global $user; + $matches = []; + if (preg_match("/^(?:poster|user)[=|:](.*)$/i", $event->term, $matches)) { + $duser = User::by_name($matches[1]); + if (!is_null($duser)) { + $user_id = $duser->id; + } else { + $user_id = -1; + } + $event->add_querylet(new Querylet("images.owner_id = $user_id")); + } elseif (preg_match("/^(?:poster|user)_id[=|:]([0-9]+)$/i", $event->term, $matches)) { + $user_id = int_escape($matches[1]); + $event->add_querylet(new Querylet("images.owner_id = $user_id")); + } elseif ($user->can("view_ip") && preg_match("/^(?:poster|user)_ip[=|:]([0-9\.]+)$/i", $event->term, $matches)) { + $user_ip = $matches[1]; // FIXME: ip_escape? + $event->add_querylet(new Querylet("images.owner_ip = '$user_ip'")); + } + } - $matches = array(); - if(preg_match("/^(?:poster|user)[=|:](.*)$/i", $event->term, $matches)) { - $duser = User::by_name($matches[1]); - if(!is_null($duser)) { - $user_id = $duser->id; - } - else { - $user_id = -1; - } - $event->add_querylet(new Querylet("images.owner_id = $user_id")); - } - else if(preg_match("/^(?:poster|user)_id[=|:]([0-9]+)$/i", $event->term, $matches)) { - $user_id = int_escape($matches[1]); - $event->add_querylet(new Querylet("images.owner_id = $user_id")); - } - else if($user->can("view_ip") && preg_match("/^(?:poster|user)_ip[=|:]([0-9\.]+)$/i", $event->term, $matches)) { - $user_ip = $matches[1]; // FIXME: ip_escape? - $event->add_querylet(new Querylet("images.owner_ip = '$user_ip'")); - } - } - - private function show_user_info() { - global $user, $page; - // user info is shown on all pages - if ($user->is_anonymous()) { - $this->theme->display_login_block($page); - } else { - $ubbe = new UserBlockBuildingEvent(); - send_event($ubbe); - ksort($ubbe->parts); - $this->theme->display_user_block($page, $user, $ubbe->parts); - } - } -// }}} -// Things done *with* the user {{{ - private function page_login($name, $pass) { - global $config, $user, $page; + private function show_user_info() + { + global $user, $page; + // user info is shown on all pages + if ($user->is_anonymous()) { + $this->theme->display_login_block($page); + } else { + $ubbe = new UserBlockBuildingEvent(); + send_event($ubbe); + ksort($ubbe->parts); + $this->theme->display_user_block($page, $user, $ubbe->parts); + } + } + // }}} + // Things done *with* the user {{{ + private function page_login($name, $pass) + { + global $config, $user, $page; - if(empty($name) || empty($pass)) { - $this->theme->display_error(400, "Error", "Username or password left blank"); - return; - } + if (empty($name) || empty($pass)) { + $this->theme->display_error(400, "Error", "Username or password left blank"); + return; + } - $duser = User::by_name_and_pass($name, $pass); - if(!is_null($duser)) { - $user = $duser; - $this->set_login_cookie($duser->name, $pass); - $page->set_mode("redirect"); + $duser = User::by_name_and_pass($name, $pass); + if (!is_null($duser)) { + $user = $duser; + $this->set_login_cookie($duser->name, $pass); + $page->set_mode("redirect"); - // Try returning to previous page - if ($config->get_int("user_loginshowprofile",0) == 0 && - isset($_SERVER['HTTP_REFERER']) && - strstr($_SERVER['HTTP_REFERER'], "post/")) - { - $page->set_redirect($_SERVER['HTTP_REFERER']); - } else { - $page->set_redirect(make_link("user")); - } - } - else { - $this->theme->display_error(401, "Error", "No user with those details was found"); - } - } + // Try returning to previous page + if ($config->get_int("user_loginshowprofile", 0) == 0 && + isset($_SERVER['HTTP_REFERER']) && + strstr($_SERVER['HTTP_REFERER'], "post/")) { + $page->set_redirect($_SERVER['HTTP_REFERER']); + } else { + $page->set_redirect(make_link("user")); + } + } else { + $this->theme->display_error(401, "Error", "No user with those details was found"); + } + } - private function page_logout() { - global $page, $config; - $page->add_cookie("session", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); - if (CACHE_HTTP || SPEED_HAX) { - # to keep as few versions of content as possible, - # make cookies all-or-nothing - $page->add_cookie("user", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); - } - log_info("user", "Logged out"); - $page->set_mode("redirect"); + private function page_logout() + { + global $page, $config; + $page->add_cookie("session", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); + if (CACHE_HTTP || SPEED_HAX) { + # to keep as few versions of content as possible, + # make cookies all-or-nothing + $page->add_cookie("user", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); + } + log_info("user", "Logged out"); + $page->set_mode("redirect"); - // Try forwarding to same page on logout unless user comes from registration page - if ($config->get_int("user_loginshowprofile", 0) == 0 && - isset($_SERVER['HTTP_REFERER']) && - strstr($_SERVER['HTTP_REFERER'], "post/") - ) { - $page->set_redirect($_SERVER['HTTP_REFERER']); - } else { - $page->set_redirect(make_link()); - } - } + // Try forwarding to same page on logout unless user comes from registration page + if ($config->get_int("user_loginshowprofile", 0) == 0 && + isset($_SERVER['HTTP_REFERER']) && + strstr($_SERVER['HTTP_REFERER'], "post/") + ) { + $page->set_redirect($_SERVER['HTTP_REFERER']); + } else { + $page->set_redirect(make_link()); + } + } - private function page_recover(string $username) { - $user = User::by_name($username); - if (is_null($user)) { - $this->theme->display_error(404, "Error", "There's no user with that name"); - } else if (is_null($user->email)) { - $this->theme->display_error(400, "Error", "That user has no registered email address"); - } else { - // send email - } - } + private function page_recover(string $username) + { + $user = User::by_name($username); + if (is_null($user)) { + $this->theme->display_error(404, "Error", "There's no user with that name"); + } elseif (is_null($user->email)) { + $this->theme->display_error(400, "Error", "That user has no registered email address"); + } else { + // send email + } + } - private function page_create() { - global $config, $page; - if (!$config->get_bool("login_signup_enabled")) { - $this->theme->display_signups_disabled($page); - } else if (!isset($_POST['name'])) { - $this->theme->display_signup_page($page); - } else if ($_POST['pass1'] != $_POST['pass2']) { - $this->theme->display_error(400, "Password Mismatch", "Passwords don't match"); - } else { - try { - if (!captcha_check()) { - throw new UserCreationException("Error in captcha"); - } + private function page_create() + { + global $config, $page; + if (!$config->get_bool("login_signup_enabled")) { + $this->theme->display_signups_disabled($page); + } elseif (!isset($_POST['name'])) { + $this->theme->display_signup_page($page); + } elseif ($_POST['pass1'] != $_POST['pass2']) { + $this->theme->display_error(400, "Password Mismatch", "Passwords don't match"); + } else { + try { + if (!captcha_check()) { + throw new UserCreationException("Error in captcha"); + } - $uce = new UserCreationEvent($_POST['name'], $_POST['pass1'], $_POST['email']); - send_event($uce); - $this->set_login_cookie($uce->username, $uce->password); - $page->set_mode("redirect"); - $page->set_redirect(make_link("user")); - } catch (UserCreationException $ex) { - $this->theme->display_error(400, "User Creation Error", $ex->getMessage()); - } - } - } + $uce = new UserCreationEvent($_POST['name'], $_POST['pass1'], $_POST['email']); + send_event($uce); + $this->set_login_cookie($uce->username, $uce->password); + $page->set_mode("redirect"); + $page->set_redirect(make_link("user")); + } catch (UserCreationException $ex) { + $this->theme->display_error(400, "User Creation Error", $ex->getMessage()); + } + } + } - private function check_user_creation(UserCreationEvent $event) { - $name = $event->username; - //$pass = $event->password; - //$email = $event->email; + private function check_user_creation(UserCreationEvent $event) + { + $name = $event->username; + //$pass = $event->password; + //$email = $event->email; - if(strlen($name) < 1) { - throw new UserCreationException("Username must be at least 1 character"); - } - else if(!preg_match('/^[a-zA-Z0-9-_]+$/', $name)) { - throw new UserCreationException( - "Username contains invalid characters. Allowed characters are ". - "letters, numbers, dash, and underscore"); - } - else if(User::by_name($name)) { - throw new UserCreationException("That username is already taken"); - } - } + if (strlen($name) < 1) { + throw new UserCreationException("Username must be at least 1 character"); + } elseif (!preg_match('/^[a-zA-Z0-9-_]+$/', $name)) { + throw new UserCreationException( + "Username contains invalid characters. Allowed characters are ". + "letters, numbers, dash, and underscore" + ); + } elseif (User::by_name($name)) { + throw new UserCreationException("That username is already taken"); + } + } - private function create_user(UserCreationEvent $event) { - global $database, $user; + private function create_user(UserCreationEvent $event) + { + global $database, $user; - $email = (!empty($event->email)) ? $event->email : null; + $email = (!empty($event->email)) ? $event->email : null; - // if there are currently no admins, the new user should be one - $need_admin = ($database->get_one("SELECT COUNT(*) FROM users WHERE class='admin'") == 0); - $class = $need_admin ? 'admin' : 'user'; + // if there are currently no admins, the new user should be one + $need_admin = ($database->get_one("SELECT COUNT(*) FROM users WHERE class='admin'") == 0); + $class = $need_admin ? 'admin' : 'user'; - $database->Execute( - "INSERT INTO users (name, pass, joindate, email, class) VALUES (:username, :hash, now(), :email, :class)", - array("username"=>$event->username, "hash"=>'', "email"=>$email, "class"=>$class)); - $uid = $database->get_last_insert_id('users_id_seq'); - $user = User::by_name($event->username); - $user->set_password($event->password); - log_info("user", "Created User #$uid ({$event->username})"); - } + $database->Execute( + "INSERT INTO users (name, pass, joindate, email, class) VALUES (:username, :hash, now(), :email, :class)", + ["username"=>$event->username, "hash"=>'', "email"=>$email, "class"=>$class] + ); + $uid = $database->get_last_insert_id('users_id_seq'); + $user = User::by_name($event->username); + $user->set_password($event->password); + log_info("user", "Created User #$uid ({$event->username})"); + } - private function set_login_cookie(string $name, string $pass) { - global $config, $page; + private function set_login_cookie(string $name, string $pass) + { + global $config, $page; - $addr = get_session_ip($config); - $hash = User::by_name($name)->passhash; + $addr = get_session_ip($config); + $hash = User::by_name($name)->passhash; - $page->add_cookie("user", $name, - time()+60*60*24*365, '/'); - $page->add_cookie("session", md5($hash.$addr), - time()+60*60*24*$config->get_int('login_memory'), '/'); - } -//}}} -// Things done *to* the user {{{ - private function user_can_edit_user(User $a, User $b): bool { - if($a->is_anonymous()) { - $this->theme->display_error(401, "Error", "You aren't logged in"); - return false; - } + $page->add_cookie( + "user", + $name, + time()+60*60*24*365, + '/' + ); + $page->add_cookie( + "session", + md5($hash.$addr), + time()+60*60*24*$config->get_int('login_memory'), + '/' + ); + } + //}}} + // Things done *to* the user {{{ + private function user_can_edit_user(User $a, User $b): bool + { + if ($a->is_anonymous()) { + $this->theme->display_error(401, "Error", "You aren't logged in"); + return false; + } - if( - ($a->name == $b->name) || - ($b->can("protected") && $a->class->name == "admin") || - (!$b->can("protected") && $a->can("edit_user_info")) - ) { - return true; - } - else { - $this->theme->display_error(401, "Error", "You need to be an admin to change other people's details"); - return false; - } - } + if ( + ($a->name == $b->name) || + ($b->can("protected") && $a->class->name == "admin") || + (!$b->can("protected") && $a->can("edit_user_info")) + ) { + return true; + } else { + $this->theme->display_error(401, "Error", "You need to be an admin to change other people's details"); + return false; + } + } - private function redirect_to_user(User $duser) { - global $page, $user; + private function redirect_to_user(User $duser) + { + global $page, $user; - if($user->id == $duser->id) { - $page->set_mode("redirect"); - $page->set_redirect(make_link("user")); - } - else { - $page->set_mode("redirect"); - $page->set_redirect(make_link("user/{$duser->name}")); - } - } + if ($user->id == $duser->id) { + $page->set_mode("redirect"); + $page->set_redirect(make_link("user")); + } else { + $page->set_mode("redirect"); + $page->set_redirect(make_link("user/{$duser->name}")); + } + } - private function change_name_wrapper(User $duser, $name) { - global $user; + private function change_name_wrapper(User $duser, $name) + { + global $user; - if($user->can('edit_user_name') && $this->user_can_edit_user($user, $duser)) { - $duser->set_name($name); - flash_message("Username changed"); - // TODO: set login cookie if user changed themselves - $this->redirect_to_user($duser); - } - else { - $this->theme->display_error(400, "Error", "Permission denied"); - } - } + if ($user->can('edit_user_name') && $this->user_can_edit_user($user, $duser)) { + $duser->set_name($name); + flash_message("Username changed"); + // TODO: set login cookie if user changed themselves + $this->redirect_to_user($duser); + } else { + $this->theme->display_error(400, "Error", "Permission denied"); + } + } - private function change_password_wrapper(User $duser, string $pass1, string $pass2) { - global $user; + private function change_password_wrapper(User $duser, string $pass1, string $pass2) + { + global $user; - if($this->user_can_edit_user($user, $duser)) { - if($pass1 != $pass2) { - $this->theme->display_error(400, "Error", "Passwords don't match"); - } - else { - // FIXME: send_event() - $duser->set_password($pass1); + if ($this->user_can_edit_user($user, $duser)) { + if ($pass1 != $pass2) { + $this->theme->display_error(400, "Error", "Passwords don't match"); + } else { + // FIXME: send_event() + $duser->set_password($pass1); - if($duser->id == $user->id) { - $this->set_login_cookie($duser->name, $pass1); - } + if ($duser->id == $user->id) { + $this->set_login_cookie($duser->name, $pass1); + } - flash_message("Password changed"); - $this->redirect_to_user($duser); - } - } - } + flash_message("Password changed"); + $this->redirect_to_user($duser); + } + } + } - private function change_email_wrapper(User $duser, string $address) { - global $user; + private function change_email_wrapper(User $duser, string $address) + { + global $user; - if($this->user_can_edit_user($user, $duser)) { - $duser->set_email($address); + if ($this->user_can_edit_user($user, $duser)) { + $duser->set_email($address); - flash_message("Email changed"); - $this->redirect_to_user($duser); - } - } + flash_message("Email changed"); + $this->redirect_to_user($duser); + } + } - private function change_class_wrapper(User $duser, string $class) { - global $user; + private function change_class_wrapper(User $duser, string $class) + { + global $user; - if($user->class->name == "admin") { - $duser->set_class($class); - flash_message("Class changed"); - $this->redirect_to_user($duser); - } - } -// }}} -// ips {{{ - private function count_upload_ips(User $duser): array { - global $database; - $rows = $database->get_pairs(" + if ($user->class->name == "admin") { + $duser->set_class($class); + flash_message("Class changed"); + $this->redirect_to_user($duser); + } + } + // }}} + // ips {{{ + private function count_upload_ips(User $duser): array + { + global $database; + $rows = $database->get_pairs(" SELECT owner_ip, COUNT(images.id) AS count, @@ -569,13 +610,14 @@ class UserPage extends Extension { FROM images WHERE owner_id=:id GROUP BY owner_ip - ORDER BY most_recent DESC", array("id"=>$duser->id)); - return $rows; - } + ORDER BY most_recent DESC", ["id"=>$duser->id]); + return $rows; + } - private function count_comment_ips(User $duser): array { - global $database; - $rows = $database->get_pairs(" + private function count_comment_ips(User $duser): array + { + global $database; + $rows = $database->get_pairs(" SELECT owner_ip, COUNT(comments.id) AS count, @@ -583,14 +625,17 @@ class UserPage extends Extension { FROM comments WHERE owner_id=:id GROUP BY owner_ip - ORDER BY most_recent DESC", array("id"=>$duser->id)); - return $rows; - } + ORDER BY most_recent DESC", ["id"=>$duser->id]); + return $rows; + } - private function count_log_ips(User $duser): array { - if(!class_exists('LogDatabase')) return array(); - global $database; - $rows = $database->get_pairs(" + private function count_log_ips(User $duser): array + { + if (!class_exists('LogDatabase')) { + return []; + } + global $database; + $rows = $database->get_pairs(" SELECT address, COUNT(id) AS count, @@ -598,66 +643,64 @@ class UserPage extends Extension { FROM score_log WHERE username=:username GROUP BY address - ORDER BY most_recent DESC", array("username"=>$duser->name)); - return $rows; - } + ORDER BY most_recent DESC", ["username"=>$duser->name]); + return $rows; + } - private function delete_user(Page $page, bool $with_images=false, bool $with_comments=false) { - global $user, $config, $database; - - $page->set_title("Error"); - $page->set_heading("Error"); - $page->add_block(new NavBlock()); - - if (!$user->can("delete_user")) { - $page->add_block(new Block("Not Admin", "Only admins can delete accounts")); - } - else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) { - $page->add_block(new Block("No ID Specified", - "You need to specify the account number to edit")); - } - else { - log_warning("user", "Deleting user #{$_POST['id']}"); + private function delete_user(Page $page, bool $with_images=false, bool $with_comments=false) + { + global $user, $config, $database; + + $page->set_title("Error"); + $page->set_heading("Error"); + $page->add_block(new NavBlock()); + + if (!$user->can("delete_user")) { + $page->add_block(new Block("Not Admin", "Only admins can delete accounts")); + } elseif (!isset($_POST['id']) || !is_numeric($_POST['id'])) { + $page->add_block(new Block( + "No ID Specified", + "You need to specify the account number to edit" + )); + } else { + log_warning("user", "Deleting user #{$_POST['id']}"); - if($with_images) { - log_warning("user", "Deleting user #{$_POST['id']}'s uploads"); - $rows = $database->get_all("SELECT * FROM images WHERE owner_id = :owner_id", array("owner_id" => $_POST['id'])); - foreach ($rows as $key => $value) { - $image = Image::by_id($value['id']); - if($image) { - send_event(new ImageDeletionEvent($image)); - } - } - } - else { - $database->Execute( - "UPDATE images SET owner_id = :new_owner_id WHERE owner_id = :old_owner_id", - array("new_owner_id" => $config->get_int('anon_id'), "old_owner_id" => $_POST['id']) - ); - } + if ($with_images) { + log_warning("user", "Deleting user #{$_POST['id']}'s uploads"); + $rows = $database->get_all("SELECT * FROM images WHERE owner_id = :owner_id", ["owner_id" => $_POST['id']]); + foreach ($rows as $key => $value) { + $image = Image::by_id($value['id']); + if ($image) { + send_event(new ImageDeletionEvent($image)); + } + } + } else { + $database->Execute( + "UPDATE images SET owner_id = :new_owner_id WHERE owner_id = :old_owner_id", + ["new_owner_id" => $config->get_int('anon_id'), "old_owner_id" => $_POST['id']] + ); + } - if($with_comments) { - log_warning("user", "Deleting user #{$_POST['id']}'s comments"); - $database->execute("DELETE FROM comments WHERE owner_id = :owner_id", array("owner_id" => $_POST['id'])); - } - else { - $database->Execute( - "UPDATE comments SET owner_id = :new_owner_id WHERE owner_id = :old_owner_id", - array("new_owner_id" => $config->get_int('anon_id'), "old_owner_id" => $_POST['id']) - ); - } + if ($with_comments) { + log_warning("user", "Deleting user #{$_POST['id']}'s comments"); + $database->execute("DELETE FROM comments WHERE owner_id = :owner_id", ["owner_id" => $_POST['id']]); + } else { + $database->Execute( + "UPDATE comments SET owner_id = :new_owner_id WHERE owner_id = :old_owner_id", + ["new_owner_id" => $config->get_int('anon_id'), "old_owner_id" => $_POST['id']] + ); + } - send_event(new UserDeletionEvent($_POST['id'])); + send_event(new UserDeletionEvent($_POST['id'])); - $database->execute( - "DELETE FROM users WHERE id = :id", - array("id" => $_POST['id']) - ); - - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/list")); - } - } -// }}} + $database->execute( + "DELETE FROM users WHERE id = :id", + ["id" => $_POST['id']] + ); + + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/list")); + } + } + // }}} } - diff --git a/ext/user/test.php b/ext/user/test.php index 6e72ebc3..9b3d00af 100644 --- a/ext/user/test.php +++ b/ext/user/test.php @@ -1,41 +1,43 @@ get_page('user'); - $this->assert_title("Not Logged In"); - $this->assert_no_text("Options"); - $this->assert_no_text("More Options"); +class UserPageTest extends ShimmiePHPUnitTestCase +{ + public function testUserPage() + { + $this->get_page('user'); + $this->assert_title("Not Logged In"); + $this->assert_no_text("Options"); + $this->assert_no_text("More Options"); - $this->get_page('user/demo'); - $this->assert_title("demo's Page"); - $this->assert_text("Joined:"); + $this->get_page('user/demo'); + $this->assert_title("demo's Page"); + $this->assert_text("Joined:"); - $this->get_page('user/MauMau'); - $this->assert_title("No Such User"); + $this->get_page('user/MauMau'); + $this->assert_title("No Such User"); - $this->log_in_as_user(); - // should be on the user page - $this->get_page('user/test'); - $this->assert_title("test's Page"); - $this->assert_text("Options"); - // FIXME: check class - //$this->assert_no_text("Admin:"); - $this->log_out(); + $this->log_in_as_user(); + // should be on the user page + $this->get_page('user/test'); + $this->assert_title("test's Page"); + $this->assert_text("Options"); + // FIXME: check class + //$this->assert_no_text("Admin:"); + $this->log_out(); - $this->log_in_as_admin(); - // should be on the user page - $this->get_page('user/demo'); - $this->assert_title("demo's Page"); - $this->assert_text("Options"); - // FIXME: check class - //$this->assert_text("Admin:"); - $this->log_out(); + $this->log_in_as_admin(); + // should be on the user page + $this->get_page('user/demo'); + $this->assert_title("demo's Page"); + $this->assert_text("Options"); + // FIXME: check class + //$this->assert_text("Admin:"); + $this->log_out(); - # FIXME: test user creation - # FIXME: test adminifying - # FIXME: test password reset + # FIXME: test user creation + # FIXME: test adminifying + # FIXME: test password reset - $this->get_page('user_admin/list'); - $this->assert_text("demo"); - } + $this->get_page('user_admin/list'); + $this->assert_text("demo"); + } } diff --git a/ext/user/theme.php b/ext/user/theme.php index b53ac92d..45f6f08f 100644 --- a/ext/user/theme.php +++ b/ext/user/theme.php @@ -1,114 +1,137 @@ set_title("Login"); - $page->set_heading("Login"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Login There", - "There should be a login box to the left")); - } +class UserPageTheme extends Themelet +{ + public function display_login_page(Page $page) + { + $page->set_title("Login"); + $page->set_heading("Login"); + $page->add_block(new NavBlock()); + $page->add_block(new Block( + "Login There", + "There should be a login box to the left" + )); + } - /** - * #param User[] $users - */ - public function display_user_list(Page $page, array $users, User $user, int $page_num, int $page_total) { - $page->set_title("User List"); - $page->set_heading("User List"); - $page->add_block(new NavBlock()); + /** + * #param User[] $users + */ + public function display_user_list(Page $page, array $users, User $user, int $page_num, int $page_total) + { + $page->set_title("User List"); + $page->set_heading("User List"); + $page->add_block(new NavBlock()); - $html = "
    "; + $html = "
    "; - $html .= ""; - $html .= ""; - if($user->can('delete_user')) - $html .= ""; - $html .= ""; - $html .= ""; - $html .= ""; + $html .= ""; + $html .= ""; + if ($user->can('delete_user')) { + $html .= ""; + } + $html .= ""; + $html .= ""; + $html .= ""; - $h_username = html_escape(@$_GET['username']); - $h_email = html_escape(@$_GET['email']); - $h_class = html_escape(@$_GET['class']); + $h_username = html_escape(@$_GET['username']); + $h_email = html_escape(@$_GET['email']); + $h_class = html_escape(@$_GET['class']); - $html .= "" . make_form("user_admin/list", "GET"); - $html .= ""; - if($user->can('delete_user')) - $html .= ""; - $html .= ""; - $html .= ""; - $html .= ""; + $html .= "" . make_form("user_admin/list", "GET"); + $html .= ""; + if ($user->can('delete_user')) { + $html .= ""; + } + $html .= ""; + $html .= ""; + $html .= ""; - foreach($users as $duser) { - $h_name = html_escape($duser->name); - $h_email = html_escape($duser->email); - $h_class = html_escape($duser->class->name); - $u_link = make_link("user/" . url_escape($duser->name)); - $u_posts = make_link("post/list/user_id=" . url_escape($duser->id) . "/1"); + foreach ($users as $duser) { + $h_name = html_escape($duser->name); + $h_email = html_escape($duser->email); + $h_class = html_escape($duser->class->name); + $u_link = make_link("user/" . url_escape($duser->name)); + $u_posts = make_link("post/list/user_id=" . url_escape($duser->id) . "/1"); - $html .= ""; - $html .= ""; - if($user->can('delete_user')) - $html .= ""; - $html .= ""; - $html .= ""; - $html .= ""; - } + $html .= ""; + $html .= ""; + if ($user->can('delete_user')) { + $html .= ""; + } + $html .= ""; + $html .= ""; + $html .= ""; + } - $html .= "
    NameEmailClassAction
    NameEmailClassAction
    $h_name$h_email$h_classShow Posts
    $h_name$h_email$h_classShow Posts
    "; + $html .= ""; - $page->add_block(new Block("Users", $html)); - $this->display_paginator($page, "user_admin/list", $this->get_args(), $page_num, $page_total); - } + $page->add_block(new Block("Users", $html)); + $this->display_paginator($page, "user_admin/list", $this->get_args(), $page_num, $page_total); + } - protected function ueie($var) { - if(isset($_GET[$var])) return $var."=".url_escape($_GET[$var]); - else return ""; - } - protected function get_args() { - $args = ""; - // Check if each arg is actually empty and skip it if so - if(strlen($this->ueie("username"))) - $args .= $this->ueie("username")."&"; - if(strlen($this->ueie("email"))) - $args .= $this->ueie("email")."&"; - if(strlen($this->ueie("class"))) - $args .= $this->ueie("class")."&"; - // If there are no args at all, set $args to null to prevent an unnecessary ? at the end of the paginator url - if(strlen($args) == 0) - $args = null; - return $args; - } + protected function ueie($var) + { + if (isset($_GET[$var])) { + return $var."=".url_escape($_GET[$var]); + } else { + return ""; + } + } + protected function get_args() + { + $args = ""; + // Check if each arg is actually empty and skip it if so + if (strlen($this->ueie("username"))) { + $args .= $this->ueie("username")."&"; + } + if (strlen($this->ueie("email"))) { + $args .= $this->ueie("email")."&"; + } + if (strlen($this->ueie("class"))) { + $args .= $this->ueie("class")."&"; + } + // If there are no args at all, set $args to null to prevent an unnecessary ? at the end of the paginator url + if (strlen($args) == 0) { + $args = null; + } + return $args; + } - public function display_user_links(Page $page, User $user, $parts) { - # $page->add_block(new Block("User Links", join(", ", $parts), "main", 10)); - } + public function display_user_links(Page $page, User $user, $parts) + { + # $page->add_block(new Block("User Links", join(", ", $parts), "main", 10)); + } - public function display_user_block(Page $page, User $user, $parts) { - $h_name = html_escape($user->name); - $html = 'Logged in as '.$h_name; - foreach($parts as $part) { - $html .= '
    '.$part["name"].''; - } - $page->add_block(new Block("User Links", $html, "left", 90)); - } + public function display_user_block(Page $page, User $user, $parts) + { + $h_name = html_escape($user->name); + $html = 'Logged in as '.$h_name; + foreach ($parts as $part) { + $html .= '
    '.$part["name"].''; + } + $page->add_block(new Block("User Links", $html, "left", 90)); + } - public function display_signup_page(Page $page) { - global $config; - $tac = $config->get_string("login_tac", ""); + public function display_signup_page(Page $page) + { + global $config; + $tac = $config->get_string("login_tac", ""); - if($config->get_bool("login_tac_bbcode")) { - $tfe = new TextFormattingEvent($tac); - send_event($tfe); - $tac = $tfe->formatted; - } + if ($config->get_bool("login_tac_bbcode")) { + $tfe = new TextFormattingEvent($tac); + send_event($tfe); + $tac = $tfe->formatted; + } - if(empty($tac)) {$html = "";} - else {$html = '

    '.$tac.'

    ';} + if (empty($tac)) { + $html = ""; + } else { + $html = '

    '.$tac.'

    '; + } - $h_reca = "".captcha_get_html().""; + $h_reca = "".captcha_get_html().""; - $html .= ' + $html .= ' '.make_form(make_link("user_admin/create"))." @@ -125,23 +148,27 @@ class UserPageTheme extends Themelet { "; - $page->set_title("Create Account"); - $page->set_heading("Create Account"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Signup", $html)); - } + $page->set_title("Create Account"); + $page->set_heading("Create Account"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Signup", $html)); + } - public function display_signups_disabled(Page $page) { - $page->set_title("Signups Disabled"); - $page->set_heading("Signups Disabled"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Signups Disabled", - "The board admin has disabled the ability to create new accounts~")); - } + public function display_signups_disabled(Page $page) + { + $page->set_title("Signups Disabled"); + $page->set_heading("Signups Disabled"); + $page->add_block(new NavBlock()); + $page->add_block(new Block( + "Signups Disabled", + "The board admin has disabled the ability to create new accounts~" + )); + } - public function display_login_block(Page $page) { - global $config; - $html = ' + public function display_login_block(Page $page) + { + global $config; + $html = ' '.make_form(make_link("user_admin/login"))."
    @@ -160,74 +187,77 @@ class UserPageTheme extends Themelet {
    "; - if($config->get_bool("login_signup_enabled")) { - $html .= "Create Account"; - } - $page->add_block(new Block("Login", $html, "left", 90)); - } + if ($config->get_bool("login_signup_enabled")) { + $html .= "Create Account"; + } + $page->add_block(new Block("Login", $html, "left", 90)); + } - public function display_ip_list(Page $page, array $uploads, array $comments, array $events) { - $html = ""; - $html .= ""; + $html .= "
    Uploaded from: "; - $n = 0; - foreach($uploads as $ip => $count) { - $html .= '
    '.$ip.' ('.$count.')'; - if(++$n >= 20) { - $html .= "
    ..."; - break; - } - } + public function display_ip_list(Page $page, array $uploads, array $comments, array $events) + { + $html = ""; + $html .= ""; - $html .= "
    Uploaded from: "; + $n = 0; + foreach ($uploads as $ip => $count) { + $html .= '
    '.$ip.' ('.$count.')'; + if (++$n >= 20) { + $html .= "
    ..."; + break; + } + } - $html .= "
    Commented from:"; - $n = 0; - foreach($comments as $ip => $count) { - $html .= '
    '.$ip.' ('.$count.')'; - if(++$n >= 20) { - $html .= "
    ..."; - break; - } - } + $html .= "
    Commented from:"; + $n = 0; + foreach ($comments as $ip => $count) { + $html .= '
    '.$ip.' ('.$count.')'; + if (++$n >= 20) { + $html .= "
    ..."; + break; + } + } - $html .= "
    Logged Events:"; - $n = 0; - foreach($events as $ip => $count) { - $html .= '
    '.$ip.' ('.$count.')'; - if(++$n >= 20) { - $html .= "
    ..."; - break; - } - } + $html .= "
    Logged Events:"; + $n = 0; + foreach ($events as $ip => $count) { + $html .= '
    '.$ip.' ('.$count.')'; + if (++$n >= 20) { + $html .= "
    ..."; + break; + } + } - $html .= "
    (Most recent at top)
    "; + $html .= "
    (Most recent at top)
    "; - $page->add_block(new Block("IPs", $html, "main", 70)); - } + $page->add_block(new Block("IPs", $html, "main", 70)); + } - public function display_user_page(User $duser, $stats) { - global $page, $user; - assert(is_array($stats)); - $stats[] = 'User ID: '.$duser->id; + public function display_user_page(User $duser, $stats) + { + global $page, $user; + assert(is_array($stats)); + $stats[] = 'User ID: '.$duser->id; - $page->set_title(html_escape($duser->name)."'s Page"); - $page->set_heading(html_escape($duser->name)."'s Page"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Stats", join("
    ", $stats), "main", 10)); + $page->set_title(html_escape($duser->name)."'s Page"); + $page->set_heading(html_escape($duser->name)."'s Page"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Stats", join("
    ", $stats), "main", 10)); - if(!$user->is_anonymous()) { - if($user->id == $duser->id || $user->can("edit_user_info")) { - $page->add_block(new Block("Options", $this->build_options($duser), "main", 60)); - } - } - } + if (!$user->is_anonymous()) { + if ($user->id == $duser->id || $user->can("edit_user_info")) { + $page->add_block(new Block("Options", $this->build_options($duser), "main", 60)); + } + } + } - protected function build_options(User $duser) { - global $config, $user; - $html = ""; - if($duser->id != $config->get_int('anon_id')){ //justa fool-admin protection so they dont mess around with anon users. - - if($user->can('edit_user_name')) { - $html .= " + protected function build_options(User $duser) + { + global $config, $user; + $html = ""; + if ($duser->id != $config->get_int('anon_id')) { //justa fool-admin protection so they dont mess around with anon users. + + if ($user->can('edit_user_name')) { + $html .= "

    ".make_form(make_link("user_admin/change_name"))." @@ -237,9 +267,9 @@ class UserPageTheme extends Themelet {
    "; - } + } - $html .= " + $html .= "

    ".make_form(make_link("user_admin/change_pass"))." @@ -266,18 +296,18 @@ class UserPageTheme extends Themelet { "; - $i_user_id = int_escape($duser->id); + $i_user_id = int_escape($duser->id); - if($user->can("edit_user_class")) { - global $_shm_user_classes; - $class_html = ""; - foreach($_shm_user_classes as $name => $values) { - $h_name = html_escape($name); - $h_title = html_escape(ucwords($name)); - $h_selected = ($name == $duser->class->name ? " selected" : ""); - $class_html .= "\n"; - } - $html .= " + if ($user->can("edit_user_class")) { + global $_shm_user_classes; + $class_html = ""; + foreach ($_shm_user_classes as $name => $values) { + $h_name = html_escape($name); + $h_title = html_escape(ucwords($name)); + $h_selected = ($name == $duser->class->name ? " selected" : ""); + $class_html .= "\n"; + } + $html .= "

    ".make_form(make_link("user_admin/change_class"))."

    @@ -287,10 +317,10 @@ class UserPageTheme extends Themelet {
    "; - } + } - if($user->can("delete_user")) { - $html .= " + if ($user->can("delete_user")) { + $html .= "

    ".make_form(make_link("user_admin/delete_user"))." @@ -308,10 +338,9 @@ class UserPageTheme extends Themelet {
    "; - } - } - return $html; - } -// }}} + } + } + return $html; + } + // }}} } - diff --git a/ext/varnish/main.php b/ext/varnish/main.php index 6ac7831a..a90c4e13 100644 --- a/ext/varnish/main.php +++ b/ext/varnish/main.php @@ -7,33 +7,43 @@ * Description: Sends PURGE requests when a /post/view is updated */ -class VarnishPurger extends Extension { - private function curl_purge($path) { - // waiting for curl timeout adds ~5 minutes to unit tests - if(defined("UNITTEST")) return; +class VarnishPurger extends Extension +{ + private function curl_purge($path) + { + // waiting for curl timeout adds ~5 minutes to unit tests + if (defined("UNITTEST")) { + return; + } - $url = make_http(make_link($path)); - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PURGE"); - curl_setopt($ch, CURLOPT_TIMEOUT, 5); - $result = curl_exec($ch); - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - //return $result; - } + $url = make_http(make_link($path)); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PURGE"); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + $result = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + //return $result; + } - public function onCommentPosting(CommentPostingEvent $event) { - $this->curl_purge("post/view/{$event->image_id}"); - } + public function onCommentPosting(CommentPostingEvent $event) + { + $this->curl_purge("post/view/{$event->image_id}"); + } - public function onImageInfoSet(ImageInfoSetEvent $event) { - $this->curl_purge("post/view/{$event->image->id}"); - } + public function onImageInfoSet(ImageInfoSetEvent $event) + { + $this->curl_purge("post/view/{$event->image->id}"); + } - public function onImageDeletion(ImageDeletionEvent $event) { - $this->curl_purge("post/view/{$event->image->id}"); - } + public function onImageDeletion(ImageDeletionEvent $event) + { + $this->curl_purge("post/view/{$event->image->id}"); + } - public function get_priority(): int {return 99;} + public function get_priority(): int + { + return 99; + } } diff --git a/ext/view/main.php b/ext/view/main.php index 7fe0c2a6..85415878 100644 --- a/ext/view/main.php +++ b/ext/view/main.php @@ -14,138 +14,152 @@ * wish to appear on the "view" page should listen for this, * which only appears when an image actually exists. */ -class DisplayingImageEvent extends Event { - /** @var \Image */ - public $image; +class DisplayingImageEvent extends Event +{ + /** @var \Image */ + public $image; - public function __construct(Image $image) { - $this->image = $image; - } + public function __construct(Image $image) + { + $this->image = $image; + } - public function get_image(): Image { - return $this->image; - } + public function get_image(): Image + { + return $this->image; + } } -class ImageInfoBoxBuildingEvent extends Event { - /** @var array */ - public $parts = array(); - /** @var \Image */ - public $image; - /** @var \User */ - public $user; +class ImageInfoBoxBuildingEvent extends Event +{ + /** @var array */ + public $parts = []; + /** @var \Image */ + public $image; + /** @var \User */ + public $user; - public function __construct(Image $image, User $user) { - $this->image = $image; - $this->user = $user; - } + public function __construct(Image $image, User $user) + { + $this->image = $image; + $this->user = $user; + } - public function add_part(string $html, int $position=50) { - while(isset($this->parts[$position])) $position++; - $this->parts[$position] = $html; - } + public function add_part(string $html, int $position=50) + { + while (isset($this->parts[$position])) { + $position++; + } + $this->parts[$position] = $html; + } } -class ImageInfoSetEvent extends Event { - /** @var \Image */ - public $image; +class ImageInfoSetEvent extends Event +{ + /** @var \Image */ + public $image; - public function __construct(Image $image) { - $this->image = $image; - } + public function __construct(Image $image) + { + $this->image = $image; + } } -class ImageAdminBlockBuildingEvent extends Event { - /** @var string[] */ - public $parts = array(); - /** @var \Image|null */ - public $image = null; - /** @var null|\User */ - public $user = null; +class ImageAdminBlockBuildingEvent extends Event +{ + /** @var string[] */ + public $parts = []; + /** @var \Image|null */ + public $image = null; + /** @var null|\User */ + public $user = null; - public function __construct(Image $image, User $user) { - $this->image = $image; - $this->user = $user; - } + public function __construct(Image $image, User $user) + { + $this->image = $image; + $this->user = $user; + } - public function add_part(string $html, int $position=50) { - while(isset($this->parts[$position])) $position++; - $this->parts[$position] = $html; - } + public function add_part(string $html, int $position=50) + { + while (isset($this->parts[$position])) { + $position++; + } + $this->parts[$position] = $html; + } } -class ViewImage extends Extension { - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; +class ViewImage extends Extension +{ + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; - if($event->page_matches("post/prev") || $event->page_matches("post/next")) { - $image_id = int_escape($event->get_arg(0)); + if ($event->page_matches("post/prev") || $event->page_matches("post/next")) { + $image_id = int_escape($event->get_arg(0)); - if(isset($_GET['search'])) { - $search_terms = explode(' ', $_GET['search']); - $query = "#search=".url_escape($_GET['search']); - } - else { - $search_terms = array(); - $query = null; - } + if (isset($_GET['search'])) { + $search_terms = explode(' ', $_GET['search']); + $query = "#search=".url_escape($_GET['search']); + } else { + $search_terms = []; + $query = null; + } - $image = Image::by_id($image_id); - if(is_null($image)) { - $this->theme->display_error(404, "Image not found", "Image $image_id could not be found"); - return; - } + $image = Image::by_id($image_id); + if (is_null($image)) { + $this->theme->display_error(404, "Image not found", "Image $image_id could not be found"); + return; + } - if($event->page_matches("post/next")) { - $image = $image->get_next($search_terms); - } - else { - $image = $image->get_prev($search_terms); - } + if ($event->page_matches("post/next")) { + $image = $image->get_next($search_terms); + } else { + $image = $image->get_prev($search_terms); + } - if(is_null($image)) { - $this->theme->display_error(404, "Image not found", "No more images"); - return; - } + if (is_null($image)) { + $this->theme->display_error(404, "Image not found", "No more images"); + return; + } - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/{$image->id}", $query)); - } - else if($event->page_matches("post/view")) { - $image_id = int_escape($event->get_arg(0)); + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/{$image->id}", $query)); + } elseif ($event->page_matches("post/view")) { + $image_id = int_escape($event->get_arg(0)); - $image = Image::by_id($image_id); + $image = Image::by_id($image_id); - if(!is_null($image)) { - send_event(new DisplayingImageEvent($image)); - $iabbe = new ImageAdminBlockBuildingEvent($image, $user); - send_event($iabbe); - ksort($iabbe->parts); - $this->theme->display_admin_block($page, $iabbe->parts); - } - else { - $this->theme->display_error(404, "Image not found", "No image in the database has the ID #$image_id"); - } - } - else if($event->page_matches("post/set")) { - if(!isset($_POST['image_id'])) return; + if (!is_null($image)) { + send_event(new DisplayingImageEvent($image)); + $iabbe = new ImageAdminBlockBuildingEvent($image, $user); + send_event($iabbe); + ksort($iabbe->parts); + $this->theme->display_admin_block($page, $iabbe->parts); + } else { + $this->theme->display_error(404, "Image not found", "No image in the database has the ID #$image_id"); + } + } elseif ($event->page_matches("post/set")) { + if (!isset($_POST['image_id'])) { + return; + } - $image_id = int_escape($_POST['image_id']); + $image_id = int_escape($_POST['image_id']); - send_event(new ImageInfoSetEvent(Image::by_id($image_id))); + send_event(new ImageInfoSetEvent(Image::by_id($image_id))); - $page->set_mode("redirect"); - $page->set_redirect(make_link("post/view/$image_id", url_escape(@$_POST['query']))); - } - } + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/$image_id", url_escape(@$_POST['query']))); + } + } - public function onDisplayingImage(DisplayingImageEvent $event) { - global $user; - $iibbe = new ImageInfoBoxBuildingEvent($event->get_image(), $user); - send_event($iibbe); - ksort($iibbe->parts); - $this->theme->display_meta_headers($event->get_image()); - $this->theme->display_page($event->get_image(), $iibbe->parts); - } + public function onDisplayingImage(DisplayingImageEvent $event) + { + global $user; + $iibbe = new ImageInfoBoxBuildingEvent($event->get_image(), $user); + send_event($iibbe); + ksort($iibbe->parts); + $this->theme->display_meta_headers($event->get_image()); + $this->theme->display_page($event->get_image(), $iibbe->parts); + } } - diff --git a/ext/view/test.php b/ext/view/test.php index d4ae305c..d3d118f0 100644 --- a/ext/view/test.php +++ b/ext/view/test.php @@ -1,66 +1,71 @@ log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); - $image_id_3 = $this->post_image("tests/favicon.png", "test"); - $idp1 = $image_id_3 + 1; + public function testViewPage() + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); + $image_id_3 = $this->post_image("tests/favicon.png", "test"); + $idp1 = $image_id_3 + 1; - $this->get_page("post/view/$image_id_1"); - $this->assert_title("Image $image_id_1: test"); - } + $this->get_page("post/view/$image_id_1"); + $this->assert_title("Image $image_id_1: test"); + } - public function testPrevNext() { - $this->markTestIncomplete(); + public function testPrevNext() + { + $this->markTestIncomplete(); - $this->log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); - $image_id_3 = $this->post_image("tests/favicon.png", "test"); + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); + $image_id_3 = $this->post_image("tests/favicon.png", "test"); - $this->click("Prev"); - $this->assert_title("Image $image_id_2: test2"); + $this->click("Prev"); + $this->assert_title("Image $image_id_2: test2"); - $this->click("Next"); - $this->assert_title("Image $image_id_1: test"); + $this->click("Next"); + $this->assert_title("Image $image_id_1: test"); - $this->click("Next"); - $this->assert_title("Image not found"); - } + $this->click("Next"); + $this->assert_title("Image not found"); + } - public function testView404() { - $this->log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); - $image_id_3 = $this->post_image("tests/favicon.png", "test"); - $idp1 = $image_id_3 + 1; + public function testView404() + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); + $image_id_3 = $this->post_image("tests/favicon.png", "test"); + $idp1 = $image_id_3 + 1; - $this->get_page("post/view/$idp1"); - $this->assert_title('Image not found'); + $this->get_page("post/view/$idp1"); + $this->assert_title('Image not found'); - $this->get_page('post/view/-1'); - $this->assert_title('Image not found'); - } + $this->get_page('post/view/-1'); + $this->assert_title('Image not found'); + } - public function testNextSearchResult() { - $this->markTestIncomplete(); + public function testNextSearchResult() + { + $this->markTestIncomplete(); - $this->log_in_as_user(); - $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); - $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); - $image_id_3 = $this->post_image("tests/favicon.png", "test"); + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "test"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "test2"); + $image_id_3 = $this->post_image("tests/favicon.png", "test"); - // FIXME: this assumes Nice URLs. - # note: skips image #2 - $this->get_page("post/view/$image_id_1?search=test"); // FIXME: assumes niceurls - $this->click("Prev"); - $this->assert_title("Image $image_id_3: test"); - } + // FIXME: this assumes Nice URLs. + # note: skips image #2 + $this->get_page("post/view/$image_id_1?search=test"); // FIXME: assumes niceurls + $this->click("Prev"); + $this->assert_title("Image $image_id_3: test"); + } } - diff --git a/ext/view/theme.php b/ext/view/theme.php index 8c16712c..82bd51f4 100644 --- a/ext/view/theme.php +++ b/ext/view/theme.php @@ -1,55 +1,60 @@ get_tag_list())); - $page->add_html_header(""); - $page->add_html_header(""); - $page->add_html_header(""); - $page->add_html_header("get_thumb_link())."\">"); - $page->add_html_header("id}"))."\">"); - } + $h_metatags = str_replace(" ", ", ", html_escape($image->get_tag_list())); + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header("get_thumb_link())."\">"); + $page->add_html_header("id}"))."\">"); + } - /* - * Build a page showing $image and some info about it - */ - public function display_page(Image $image, $editor_parts) { - global $page; + /* + * Build a page showing $image and some info about it + */ + public function display_page(Image $image, $editor_parts) + { + global $page; - $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); - $page->set_heading(html_escape($image->get_tag_list())); - $page->add_block(new Block("Navigation", $this->build_navigation($image), "left", 0)); - $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 20)); - //$page->add_block(new Block(null, $this->build_pin($image), "main", 11)); - } + $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); + $page->set_heading(html_escape($image->get_tag_list())); + $page->add_block(new Block("Navigation", $this->build_navigation($image), "left", 0)); + $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 20)); + //$page->add_block(new Block(null, $this->build_pin($image), "main", 11)); + } - public function display_admin_block(Page $page, $parts) { - if(count($parts) > 0) { - $page->add_block(new Block("Image Controls", join("
    ", $parts), "left", 50)); - } - } + public function display_admin_block(Page $page, $parts) + { + if (count($parts) > 0) { + $page->add_block(new Block("Image Controls", join("
    ", $parts), "left", 50)); + } + } - protected function build_pin(Image $image) { - if(isset($_GET['search'])) { - $query = "search=".url_escape($_GET['search']); - } - else { - $query = null; - } + protected function build_pin(Image $image) + { + if (isset($_GET['search'])) { + $query = "search=".url_escape($_GET['search']); + } else { + $query = null; + } - $h_prev = "Prev"; - $h_index = "Index"; - $h_next = "Next"; + $h_prev = "Prev"; + $h_index = "Index"; + $h_next = "Next"; - return "$h_prev | $h_index | $h_next"; - } + return "$h_prev | $h_index | $h_next"; + } - protected function build_navigation(Image $image): string { - $h_pin = $this->build_pin($image); - $h_search = " + protected function build_navigation(Image $image): string + { + $h_pin = $this->build_pin($image); + $h_search = "

    @@ -57,37 +62,39 @@ class ViewImageTheme extends Themelet {
    "; - return "$h_pin
    $h_search"; - } + return "$h_pin
    $h_search"; + } - protected function build_info(Image $image, $editor_parts) { - global $user; + protected function build_info(Image $image, $editor_parts) + { + global $user; - if(count($editor_parts) == 0) return ($image->is_locked() ? "
    [Image Locked]" : ""); + if (count($editor_parts) == 0) { + return ($image->is_locked() ? "
    [Image Locked]" : ""); + } - $html = make_form(make_link("post/set"))." + $html = make_form(make_link("post/set"))." "; - foreach($editor_parts as $part) { - $html .= $part; - } - if( - (!$image->is_locked() || $user->can("edit_image_lock")) && - $user->can("edit_image_tag") - ) { - $html .= " + foreach ($editor_parts as $part) { + $html .= $part; + } + if ( + (!$image->is_locked() || $user->can("edit_image_lock")) && + $user->can("edit_image_tag") + ) { + $html .= " "; - } - $html .= " + } + $html .= "
    "; - return $html; - } + return $html; + } } - diff --git a/ext/wiki/main.php b/ext/wiki/main.php index b85ab7c1..e0e14c8b 100644 --- a/ext/wiki/main.php +++ b/ext/wiki/main.php @@ -8,76 +8,85 @@ * Standard formatting APIs are used (This will be BBCode by default) */ -class WikiUpdateEvent extends Event { - /** @var \User */ - public $user; - /** @var \WikiPage */ - public $wikipage; +class WikiUpdateEvent extends Event +{ + /** @var \User */ + public $user; + /** @var \WikiPage */ + public $wikipage; - public function __construct(User $user, WikiPage $wikipage) { - $this->user = $user; - $this->wikipage = $wikipage; - } + public function __construct(User $user, WikiPage $wikipage) + { + $this->user = $user; + $this->wikipage = $wikipage; + } } -class WikiUpdateException extends SCoreException { +class WikiUpdateException extends SCoreException +{ } -class WikiPage { - /** @var int|string */ - public $id; +class WikiPage +{ + /** @var int|string */ + public $id; - /** @var int */ - public $owner_id; + /** @var int */ + public $owner_id; - /** @var string */ - public $owner_ip; + /** @var string */ + public $owner_ip; - /** @var string */ - public $date; + /** @var string */ + public $date; - /** @var string */ - public $title; + /** @var string */ + public $title; - /** @var int */ - public $revision; + /** @var int */ + public $revision; - /** @var bool */ - public $locked; + /** @var bool */ + public $locked; - /** @var string */ - public $body; + /** @var string */ + public $body; - public function __construct(array $row=null) { - //assert(!empty($row)); + public function __construct(array $row=null) + { + //assert(!empty($row)); - if (!is_null($row)) { - $this->id = $row['id']; - $this->owner_id = $row['owner_id']; - $this->owner_ip = $row['owner_ip']; - $this->date = $row['date']; - $this->title = $row['title']; - $this->revision = $row['revision']; - $this->locked = ($row['locked'] == 'Y'); - $this->body = $row['body']; - } - } + if (!is_null($row)) { + $this->id = $row['id']; + $this->owner_id = $row['owner_id']; + $this->owner_ip = $row['owner_ip']; + $this->date = $row['date']; + $this->title = $row['title']; + $this->revision = $row['revision']; + $this->locked = ($row['locked'] == 'Y'); + $this->body = $row['body']; + } + } - public function get_owner(): User { - return User::by_id($this->owner_id); - } + public function get_owner(): User + { + return User::by_id($this->owner_id); + } - public function is_locked(): bool { - return $this->locked; - } + public function is_locked(): bool + { + return $this->locked; + } } -class Wiki extends Extension { - public function onInitExt(InitExtEvent $event) { - global $database, $config; +class Wiki extends Extension +{ + public function onInitExt(InitExtEvent $event) + { + global $database, $config; - if($config->get_int("ext_wiki_version", 0) < 1) { - $database->create_table("wiki_pages", " + if ($config->get_int("ext_wiki_version", 0) < 1) { + $database->create_table("wiki_pages", " id SCORE_AIPK, owner_id INTEGER NOT NULL, owner_ip SCORE_INET NOT NULL, @@ -89,412 +98,399 @@ class Wiki extends Extension { UNIQUE (title, revision), FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT "); - $config->set_int("ext_wiki_version", 2); - } - if($config->get_int("ext_wiki_version") < 2) { - $database->Execute("ALTER TABLE wiki_pages ADD COLUMN + $config->set_int("ext_wiki_version", 2); + } + if ($config->get_int("ext_wiki_version") < 2) { + $database->Execute("ALTER TABLE wiki_pages ADD COLUMN locked ENUM('Y', 'N') DEFAULT 'N' NOT NULL AFTER REVISION"); - $config->set_int("ext_wiki_version", 2); - } - } + $config->set_int("ext_wiki_version", 2); + } + } - public function onPageRequest(PageRequestEvent $event) { - global $page, $user; - if($event->page_matches("wiki")) { - if(is_null($event->get_arg(0)) || strlen(trim($event->get_arg(0))) === 0) { - $title = "Index"; - } - else { - $title = $event->get_arg(0); - } + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("wiki")) { + if (is_null($event->get_arg(0)) || strlen(trim($event->get_arg(0))) === 0) { + $title = "Index"; + } else { + $title = $event->get_arg(0); + } - $content = $this->get_page($title); - $this->theme->display_page($page, $content, $this->get_page("wiki:sidebar")); - } - else if($event->page_matches("wiki_admin/edit")) { - $content = $this->get_page($_POST['title']); - $this->theme->display_page_editor($page, $content); - } - else if($event->page_matches("wiki_admin/save")) { - $title = $_POST['title']; - $rev = int_escape($_POST['revision']); - $body = $_POST['body']; - $lock = $user->is_admin() && isset($_POST['lock']) && ($_POST['lock'] == "on"); + $content = $this->get_page($title); + $this->theme->display_page($page, $content, $this->get_page("wiki:sidebar")); + } elseif ($event->page_matches("wiki_admin/edit")) { + $content = $this->get_page($_POST['title']); + $this->theme->display_page_editor($page, $content); + } elseif ($event->page_matches("wiki_admin/save")) { + $title = $_POST['title']; + $rev = int_escape($_POST['revision']); + $body = $_POST['body']; + $lock = $user->is_admin() && isset($_POST['lock']) && ($_POST['lock'] == "on"); - if($this->can_edit($user, $this->get_page($title))) { - $wikipage = $this->get_page($title); - $wikipage->revision = $rev; - $wikipage->body = $body; - $wikipage->locked = $lock; - try { - send_event(new WikiUpdateEvent($user, $wikipage)); + if ($this->can_edit($user, $this->get_page($title))) { + $wikipage = $this->get_page($title); + $wikipage->revision = $rev; + $wikipage->body = $body; + $wikipage->locked = $lock; + try { + send_event(new WikiUpdateEvent($user, $wikipage)); - $u_title = url_escape($title); - $page->set_mode("redirect"); - $page->set_redirect(make_link("wiki/$u_title")); - } - catch(WikiUpdateException $e) { - $original = $this->get_page($title); - // @ because arr_diff is full of warnings - $original->body = @$this->arr_diff( - explode("\n", $original->body), - explode("\n", $wikipage->body) - ); - $this->theme->display_page_editor($page, $original); - } - } - else { - $this->theme->display_permission_denied(); - } - } - else if($event->page_matches("wiki_admin/delete_revision")) { - if($user->is_admin()) { - global $database; - $database->Execute( - "DELETE FROM wiki_pages WHERE title=:title AND revision=:rev", - array("title"=>$_POST["title"], "rev"=>$_POST["revision"])); - $u_title = url_escape($_POST["title"]); - $page->set_mode("redirect"); - $page->set_redirect(make_link("wiki/$u_title")); - } - } - else if($event->page_matches("wiki_admin/delete_all")) { - if($user->is_admin()) { - global $database; - $database->Execute( - "DELETE FROM wiki_pages WHERE title=:title", - array("title"=>$_POST["title"])); - $u_title = url_escape($_POST["title"]); - $page->set_mode("redirect"); - $page->set_redirect(make_link("wiki/$u_title")); - } - } - } + $u_title = url_escape($title); + $page->set_mode("redirect"); + $page->set_redirect(make_link("wiki/$u_title")); + } catch (WikiUpdateException $e) { + $original = $this->get_page($title); + // @ because arr_diff is full of warnings + $original->body = @$this->arr_diff( + explode("\n", $original->body), + explode("\n", $wikipage->body) + ); + $this->theme->display_page_editor($page, $original); + } + } else { + $this->theme->display_permission_denied(); + } + } elseif ($event->page_matches("wiki_admin/delete_revision")) { + if ($user->is_admin()) { + global $database; + $database->Execute( + "DELETE FROM wiki_pages WHERE title=:title AND revision=:rev", + ["title"=>$_POST["title"], "rev"=>$_POST["revision"]] + ); + $u_title = url_escape($_POST["title"]); + $page->set_mode("redirect"); + $page->set_redirect(make_link("wiki/$u_title")); + } + } elseif ($event->page_matches("wiki_admin/delete_all")) { + if ($user->is_admin()) { + global $database; + $database->Execute( + "DELETE FROM wiki_pages WHERE title=:title", + ["title"=>$_POST["title"]] + ); + $u_title = url_escape($_POST["title"]); + $page->set_mode("redirect"); + $page->set_redirect(make_link("wiki/$u_title")); + } + } + } - public function onWikiUpdate(WikiUpdateEvent $event) { - global $database; - $wpage = $event->wikipage; - try { - $database->Execute(" + public function onWikiUpdate(WikiUpdateEvent $event) + { + global $database; + $wpage = $event->wikipage; + try { + $database->Execute(" INSERT INTO wiki_pages(owner_id, owner_ip, date, title, revision, locked, body) - VALUES (?, ?, now(), ?, ?, ?, ?)", array($event->user->id, $_SERVER['REMOTE_ADDR'], - $wpage->title, $wpage->revision, $wpage->locked?'Y':'N', $wpage->body)); - } - catch(Exception $e) { - throw new WikiUpdateException("Somebody else edited that page at the same time :-("); - } - } + VALUES (?, ?, now(), ?, ?, ?, ?)", [$event->user->id, $_SERVER['REMOTE_ADDR'], + $wpage->title, $wpage->revision, $wpage->locked?'Y':'N', $wpage->body]); + } catch (Exception $e) { + throw new WikiUpdateException("Somebody else edited that page at the same time :-("); + } + } - /** - * See if the given user is allowed to edit the given page. - */ - public static function can_edit(User $user, WikiPage $page): bool { - // admins can edit everything - if($user->is_admin()) return true; + /** + * See if the given user is allowed to edit the given page. + */ + public static function can_edit(User $user, WikiPage $page): bool + { + // admins can edit everything + if ($user->is_admin()) { + return true; + } - // anon / user can't ever edit locked pages - if($page->is_locked()) return false; + // anon / user can't ever edit locked pages + if ($page->is_locked()) { + return false; + } - // anon / user can edit if allowed by config - if($user->can("edit_wiki_page")) return true; + // anon / user can edit if allowed by config + if ($user->can("edit_wiki_page")) { + return true; + } - return false; - } + return false; + } - private function get_page(string $title, int $revision=-1): WikiPage { - global $database; - // first try and get the actual page - $row = $database->get_row($database->scoreql_to_sql(" + private function get_page(string $title, int $revision=-1): WikiPage + { + global $database; + // first try and get the actual page + $row = $database->get_row( + $database->scoreql_to_sql(" SELECT * FROM wiki_pages WHERE SCORE_STRNORM(title) LIKE SCORE_STRNORM(:title) ORDER BY revision DESC"), - array("title"=>$title)); + ["title"=>$title] + ); - // fall back to wiki:default - if(empty($row)) { - $row = $database->get_row(" + // fall back to wiki:default + if (empty($row)) { + $row = $database->get_row(" SELECT * FROM wiki_pages WHERE title LIKE :title - ORDER BY revision DESC", array("title"=>"wiki:default")); + ORDER BY revision DESC", ["title"=>"wiki:default"]); - // fall further back to manual - if(empty($row)) { - $row = array( - "id" => -1, - "owner_ip" => "0.0.0.0", - "date" => "", - "revision" => 0, - "locked" => false, - "body" => "This is a default page for when a page is empty, ". - "it can be edited by editing [[wiki:default]].", - ); - } + // fall further back to manual + if (empty($row)) { + $row = [ + "id" => -1, + "owner_ip" => "0.0.0.0", + "date" => "", + "revision" => 0, + "locked" => false, + "body" => "This is a default page for when a page is empty, ". + "it can be edited by editing [[wiki:default]].", + ]; + } - // correct the default - global $config; - $row["title"] = $title; - $row["owner_id"] = $config->get_int("anon_id", 0); - } + // correct the default + global $config; + $row["title"] = $title; + $row["owner_id"] = $config->get_int("anon_id", 0); + } - assert(!empty($row)); + assert(!empty($row)); - return new WikiPage($row); - } + return new WikiPage($row); + } -// php-diff {{{ - /** - Diff implemented in pure php, written from scratch. - Copyright (C) 2003 Daniel Unterberger - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - http://www.gnu.org/licenses/gpl.html + // php-diff {{{ + /** + Diff implemented in pure php, written from scratch. + Copyright (C) 2003 Daniel Unterberger - About: - I searched a function to compare arrays and the array_diff() - was not specific enough. It ignores the order of the array-values. - So I reimplemented the diff-function which is found on unix-systems - but this you can use directly in your code and adopt for your needs. - Simply adopt the formatline-function. with the third-parameter of arr_diff() - you can hide matching lines. Hope someone has use for this. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. - Contact: d.u.diff@holomind.de - **/ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - private function arr_diff( $f1 , $f2 , $show_equal = 0 ) - { + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - $c1 = 0 ; # current line of left - $c2 = 0 ; # current line of right - $max1 = count( $f1 ) ; # maximal lines of left - $max2 = count( $f2 ) ; # maximal lines of right - $outcount = 0; # output counter - $hit1 = "" ; # hit in left - $hit2 = "" ; # hit in right - $stop = 0; - $out = ""; + http://www.gnu.org/licenses/gpl.html - while ( - $c1 < $max1 # have next line in left - and - $c2 < $max2 # have next line in right - and - ($stop++) < 1000 # don-t have more then 1000 ( loop-stopper ) - and - $outcount < 20 # output count is less then 20 - ) - { - /** - * is the trimmed line of the current left and current right line - * the same ? then this is a hit (no difference) - */ - if ( trim( $f1[$c1] ) == trim ( $f2[$c2]) ) - { - /** - * add to output-string, if "show_equal" is enabled - */ - $out .= ($show_equal==1) - ? formatline ( ($c1) , ($c2), "=", $f1[ $c1 ] ) - : "" ; - /** - * increase the out-putcounter, if "show_equal" is enabled - * this ist more for demonstration purpose - */ - if ( $show_equal == 1 ) - { - $outcount++ ; - } + About: + I searched a function to compare arrays and the array_diff() + was not specific enough. It ignores the order of the array-values. + So I reimplemented the diff-function which is found on unix-systems + but this you can use directly in your code and adopt for your needs. + Simply adopt the formatline-function. with the third-parameter of arr_diff() + you can hide matching lines. Hope someone has use for this. + + Contact: d.u.diff@holomind.de + **/ + + private function arr_diff($f1, $f2, $show_equal = 0) + { + $c1 = 0 ; # current line of left + $c2 = 0 ; # current line of right + $max1 = count($f1) ; # maximal lines of left + $max2 = count($f2) ; # maximal lines of right + $outcount = 0; # output counter + $hit1 = "" ; # hit in left + $hit2 = "" ; # hit in right + $stop = 0; + $out = ""; + + while ( + $c1 < $max1 # have next line in left + and + $c2 < $max2 # have next line in right + and + ($stop++) < 1000 # don-t have more then 1000 ( loop-stopper ) + and + $outcount < 20 # output count is less then 20 + ) { + /** + * is the trimmed line of the current left and current right line + * the same ? then this is a hit (no difference) + */ + if (trim($f1[$c1]) == trim($f2[$c2])) { + /** + * add to output-string, if "show_equal" is enabled + */ + $out .= ($show_equal==1) + ? formatline(($c1), ($c2), "=", $f1[ $c1 ]) + : "" ; + /** + * increase the out-putcounter, if "show_equal" is enabled + * this ist more for demonstration purpose + */ + if ($show_equal == 1) { + $outcount++ ; + } - /** - * move the current-pointer in the left and right side - */ - $c1 ++; - $c2 ++; - } + /** + * move the current-pointer in the left and right side + */ + $c1 ++; + $c2 ++; + } - /** - * the current lines are different so we search in parallel - * on each side for the next matching pair, we walk on both - * sided at the same time comparing with the current-lines - * this should be most probable to find the next matching pair - * we only search in a distance of 10 lines, because then it - * is not the same function most of the time. other algos - * would be very complicated, to detect 'real' block movements. - */ - else - { - - $b = "" ; - $s1 = 0 ; # search on left - $s2 = 0 ; # search on right - $found = 0 ; # flag, found a matching pair - $b1 = "" ; - $b2 = "" ; - $fstop = 0 ; # distance of maximum search + /** + * the current lines are different so we search in parallel + * on each side for the next matching pair, we walk on both + * sided at the same time comparing with the current-lines + * this should be most probable to find the next matching pair + * we only search in a distance of 10 lines, because then it + * is not the same function most of the time. other algos + * would be very complicated, to detect 'real' block movements. + */ + else { + $b = "" ; + $s1 = 0 ; # search on left + $s2 = 0 ; # search on right + $found = 0 ; # flag, found a matching pair + $b1 = "" ; + $b2 = "" ; + $fstop = 0 ; # distance of maximum search - #fast search in on both sides for next match. - while ( - $found == 0 # search until we find a pair - and - ( $c1 + $s1 <= $max1 ) # and we are inside of the left lines - and - ( $c2 + $s2 <= $max2 ) # and we are inside of the right lines - and - $fstop++ < 10 # and the distance is lower than 10 lines - ) - { + #fast search in on both sides for next match. + while ( + $found == 0 # search until we find a pair + and + ($c1 + $s1 <= $max1) # and we are inside of the left lines + and + ($c2 + $s2 <= $max2) # and we are inside of the right lines + and + $fstop++ < 10 # and the distance is lower than 10 lines + ) { - /** - * test the left side for a hit - * - * comparing current line with the searching line on the left - * b1 is a buffer, which collects the line which not match, to - * show the differences later, if one line hits, this buffer will - * be used, else it will be discarded later - */ - #hit - if ( trim( $f1[$c1+$s1] ) == trim( $f2[$c2] ) ) - { - $found = 1 ; # set flag to stop further search - $s2 = 0 ; # reset right side search-pointer - $c2-- ; # move back the current right, so next loop hits - $b = $b1 ; # set b=output (b)uffer - } - #no hit: move on - else - { - /** - * prevent finding a line again, which would show wrong results - * - * add the current line to leftbuffer, if this will be the hit - */ - if ( $hit1[ ($c1 + $s1) . "_" . ($c2) ] != 1 ) - { - /** - * add current search-line to diffence-buffer - */ - $b1 .= $this->formatline( ($c1 + $s1) , ($c2), "-", $f1[ $c1+$s1 ] ); + /** + * test the left side for a hit + * + * comparing current line with the searching line on the left + * b1 is a buffer, which collects the line which not match, to + * show the differences later, if one line hits, this buffer will + * be used, else it will be discarded later + */ + #hit + if (trim($f1[$c1+$s1]) == trim($f2[$c2])) { + $found = 1 ; # set flag to stop further search + $s2 = 0 ; # reset right side search-pointer + $c2-- ; # move back the current right, so next loop hits + $b = $b1 ; # set b=output (b)uffer + } + #no hit: move on + else { + /** + * prevent finding a line again, which would show wrong results + * + * add the current line to leftbuffer, if this will be the hit + */ + if ($hit1[ ($c1 + $s1) . "_" . ($c2) ] != 1) { + /** + * add current search-line to diffence-buffer + */ + $b1 .= $this->formatline(($c1 + $s1), ($c2), "-", $f1[ $c1+$s1 ]); - /** - * mark this line as 'searched' to prevent doubles. - */ - $hit1[ ($c1 + $s1) . "_" . $c2 ] = 1 ; - } - } + /** + * mark this line as 'searched' to prevent doubles. + */ + $hit1[ ($c1 + $s1) . "_" . $c2 ] = 1 ; + } + } - /** - * test the right side for a hit - * - * comparing current line with the searching line on the right - */ - if ( trim ( $f1[$c1] ) == trim ( $f2[$c2+$s2]) ) - { - $found = 1 ; # flag to stop search - $s1 = 0 ; # reset pointer for search - $c1-- ; # move current line back, so we hit next loop - $b = $b2 ; # get the buffered difference - } - else - { - /** - * prevent to find line again - */ - if ( $hit2[ ($c1) . "_" . ( $c2 + $s2) ] != 1 ) - { - /** - * add current searchline to buffer - */ - $b2 .= $this->formatline ( ($c1) , ($c2 + $s2), "+", $f2[ $c2+$s2 ] ); + /** + * test the right side for a hit + * + * comparing current line with the searching line on the right + */ + if (trim($f1[$c1]) == trim($f2[$c2+$s2])) { + $found = 1 ; # flag to stop search + $s1 = 0 ; # reset pointer for search + $c1-- ; # move current line back, so we hit next loop + $b = $b2 ; # get the buffered difference + } else { + /** + * prevent to find line again + */ + if ($hit2[ ($c1) . "_" . ($c2 + $s2) ] != 1) { + /** + * add current searchline to buffer + */ + $b2 .= $this->formatline(($c1), ($c2 + $s2), "+", $f2[ $c2+$s2 ]); - /** - * mark current line to prevent double-hits - */ - $hit2[ ($c1) . "_" . ($c2 + $s2) ] = 1; - } + /** + * mark current line to prevent double-hits + */ + $hit2[ ($c1) . "_" . ($c2 + $s2) ] = 1; + } + } - } + /** + * search in bigger distance + * + * increase the search-pointers (satelites) and try again + */ + $s1++ ; # increase left search-pointer + $s2++ ; # increase right search-pointer + } - /** - * search in bigger distance - * - * increase the search-pointers (satelites) and try again - */ - $s1++ ; # increase left search-pointer - $s2++ ; # increase right search-pointer - } + /** + * add line as different on both arrays (no match found) + */ + if ($found == 0) { + $b .= $this->formatline(($c1), ($c2), "-", $f1[ $c1 ]); + $b .= $this->formatline(($c1), ($c2), "+", $f2[ $c2 ]); + } - /** - * add line as different on both arrays (no match found) - */ - if ( $found == 0 ) - { - $b .= $this->formatline ( ($c1) , ($c2), "-", $f1[ $c1 ] ); - $b .= $this->formatline ( ($c1) , ($c2), "+", $f2[ $c2 ] ); - } + /** + * add current buffer to outputstring + */ + $out .= $b; + $outcount++ ; #increase outcounter - /** - * add current buffer to outputstring - */ - $out .= $b; - $outcount++ ; #increase outcounter + $c1++ ; #move currentline forward + $c2++ ; #move currentline forward - $c1++ ; #move currentline forward - $c2++ ; #move currentline forward + /** + * comment the lines are tested quite fast, because + * the current line always moves forward + */ + } /*endif*/ + }/*endwhile*/ - /** - * comment the lines are tested quite fast, because - * the current line always moves forward - */ + return $out; + }/*end func*/ - } /*endif*/ + /** + * callback function to format the diffence-lines with your 'style' + */ + private function formatline(int $nr1, int $nr2, string $stat, &$value): string + { #change to $value if problems + if (trim($value) == "") { + return ""; + } - }/*endwhile*/ + switch ($stat) { + case "=": + // return $nr1. " : $nr2 : = ".htmlentities( $value ) ."
    "; + return "$value\n"; + break; - return $out; + case "+": + //return $nr1. " : $nr2 : + ".htmlentities( $value ) ."
    "; + return "+++ $value\n"; + break; - }/*end func*/ - - /** - * callback function to format the diffence-lines with your 'style' - */ - private function formatline(int $nr1, int $nr2, string $stat, &$value ): string { #change to $value if problems - if(trim($value) == "") { - return ""; - } - - switch($stat) { - case "=": - // return $nr1. " : $nr2 : = ".htmlentities( $value ) ."
    "; - return "$value\n"; - break; - - case "+": - //return $nr1. " : $nr2 : + ".htmlentities( $value ) ."
    "; - return "+++ $value\n"; - break; - - case "-": - //return $nr1. " : $nr2 : - ".htmlentities( $value ) ."
    "; - return "--- $value\n"; - break; - } - } -// }}} + case "-": + //return $nr1. " : $nr2 : - ".htmlentities( $value ) ."
    "; + return "--- $value\n"; + break; + } + } + // }}} } - diff --git a/ext/wiki/test.php b/ext/wiki/test.php index 8d6e9bb2..dfd6d71b 100644 --- a/ext/wiki/test.php +++ b/ext/wiki/test.php @@ -1,122 +1,130 @@ get_page("wiki"); - $this->assert_title("Index"); - $this->assert_text("This is a default page"); - } +class WikiTest extends ShimmiePHPUnitTestCase +{ + public function testIndex() + { + $this->get_page("wiki"); + $this->assert_title("Index"); + $this->assert_text("This is a default page"); + } - public function testAccess() { - $this->markTestIncomplete(); + public function testAccess() + { + $this->markTestIncomplete(); - global $config; - foreach(array("anon", "user", "admin") as $user) { - foreach(array(false, true) as $allowed) { - // admin has no settings to set - if($user != "admin") { - $config->set_bool("wiki_edit_$user", $allowed); - } + global $config; + foreach (["anon", "user", "admin"] as $user) { + foreach ([false, true] as $allowed) { + // admin has no settings to set + if ($user != "admin") { + $config->set_bool("wiki_edit_$user", $allowed); + } - if($user == "user") {$this->log_in_as_user();} - if($user == "admin") {$this->log_in_as_admin();} + if ($user == "user") { + $this->log_in_as_user(); + } + if ($user == "admin") { + $this->log_in_as_admin(); + } - $this->get_page("wiki/test"); - $this->assert_title("test"); - $this->assert_text("This is a default page"); + $this->get_page("wiki/test"); + $this->assert_title("test"); + $this->assert_text("This is a default page"); - if($allowed || $user == "admin") { - $this->get_page("wiki/test", array('edit'=>'on')); - $this->assert_text("Editor"); - } - else { - $this->get_page("wiki/test", array('edit'=>'on')); - $this->assert_no_text("Editor"); - } + if ($allowed || $user == "admin") { + $this->get_page("wiki/test", ['edit'=>'on']); + $this->assert_text("Editor"); + } else { + $this->get_page("wiki/test", ['edit'=>'on']); + $this->assert_no_text("Editor"); + } - if($user == "user" || $user == "admin") { - $this->log_out(); - } - } - } - } + if ($user == "user" || $user == "admin") { + $this->log_out(); + } + } + } + } - public function testLock() { - $this->markTestIncomplete(); + public function testLock() + { + $this->markTestIncomplete(); - global $config; - $config->set_bool("wiki_edit_anon", true); - $config->set_bool("wiki_edit_user", false); + global $config; + $config->set_bool("wiki_edit_anon", true); + $config->set_bool("wiki_edit_user", false); - $this->log_in_as_admin(); + $this->log_in_as_admin(); - $this->get_page("wiki/test_locked"); - $this->assert_title("test_locked"); - $this->assert_text("This is a default page"); - $this->click("Edit"); - $this->set_field("body", "test_locked content"); - $this->set_field("lock", true); - $this->click("Save"); - $this->log_out(); + $this->get_page("wiki/test_locked"); + $this->assert_title("test_locked"); + $this->assert_text("This is a default page"); + $this->click("Edit"); + $this->set_field("body", "test_locked content"); + $this->set_field("lock", true); + $this->click("Save"); + $this->log_out(); - $this->log_in_as_user(); - $this->get_page("wiki/test_locked"); - $this->assert_title("test_locked"); - $this->assert_text("test_locked content"); - $this->assert_no_text("Edit"); - $this->log_out(); + $this->log_in_as_user(); + $this->get_page("wiki/test_locked"); + $this->assert_title("test_locked"); + $this->assert_text("test_locked content"); + $this->assert_no_text("Edit"); + $this->log_out(); - $this->get_page("wiki/test_locked"); - $this->assert_title("test_locked"); - $this->assert_text("test_locked content"); - $this->assert_no_text("Edit"); + $this->get_page("wiki/test_locked"); + $this->assert_title("test_locked"); + $this->assert_text("test_locked content"); + $this->assert_no_text("Edit"); - $this->log_in_as_admin(); - $this->get_page("wiki/test_locked"); - $this->click("Delete All"); - $this->log_out(); - } + $this->log_in_as_admin(); + $this->get_page("wiki/test_locked"); + $this->click("Delete All"); + $this->log_out(); + } - public function testDefault() { - $this->markTestIncomplete(); + public function testDefault() + { + $this->markTestIncomplete(); - $this->log_in_as_admin(); - $this->get_page("wiki/wiki:default"); - $this->assert_title("wiki:default"); - $this->assert_text("This is a default page"); - $this->click("Edit"); - $this->set_field("body", "Empty page! Fill it!"); - $this->click("Save"); + $this->log_in_as_admin(); + $this->get_page("wiki/wiki:default"); + $this->assert_title("wiki:default"); + $this->assert_text("This is a default page"); + $this->click("Edit"); + $this->set_field("body", "Empty page! Fill it!"); + $this->click("Save"); - $this->get_page("wiki/something"); - $this->assert_text("Empty page! Fill it!"); + $this->get_page("wiki/something"); + $this->assert_text("Empty page! Fill it!"); - $this->get_page("wiki/wiki:default"); - $this->click("Delete All"); - $this->log_out(); - } + $this->get_page("wiki/wiki:default"); + $this->click("Delete All"); + $this->log_out(); + } - public function testRevisions() { - $this->markTestIncomplete(); + public function testRevisions() + { + $this->markTestIncomplete(); - $this->log_in_as_admin(); - $this->get_page("wiki/test"); - $this->assert_title("test"); - $this->assert_text("This is a default page"); - $this->click("Edit"); - $this->set_field("body", "Mooooo 1"); - $this->click("Save"); - $this->assert_text("Mooooo 1"); - $this->assert_text("Revision 1"); - $this->click("Edit"); - $this->set_field("body", "Mooooo 2"); - $this->click("Save"); - $this->assert_text("Mooooo 2"); - $this->assert_text("Revision 2"); - $this->click("Delete This Version"); - $this->assert_text("Mooooo 1"); - $this->assert_text("Revision 1"); - $this->click("Delete All"); - $this->log_out(); - } + $this->log_in_as_admin(); + $this->get_page("wiki/test"); + $this->assert_title("test"); + $this->assert_text("This is a default page"); + $this->click("Edit"); + $this->set_field("body", "Mooooo 1"); + $this->click("Save"); + $this->assert_text("Mooooo 1"); + $this->assert_text("Revision 1"); + $this->click("Edit"); + $this->set_field("body", "Mooooo 2"); + $this->click("Save"); + $this->assert_text("Mooooo 2"); + $this->assert_text("Revision 2"); + $this->click("Delete This Version"); + $this->assert_text("Mooooo 1"); + $this->assert_text("Revision 1"); + $this->click("Delete All"); + $this->log_out(); + } } - diff --git a/ext/wiki/theme.php b/ext/wiki/theme.php index 5a00982a..f67c9d8f 100644 --- a/ext/wiki/theme.php +++ b/ext/wiki/theme.php @@ -1,55 +1,58 @@ title and ->body - * $nav_page A wiki page object with navigation, has ->body - */ - public function display_page(Page $page, WikiPage $wiki_page, ?WikiPage $nav_page=null) { - global $user; +class WikiTheme extends Themelet +{ + /** + * Show a page. + * + * $wiki_page The wiki page, has ->title and ->body + * $nav_page A wiki page object with navigation, has ->body + */ + public function display_page(Page $page, WikiPage $wiki_page, ?WikiPage $nav_page=null) + { + global $user; - if(is_null($nav_page)) { - $nav_page = new WikiPage(); - $nav_page->body = ""; - } + if (is_null($nav_page)) { + $nav_page = new WikiPage(); + $nav_page->body = ""; + } - $tfe = new TextFormattingEvent($nav_page->body); - send_event($tfe); + $tfe = new TextFormattingEvent($nav_page->body); + send_event($tfe); - // only the admin can edit the sidebar - if($user->is_admin()) { - $tfe->formatted .= "

    (Edit)"; - } + // only the admin can edit the sidebar + if ($user->is_admin()) { + $tfe->formatted .= "

    (Edit)"; + } - $page->set_title(html_escape($wiki_page->title)); - $page->set_heading(html_escape($wiki_page->title)); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Wiki Index", $tfe->formatted, "left", 20)); - $page->add_block(new Block(html_escape($wiki_page->title), $this->create_display_html($wiki_page))); - } + $page->set_title(html_escape($wiki_page->title)); + $page->set_heading(html_escape($wiki_page->title)); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Wiki Index", $tfe->formatted, "left", 20)); + $page->add_block(new Block(html_escape($wiki_page->title), $this->create_display_html($wiki_page))); + } - public function display_page_editor(Page $page, WikiPage $wiki_page) { - $page->set_title(html_escape($wiki_page->title)); - $page->set_heading(html_escape($wiki_page->title)); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Editor", $this->create_edit_html($wiki_page))); - } + public function display_page_editor(Page $page, WikiPage $wiki_page) + { + $page->set_title(html_escape($wiki_page->title)); + $page->set_heading(html_escape($wiki_page->title)); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Editor", $this->create_edit_html($wiki_page))); + } - protected function create_edit_html(WikiPage $page) { - $h_title = html_escape($page->title); - $i_revision = int_escape($page->revision) + 1; + protected function create_edit_html(WikiPage $page) + { + $h_title = html_escape($page->title); + $i_revision = int_escape($page->revision) + 1; - global $user; - if($user->is_admin()) { - $val = $page->is_locked() ? " checked" : ""; - $lock = "
    Lock page: "; - } - else { - $lock = ""; - } - return " + global $user; + if ($user->is_admin()) { + $val = $page->is_locked() ? " checked" : ""; + $lock = "
    Lock page: "; + } else { + $lock = ""; + } + return " ".make_form(make_link("wiki_admin/save"))." @@ -58,28 +61,29 @@ class WikiTheme extends Themelet {
    "; - } + } - protected function create_display_html(WikiPage $page) { - global $user; + protected function create_display_html(WikiPage $page) + { + global $user; - $owner = $page->get_owner(); + $owner = $page->get_owner(); - $tfe = new TextFormattingEvent($page->body); - send_event($tfe); + $tfe = new TextFormattingEvent($page->body); + send_event($tfe); - $edit = ""; - $edit .= Wiki::can_edit($user, $page) ? - " + $edit = "
    "; + $edit .= Wiki::can_edit($user, $page) ? + " " : - ""; - if($user->is_admin()) { - $edit .= " + ""; + if ($user->is_admin()) { + $edit .= " "; - } - $edit .= "
    ".make_form(make_link("wiki_admin/edit"))." ".make_form(make_link("wiki_admin/delete_revision"))." @@ -90,10 +94,10 @@ class WikiTheme extends Themelet {
    "; + } + $edit .= ""; - return " + return "

    $tfe->formatted
    @@ -105,6 +109,5 @@ class WikiTheme extends Themelet {

    "; - } + } } - diff --git a/ext/word_filter/main.php b/ext/word_filter/main.php index f858f3a6..d6933383 100644 --- a/ext/word_filter/main.php +++ b/ext/word_filter/main.php @@ -7,53 +7,59 @@ * Description: Simple search and replace */ -class WordFilter extends Extension { - // before emoticon filter - public function get_priority(): int {return 40;} +class WordFilter extends Extension +{ + // before emoticon filter + public function get_priority(): int + { + return 40; + } - public function onTextFormatting(TextFormattingEvent $event) { - $event->formatted = $this->filter($event->formatted); - $event->stripped = $this->filter($event->stripped); - } + public function onTextFormatting(TextFormattingEvent $event) + { + $event->formatted = $this->filter($event->formatted); + $event->stripped = $this->filter($event->stripped); + } - public function onSetupBuilding(SetupBuildingEvent $event) { - $sb = new SetupBlock("Word Filter"); - $sb->add_longtext_option("word_filter"); - $sb->add_label("
    (each line should be search term and replace term, separated by a comma)"); - $event->panel->add_block($sb); - } + public function onSetupBuilding(SetupBuildingEvent $event) + { + $sb = new SetupBlock("Word Filter"); + $sb->add_longtext_option("word_filter"); + $sb->add_label("
    (each line should be search term and replace term, separated by a comma)"); + $event->panel->add_block($sb); + } - private function filter(string $text): string { - $map = $this->get_map(); - foreach($map as $search => $replace) { - $search = trim($search); - $replace = trim($replace); - if($search[0] == '/') { - $text = preg_replace($search, $replace, $text); - } - else { - $search = "/\\b" . str_replace("/", "\\/", $search) . "\\b/i"; - $text = preg_replace($search, $replace, $text); - } - } - return $text; - } + private function filter(string $text): string + { + $map = $this->get_map(); + foreach ($map as $search => $replace) { + $search = trim($search); + $replace = trim($replace); + if ($search[0] == '/') { + $text = preg_replace($search, $replace, $text); + } else { + $search = "/\\b" . str_replace("/", "\\/", $search) . "\\b/i"; + $text = preg_replace($search, $replace, $text); + } + } + return $text; + } - /** - * #return string[] - */ - private function get_map(): array { - global $config; - $raw = $config->get_string("word_filter"); - $lines = explode("\n", $raw); - $map = array(); - foreach($lines as $line) { - $parts = explode(",", $line); - if(count($parts) == 2) { - $map[$parts[0]] = $parts[1]; - } - } - return $map; - } + /** + * #return string[] + */ + private function get_map(): array + { + global $config; + $raw = $config->get_string("word_filter"); + $lines = explode("\n", $raw); + $map = []; + foreach ($lines as $line) { + $parts = explode(",", $line); + if (count($parts) == 2) { + $map[$parts[0]] = $parts[1]; + } + } + return $map; + } } - diff --git a/ext/word_filter/test.php b/ext/word_filter/test.php index 4ac1748d..c75069b2 100644 --- a/ext/word_filter/test.php +++ b/ext/word_filter/test.php @@ -1,67 +1,76 @@ set_string("word_filter", "whore,nice lady\na duck,a kitten\n white ,\tspace\ninvalid"); - } +class WordFilterTest extends ShimmiePHPUnitTestCase +{ + public function setUp() + { + global $config; + parent::setUp(); + $config->set_string("word_filter", "whore,nice lady\na duck,a kitten\n white ,\tspace\ninvalid"); + } - public function _doThings($in, $out) { - global $user; - $this->log_in_as_user(); - $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - send_event(new CommentPostingEvent($image_id, $user, $in)); - $this->get_page("post/view/$image_id"); - $this->assert_text($out); - } + public function _doThings($in, $out) + { + global $user; + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); + send_event(new CommentPostingEvent($image_id, $user, $in)); + $this->get_page("post/view/$image_id"); + $this->assert_text($out); + } - public function testRegular() { - $this->_doThings( - "posted by a whore", - "posted by a nice lady" - ); - } + public function testRegular() + { + $this->_doThings( + "posted by a whore", + "posted by a nice lady" + ); + } - public function testReplaceAll() { - $this->_doThings( - "a whore is a whore is a whore", - "a nice lady is a nice lady is a nice lady" - ); - } + public function testReplaceAll() + { + $this->_doThings( + "a whore is a whore is a whore", + "a nice lady is a nice lady is a nice lady" + ); + } - public function testMixedCase() { - $this->_doThings( - "monkey WhorE", - "monkey nice lady" - ); - } + public function testMixedCase() + { + $this->_doThings( + "monkey WhorE", + "monkey nice lady" + ); + } - public function testOnlyWholeWords() { - $this->_doThings( - "my name is whoretta", - "my name is whoretta" - ); - } + public function testOnlyWholeWords() + { + $this->_doThings( + "my name is whoretta", + "my name is whoretta" + ); + } - public function testMultipleWords() { - $this->_doThings( - "I would like a duck", - "I would like a kitten" - ); - } + public function testMultipleWords() + { + $this->_doThings( + "I would like a duck", + "I would like a kitten" + ); + } - public function testWhitespace() { - $this->_doThings( - "A colour is white", - "A colour is space" - ); - } + public function testWhitespace() + { + $this->_doThings( + "A colour is white", + "A colour is space" + ); + } - public function testIgnoreInvalid() { - $this->_doThings( - "The word was invalid", - "The word was invalid" - ); - } + public function testIgnoreInvalid() + { + $this->_doThings( + "The word was invalid", + "The word was invalid" + ); + } } - diff --git a/index.php b/index.php index 7c9ee6b9..b9c0b824 100644 --- a/index.php +++ b/index.php @@ -43,18 +43,18 @@ * Each of these can be imported at the start of a function with eg "global $page, $user;" */ -if(!file_exists("data/config/shimmie.conf.php")) { - require_once "core/_install.php"; - exit; +if (!file_exists("data/config/shimmie.conf.php")) { + require_once "core/_install.php"; + exit; } -if(file_exists("images") && !file_exists("data/images")) { - die("As of Shimmie 2.7 images and thumbs should be moved to data/images and data/thumbs"); +if (file_exists("images") && !file_exists("data/images")) { + die("As of Shimmie 2.7 images and thumbs should be moved to data/images and data/thumbs"); } -if(!file_exists("vendor/")) { - //CHECK: Should we just point to install.php instead? Seems unsafe though. - print << @@ -79,33 +79,34 @@ if(!file_exists("vendor/")) { EOD; - http_response_code(500); - exit; + http_response_code(500); + exit; } try { - require_once "core/_bootstrap.php"; - $_shm_ctx->log_start(@$_SERVER["REQUEST_URI"], true, true); + require_once "core/_bootstrap.php"; + $_shm_ctx->log_start(@$_SERVER["REQUEST_URI"], true, true); - // start the page generation waterfall - $user = _get_user(); - if(PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { - send_event(new CommandEvent($argv)); - } - else { - send_event(new PageRequestEvent(_get_query())); - $page->display(); - } + // start the page generation waterfall + $user = _get_user(); + if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { + send_event(new CommandEvent($argv)); + } else { + send_event(new PageRequestEvent(_get_query())); + $page->display(); + } - // saving cache data and profiling data to disk can happen later - if(function_exists("fastcgi_finish_request")) fastcgi_finish_request(); - $database->commit(); - $_shm_ctx->log_endok(); -} -catch(Exception $e) { - if($database) $database->rollback(); - _fatal_error($e); - $_shm_ctx->log_ender(); + // saving cache data and profiling data to disk can happen later + if (function_exists("fastcgi_finish_request")) { + fastcgi_finish_request(); + } + $database->commit(); + $_shm_ctx->log_endok(); +} catch (Exception $e) { + if ($database) { + $database->rollback(); + } + _fatal_error($e); + $_shm_ctx->log_ender(); } log_slow(); - diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 62275c63..28539364 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -10,144 +10,165 @@ $_SERVER['QUERY_STRING'] = '/'; chdir(dirname(dirname(__FILE__))); require_once "core/_bootstrap.php"; -if(is_null(User::by_name("demo"))) { - $userPage = new UserPage(); - $userPage->onUserCreation(new UserCreationEvent("demo", "demo", "")); - $userPage->onUserCreation(new UserCreationEvent("test", "test", "")); +if (is_null(User::by_name("demo"))) { + $userPage = new UserPage(); + $userPage->onUserCreation(new UserCreationEvent("demo", "demo", "")); + $userPage->onUserCreation(new UserCreationEvent("test", "test", "")); } -abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase { - private $images = array(); +abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase +{ + private $images = []; - public function setUp() { - $class = str_replace("Test", "", get_class($this)); - if(!class_exists($class)) { - $this->markTestSkipped("$class not loaded"); - } - elseif(!ext_is_live($class)) { - $this->markTestSkipped("$class not supported with this database"); - } + public function setUp() + { + $class = str_replace("Test", "", get_class($this)); + if (!class_exists($class)) { + $this->markTestSkipped("$class not loaded"); + } elseif (!ext_is_live($class)) { + $this->markTestSkipped("$class not supported with this database"); + } - // things to do after bootstrap and before request - // log in as anon - $this->log_out(); - } + // things to do after bootstrap and before request + // log in as anon + $this->log_out(); + } - public function tearDown() { - foreach($this->images as $image_id) { - $this->delete_image($image_id); - } - } + public function tearDown() + { + foreach ($this->images as $image_id) { + $this->delete_image($image_id); + } + } - protected function get_page($page_name, $args=null) { - // use a fresh page - global $page; - if(!$args) $args = array(); - $_GET = $args; - $_POST = array(); - $page = class_exists("CustomPage") ? new CustomPage() : new Page(); - send_event(new PageRequestEvent($page_name)); - if($page->mode == "redirect") { - $page->code = 302; - } - } + protected function get_page($page_name, $args=null) + { + // use a fresh page + global $page; + if (!$args) { + $args = []; + } + $_GET = $args; + $_POST = []; + $page = class_exists("CustomPage") ? new CustomPage() : new Page(); + send_event(new PageRequestEvent($page_name)); + if ($page->mode == "redirect") { + $page->code = 302; + } + } - protected function post_page($page_name, $args=null) { - // use a fresh page - global $page; - if(!$args) $args = array(); - $_GET = array(); - $_POST = $args; - $page = class_exists("CustomPage") ? new CustomPage() : new Page(); - send_event(new PageRequestEvent($page_name)); - if($page->mode == "redirect") { - $page->code = 302; - } - } + protected function post_page($page_name, $args=null) + { + // use a fresh page + global $page; + if (!$args) { + $args = []; + } + $_GET = []; + $_POST = $args; + $page = class_exists("CustomPage") ? new CustomPage() : new Page(); + send_event(new PageRequestEvent($page_name)); + if ($page->mode == "redirect") { + $page->code = 302; + } + } - // page things - protected function assert_title(string $title) { - global $page; - $this->assertContains($title, $page->title); - } + // page things + protected function assert_title(string $title) + { + global $page; + $this->assertContains($title, $page->title); + } - protected function assert_no_title(string $title) { - global $page; - $this->assertNotContains($title, $page->title); - } + protected function assert_no_title(string $title) + { + global $page; + $this->assertNotContains($title, $page->title); + } - protected function assert_response(int $code) { - global $page; - $this->assertEquals($code, $page->code); - } + protected function assert_response(int $code) + { + global $page; + $this->assertEquals($code, $page->code); + } - protected function page_to_text(string $section=null) { - global $page; - $text = $page->title . "\n"; - foreach($page->blocks as $block) { - if(is_null($section) || $section == $block->section) { - $text .= $block->header . "\n"; - $text .= $block->body . "\n\n"; - } - } - return $text; - } + protected function page_to_text(string $section=null) + { + global $page; + $text = $page->title . "\n"; + foreach ($page->blocks as $block) { + if (is_null($section) || $section == $block->section) { + $text .= $block->header . "\n"; + $text .= $block->body . "\n\n"; + } + } + return $text; + } - protected function assert_text(string $text, string $section=null) { - $this->assertContains($text, $this->page_to_text($section)); - } + protected function assert_text(string $text, string $section=null) + { + $this->assertContains($text, $this->page_to_text($section)); + } - protected function assert_no_text(string $text, string $section=null) { - $this->assertNotContains($text, $this->page_to_text($section)); - } + protected function assert_no_text(string $text, string $section=null) + { + $this->assertNotContains($text, $this->page_to_text($section)); + } - protected function assert_content(string $content) { - global $page; - $this->assertContains($content, $page->data); - } + protected function assert_content(string $content) + { + global $page; + $this->assertContains($content, $page->data); + } - protected function assert_no_content(string $content) { - global $page; - $this->assertNotContains($content, $page->data); - } + protected function assert_no_content(string $content) + { + global $page; + $this->assertNotContains($content, $page->data); + } - // user things - protected function log_in_as_admin() { - global $user; - $user = User::by_name('demo'); - $this->assertNotNull($user); - } + // user things + protected function log_in_as_admin() + { + global $user; + $user = User::by_name('demo'); + $this->assertNotNull($user); + } - protected function log_in_as_user() { - global $user; - $user = User::by_name('test'); - $this->assertNotNull($user); - } + protected function log_in_as_user() + { + global $user; + $user = User::by_name('test'); + $this->assertNotNull($user); + } - protected function log_out() { - global $user, $config; - $user = User::by_id($config->get_int("anon_id", 0)); - $this->assertNotNull($user); - } + protected function log_out() + { + global $user, $config; + $user = User::by_id($config->get_int("anon_id", 0)); + $this->assertNotNull($user); + } - // post things - protected function post_image(string $filename, string $tags): int { - $dae = new DataUploadEvent($filename, array( - "filename" => $filename, - "extension" => pathinfo($filename, PATHINFO_EXTENSION), - "tags" => Tag::explode($tags), - "source" => null, - )); - send_event($dae); - $this->images[] = $dae->image_id; - return $dae->image_id; - } + // post things + protected function post_image(string $filename, string $tags): int + { + $dae = new DataUploadEvent($filename, [ + "filename" => $filename, + "extension" => pathinfo($filename, PATHINFO_EXTENSION), + "tags" => Tag::explode($tags), + "source" => null, + ]); + send_event($dae); + $this->images[] = $dae->image_id; + return $dae->image_id; + } - protected function delete_image(int $image_id) { - $img = Image::by_id($image_id); - if($img) { - $ide = new ImageDeletionEvent($img); - send_event($ide); - } - } + protected function delete_image(int $image_id) + { + $img = Image::by_id($image_id); + if ($img) { + $ide = new ImageDeletionEvent($img); + send_event($ide); + } + } } diff --git a/tests/router.php b/tests/router.php index a2255eaa..dc35c942 100644 --- a/tests/router.php +++ b/tests/router.php @@ -1,19 +1,21 @@ disable_left(); + $page->disable_left(); - // parts for the whole page - $prev = $page_number - 1; - $next = $page_number + 1; + // parts for the whole page + $prev = $page_number - 1; + $next = $page_number + 1; - $h_prev = ($page_number <= 1) ? "Prev" : - "Prev"; - $h_index = "Index"; - $h_next = ($page_number >= $total_pages) ? "Next" : - "Next"; + $h_prev = ($page_number <= 1) ? "Prev" : + "Prev"; + $h_index = "Index"; + $h_next = ($page_number >= $total_pages) ? "Next" : + "Next"; - $nav = "$h_prev | $h_index | $h_next"; + $nav = "$h_prev | $h_index | $h_next"; - $page->set_title("Comments"); - $page->set_heading("Comments"); - $page->add_block(new Block("Navigation", $nav, "left")); - $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); + $page->set_title("Comments"); + $page->set_heading("Comments"); + $page->add_block(new Block("Navigation", $nav, "left")); + $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); - // parts for each image - $position = 10; - - $comment_captcha = $config->get_bool('comment_captcha'); - $comment_limit = $config->get_int("comment_list_count", 10); - - foreach($images as $pair) { - $image = $pair[0]; - $comments = $pair[1]; + // parts for each image + $position = 10; + + $comment_captcha = $config->get_bool('comment_captcha'); + $comment_limit = $config->get_int("comment_list_count", 10); + + foreach ($images as $pair) { + $image = $pair[0]; + $comments = $pair[1]; - $thumb_html = $this->build_thumb_html($image); + $thumb_html = $this->build_thumb_html($image); - $s = "   "; - $un = $image->get_owner()->name; - $t = ""; - foreach($image->get_tag_array() as $tag) { - $u_tag = url_escape($tag); - $t .= "".html_escape($tag)." "; - } - $p = autodate($image->posted); + $s = "   "; + $un = $image->get_owner()->name; + $t = ""; + foreach ($image->get_tag_array() as $tag) { + $u_tag = url_escape($tag); + $t .= "".html_escape($tag)." "; + } + $p = autodate($image->posted); - $r = ext_is_live("Ratings") ? "Rating ".Ratings::rating_to_human($image->rating) : ""; - $comment_html = "Date $p $s User $un $s $r
    Tags $t

     "; + $r = ext_is_live("Ratings") ? "Rating ".Ratings::rating_to_human($image->rating) : ""; + $comment_html = "Date $p $s User $un $s $r
    Tags $t

     "; - $comment_count = count($comments); - if($comment_limit > 0 && $comment_count > $comment_limit) { - //$hidden = $comment_count - $comment_limit; - $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; - $comments = array_slice($comments, -$comment_limit); - } - foreach($comments as $comment) { - $comment_html .= $this->comment_to_html($comment); - } - if($can_post) { - if(!$user->is_anonymous()) { - $comment_html .= $this->build_postbox($image->id); - } - else { - if(!$comment_captcha) { - $comment_html .= $this->build_postbox($image->id); - } - else { - $comment_html .= "Add Comment"; - } - } - } + $comment_count = count($comments); + if ($comment_limit > 0 && $comment_count > $comment_limit) { + //$hidden = $comment_count - $comment_limit; + $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; + $comments = array_slice($comments, -$comment_limit); + } + foreach ($comments as $comment) { + $comment_html .= $this->comment_to_html($comment); + } + if ($can_post) { + if (!$user->is_anonymous()) { + $comment_html .= $this->build_postbox($image->id); + } else { + if (!$comment_captcha) { + $comment_html .= $this->build_postbox($image->id); + } else { + $comment_html .= "Add Comment"; + } + } + } - $html = " + $html = " @@ -78,49 +78,49 @@ class CustomCommentListTheme extends CommentListTheme { "; - $page->add_block(new Block(" ", $html, "main", $position++)); - } - } + $page->add_block(new Block(" ", $html, "main", $position++)); + } + } - public function display_recent_comments(array $comments) { - // no recent comments in this theme - } + public function display_recent_comments(array $comments) + { + // no recent comments in this theme + } - protected function comment_to_html(Comment $comment, bool $trim=false): string { - global $user; + protected function comment_to_html(Comment $comment, bool $trim=false): string + { + global $user; - $tfe = new TextFormattingEvent($comment->comment); - send_event($tfe); + $tfe = new TextFormattingEvent($comment->comment); + send_event($tfe); - //$i_uid = int_escape($comment->owner_id); - $h_name = html_escape($comment->owner_name); - //$h_poster_ip = html_escape($comment->poster_ip); - $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); - $i_comment_id = int_escape($comment->comment_id); - $i_image_id = int_escape($comment->image_id); - $h_posted = autodate($comment->posted); + //$i_uid = int_escape($comment->owner_id); + $h_name = html_escape($comment->owner_name); + //$h_poster_ip = html_escape($comment->poster_ip); + $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); + $i_comment_id = int_escape($comment->comment_id); + $i_image_id = int_escape($comment->image_id); + $h_posted = autodate($comment->posted); - $h_userlink = "$h_name"; - $h_del = ""; - if ($user->can("delete_comment")) { - $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); - $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); - $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); - $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); - $h_del = " - Del"; - } - //$h_imagelink = $trim ? ">>>\n" : ""; - if($trim) { - return "

    $h_userlink $h_del
    $h_posted
    $h_comment

    "; - } - else { - return " + $h_userlink = "$h_name"; + $h_del = ""; + if ($user->can("delete_comment")) { + $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); + $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); + $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); + $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); + $h_del = " - Del"; + } + //$h_imagelink = $trim ? ">>>\n" : ""; + if ($trim) { + return "

    $h_userlink $h_del
    $h_posted
    $h_comment

    "; + } else { + return "
    $thumb_html $comment_html
    $h_userlink
    $h_posted$h_del
    $h_comment
    "; - } - } + } + } } - diff --git a/themes/danbooru/custompage.class.php b/themes/danbooru/custompage.class.php index 4b36216c..f5641dc6 100644 --- a/themes/danbooru/custompage.class.php +++ b/themes/danbooru/custompage.class.php @@ -1,11 +1,12 @@ left_enabled = false; - } + public function disable_left() + { + $this->left_enabled = false; + } } - diff --git a/themes/danbooru/index.theme.php b/themes/danbooru/index.theme.php index 154b23d8..ffff72ac 100644 --- a/themes/danbooru/index.theme.php +++ b/themes/danbooru/index.theme.php @@ -1,48 +1,48 @@ search_terms) == 0) { - $query = null; - $page_title = $config->get_string('title'); - } - else { - $search_string = implode(' ', $this->search_terms); - $query = url_escape($search_string); - $page_title = html_escape($search_string); - } + if (count($this->search_terms) == 0) { + $query = null; + $page_title = $config->get_string('title'); + } else { + $search_string = implode(' ', $this->search_terms); + $query = url_escape($search_string); + $page_title = html_escape($search_string); + } - $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); - $page->set_title($page_title); - $page->set_heading($page_title); - $page->add_block(new Block("Search", $nav, "left", 0)); - if(count($images) > 0) { - if($query) { - $page->add_block(new Block("Images", $this->build_table($images, "search=$query"), "main", 10)); - $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); - } - else { - $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10)); - $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); - } - } - else { - $page->add_block(new Block("No Images Found", "No images were found to match the search criteria")); - } - } + $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); + $page->set_title($page_title); + $page->set_heading($page_title); + $page->add_block(new Block("Search", $nav, "left", 0)); + if (count($images) > 0) { + if ($query) { + $page->add_block(new Block("Images", $this->build_table($images, "search=$query"), "main", 10)); + $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); + } else { + $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10)); + $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); + } + } else { + $page->add_block(new Block("No Images Found", "No images were found to match the search criteria")); + } + } - /** - * #param string[] $search_terms - */ - protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string { - $h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms)); - $h_search_link = make_link(); - $h_search = " + /** + * #param string[] $search_terms + */ + protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string + { + $h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms)); + $h_search_link = make_link(); + $h_search = "

    @@ -50,17 +50,17 @@ class CustomIndexTheme extends IndexTheme {
    "; - return $h_search; - } + return $h_search; + } - protected function build_table(array $images, string $query): string { - $h_query = html_escape($query); - $table = "
    "; - foreach($images as $image) { - $table .= "\t" . $this->build_thumb_html($image) . "\n"; - } - $table .= "
    "; - return $table; - } + protected function build_table(array $images, string $query): string + { + $h_query = html_escape($query); + $table = "
    "; + foreach ($images as $image) { + $table .= "\t" . $this->build_thumb_html($image) . "\n"; + } + $table .= "
    "; + return $table; + } } - diff --git a/themes/danbooru/layout.class.php b/themes/danbooru/layout.class.php index 048d3de8..6076a30f 100644 --- a/themes/danbooru/layout.class.php +++ b/themes/danbooru/layout.class.php @@ -26,12 +26,12 @@ Changes in this theme include - $site_name and $front_name retreival from config added. - $custom_link and $title_link preparation just before html is outputed. - Altered outputed html to include the custom links and removed heading - from being displayed (subheading is still displayed) + from being displayed (subheading is still displayed) - Note that only the sidebar has been left aligned. Could not properly left align the main block because blocks without headers currently do not have ids on there div elements. (this was a problem because paginator block must be centered and everything else left aligned) - + Tips - You can change custom links to point to whatever pages you want as well as adding more custom links. @@ -42,154 +42,164 @@ Tips * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -class Layout { - public function display_page(Page $page) { - global $config, $user; +class Layout +{ + public function display_page(Page $page) + { + global $config, $user; - $theme_name = $config->get_string('theme'); - //$base_href = $config->get_string('base_href'); - $data_href = get_base_href(); - $contact_link = contact_link(); - $header_html = $page->get_all_html_headers(); + $theme_name = $config->get_string('theme'); + //$base_href = $config->get_string('base_href'); + $data_href = get_base_href(); + $contact_link = contact_link(); + $header_html = $page->get_all_html_headers(); - $left_block_html = ""; - $user_block_html = ""; - $main_block_html = ""; - $sub_block_html = ""; + $left_block_html = ""; + $user_block_html = ""; + $main_block_html = ""; + $sub_block_html = ""; - foreach($page->blocks as $block) { - switch($block->section) { - case "left": - $left_block_html .= $block->get_html(true); - break; - case "user": - $user_block_html .= $block->body; // $this->block_to_html($block, true); - break; - case "subheading": - $sub_block_html .= $block->body; // $this->block_to_html($block, true); - break; - case "main": - if($block->header == "Images") { - $block->header = " "; - } - $main_block_html .= $block->get_html(false); - break; - default: - print "

    error: {$block->header} using an unknown section ({$block->section})"; - break; - } - } + foreach ($page->blocks as $block) { + switch ($block->section) { + case "left": + $left_block_html .= $block->get_html(true); + break; + case "user": + $user_block_html .= $block->body; // $this->block_to_html($block, true); + break; + case "subheading": + $sub_block_html .= $block->body; // $this->block_to_html($block, true); + break; + case "main": + if ($block->header == "Images") { + $block->header = " "; + } + $main_block_html .= $block->get_html(false); + break; + default: + print "

    error: {$block->header} using an unknown section ({$block->section})"; + break; + } + } - $debug = get_debug_info(); + $debug = get_debug_info(); - $contact = empty($contact_link) ? "" : "
    Contact"; + $contact = empty($contact_link) ? "" : "
    Contact"; - if(empty($this->subheading)) { - $subheading = ""; - } - else { - $subheading = "

    {$this->subheading}
    "; - } + if (empty($this->subheading)) { + $subheading = ""; + } else { + $subheading = "
    {$this->subheading}
    "; + } - $site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page - $main_page = $config->get_string('main_page'); // bzchan: change from normal default to get main page for top of page + $site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page + $main_page = $config->get_string('main_page'); // bzchan: change from normal default to get main page for top of page - // bzchan: CUSTOM LINKS are prepared here, change these to whatever you like - $custom_links = ""; - if($user->is_anonymous()) { - $custom_links .= $this->navlinks(make_link('user_admin/login'), "My Account", array("user", "user_admin", "setup", "admin")); - } - else { - $custom_links .= $this->navlinks(make_link('user'), "My Account", array("user", "user_admin", "setup", "admin")); - } - $custom_links .= $this->navlinks(make_link('post/list'), "Posts", array("post")); - $custom_links .= $this->navlinks(make_link('comment/list'), "Comments", array("comment")); - $custom_links .= $this->navlinks(make_link('tags'), "Tags", array("tags")); - if(class_exists("Pools")) { - $custom_links .= $this->navlinks(make_link('pool/list'), "Pools", array("pool")); - } - $custom_links .= $this->navlinks(make_link('upload'), "Upload", array("upload")); - if(class_exists("Wiki")) { - $custom_links .= $this->navlinks(make_link('wiki'), "Wiki", array("wiki")); - $custom_links .= $this->navlinks(make_link('wiki/more'), "More »", array("wiki/more")); - } + // bzchan: CUSTOM LINKS are prepared here, change these to whatever you like + $custom_links = ""; + if ($user->is_anonymous()) { + $custom_links .= $this->navlinks(make_link('user_admin/login'), "My Account", ["user", "user_admin", "setup", "admin"]); + } else { + $custom_links .= $this->navlinks(make_link('user'), "My Account", ["user", "user_admin", "setup", "admin"]); + } + $custom_links .= $this->navlinks(make_link('post/list'), "Posts", ["post"]); + $custom_links .= $this->navlinks(make_link('comment/list'), "Comments", ["comment"]); + $custom_links .= $this->navlinks(make_link('tags'), "Tags", ["tags"]); + if (class_exists("Pools")) { + $custom_links .= $this->navlinks(make_link('pool/list'), "Pools", ["pool"]); + } + $custom_links .= $this->navlinks(make_link('upload'), "Upload", ["upload"]); + if (class_exists("Wiki")) { + $custom_links .= $this->navlinks(make_link('wiki'), "Wiki", ["wiki"]); + $custom_links .= $this->navlinks(make_link('wiki/more'), "More »", ["wiki/more"]); + } - $custom_sublinks = ""; - // hack - $username = url_escape($user->name); - // hack - $qp = explode("/", ltrim(_get_query(), "/")); - // php sucks - switch($qp[0]) { - default: - $custom_sublinks .= $user_block_html; - break; - case "": - # FIXME: this assumes that the front page is - # post/list; in 99% of case it will either be - # post/list or home, and in the latter case - # the subnav links aren't shown, but it would - # be nice to be correct - case "post": - case "upload": - if(class_exists("NumericScore")){ $custom_sublinks .= "
  • Popular by Day/Month/Year
  • ";} - $custom_sublinks .= "
  • All
  • "; - if(class_exists("Favorites")){ $custom_sublinks .= "
  • My Favorites
  • ";} - if(class_exists("RSS_Images")){ $custom_sublinks .= "
  • Feed
  • ";} - if(class_exists("RandomImage")){ $custom_sublinks .= "
  • Random Image
  • ";} - if(class_exists("Wiki")){ $custom_sublinks .= "
  • Help
  • "; - }else{ $custom_sublinks .= "
  • Help
  • ";} - break; - case "comment": - $custom_sublinks .= "
  • All
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "pool": - $custom_sublinks .= "
  • List
  • "; - $custom_sublinks .= "
  • Create
  • "; - $custom_sublinks .= "
  • Changes
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "wiki": - $custom_sublinks .= "
  • Index
  • "; - $custom_sublinks .= "
  • Rules
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "tags": - case "alias": - $custom_sublinks .= "
  • Map
  • "; - $custom_sublinks .= "
  • Alphabetic
  • "; - $custom_sublinks .= "
  • Popularity
  • "; - $custom_sublinks .= "
  • Categories
  • "; - $custom_sublinks .= "
  • Aliases
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - } + $custom_sublinks = ""; + // hack + $username = url_escape($user->name); + // hack + $qp = explode("/", ltrim(_get_query(), "/")); + // php sucks + switch ($qp[0]) { + default: + $custom_sublinks .= $user_block_html; + break; + case "": + # FIXME: this assumes that the front page is + # post/list; in 99% of case it will either be + # post/list or home, and in the latter case + # the subnav links aren't shown, but it would + # be nice to be correct + case "post": + case "upload": + if (class_exists("NumericScore")) { + $custom_sublinks .= "
  • Popular by Day/Month/Year
  • "; + } + $custom_sublinks .= "
  • All
  • "; + if (class_exists("Favorites")) { + $custom_sublinks .= "
  • My Favorites
  • "; + } + if (class_exists("RSS_Images")) { + $custom_sublinks .= "
  • Feed
  • "; + } + if (class_exists("RandomImage")) { + $custom_sublinks .= "
  • Random Image
  • "; + } + if (class_exists("Wiki")) { + $custom_sublinks .= "
  • Help
  • "; + } else { + $custom_sublinks .= "
  • Help
  • "; + } + break; + case "comment": + $custom_sublinks .= "
  • All
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "pool": + $custom_sublinks .= "
  • List
  • "; + $custom_sublinks .= "
  • Create
  • "; + $custom_sublinks .= "
  • Changes
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "wiki": + $custom_sublinks .= "
  • Index
  • "; + $custom_sublinks .= "
  • Rules
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "tags": + case "alias": + $custom_sublinks .= "
  • Map
  • "; + $custom_sublinks .= "
  • Alphabetic
  • "; + $custom_sublinks .= "
  • Popularity
  • "; + $custom_sublinks .= "
  • Categories
  • "; + $custom_sublinks .= "
  • Aliases
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + } - // bzchan: failed attempt to add heading after title_link (failure was it looked bad) - //if($this->heading==$site_name)$this->heading = ''; - //$title_link = "

    $site_name/$this->heading

    "; + // bzchan: failed attempt to add heading after title_link (failure was it looked bad) + //if($this->heading==$site_name)$this->heading = ''; + //$title_link = "

    $site_name/$this->heading

    "; - // bzchan: prepare main title link - $title_link = "

    $site_name

    "; + // bzchan: prepare main title link + $title_link = "

    $site_name

    "; - if($page->left_enabled) { - $left = ""; - $withleft = "withleft"; - } - else { - $left = ""; - $withleft = "noleft"; - } + if ($page->left_enabled) { + $left = ""; + $withleft = "withleft"; + } else { + $left = ""; + $withleft = "noleft"; + } - $flash = $page->get_cookie("flash_message"); - $flash_html = ""; - if($flash) { - $flash_html = "".nl2br(html_escape($flash))." [X]"; - } + $flash = $page->get_cookie("flash_message"); + $flash_html = ""; + if ($flash) { + $flash_html = "".nl2br(html_escape($flash))." [X]"; + } - print << @@ -231,34 +241,36 @@ $header_html EOD; - } - - /** - * #param string[] $pages_matched - */ - private function navlinks(string $link, string $desc, array $pages_matched): string { - /** - * Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.) - */ - $html = null; - $url = ltrim(_get_query(), "/"); + } + + /** + * #param string[] $pages_matched + */ + private function navlinks(string $link, string $desc, array $pages_matched): string + { + /** + * Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.) + */ + $html = null; + $url = ltrim(_get_query(), "/"); - $re1='.*?'; - $re2='((?:[a-z][a-z_]+))'; + $re1='.*?'; + $re2='((?:[a-z][a-z_]+))'; - if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) { - $url=$matches[1][0]; - } - - $count_pages_matched = count($pages_matched); - - for($i=0; $i < $count_pages_matched; $i++) { - if($url == $pages_matched[$i]) { - $html = "
  • $desc
  • "; - } - } - if(is_null($html)) {$html = "
  • $desc
  • ";} - return $html; - } + if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) { + $url=$matches[1][0]; + } + + $count_pages_matched = count($pages_matched); + + for ($i=0; $i < $count_pages_matched; $i++) { + if ($url == $pages_matched[$i]) { + $html = "
  • $desc
  • "; + } + } + if (is_null($html)) { + $html = "
  • $desc
  • "; + } + return $html; + } } - diff --git a/themes/danbooru/tag_list.theme.php b/themes/danbooru/tag_list.theme.php index 6628ca29..780c4d1f 100644 --- a/themes/danbooru/tag_list.theme.php +++ b/themes/danbooru/tag_list.theme.php @@ -1,9 +1,10 @@ disable_left(); - parent::display_page($page); - } +class CustomTagListTheme extends TagListTheme +{ + public function display_page(Page $page) + { + $page->disable_left(); + parent::display_page($page); + } } - diff --git a/themes/danbooru/themelet.class.php b/themes/danbooru/themelet.class.php index 54321c64..a00a75d4 100644 --- a/themes/danbooru/themelet.class.php +++ b/themes/danbooru/themelet.class.php @@ -1,51 +1,66 @@ build_paginator($page_number, $total_pages, $base, $query); - $page->add_block(new Block(null, $body, "main", 90)); - } +class Themelet extends BaseThemelet +{ + public function display_paginator(Page $page, string $base, ?string $query, int $page_number, int $total_pages, bool $show_random = false) + { + if ($total_pages == 0) { + $total_pages = 1; + } + $body = $this->build_paginator($page_number, $total_pages, $base, $query); + $page->add_block(new Block(null, $body, "main", 90)); + } - private function gen_page_link(string $base_url, string $query, string $page, string $name): string { - $link = make_link("$base_url/$page", $query); - return "$name"; - } + private function gen_page_link(string $base_url, string $query, string $page, string $name): string + { + $link = make_link("$base_url/$page", $query); + return "$name"; + } - private function gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string { - $paginator = ""; - if($page == $current_page) $paginator .= "$page"; - else $paginator .= $this->gen_page_link($base_url, $query, $page, $name); - return $paginator; - } + private function gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string + { + $paginator = ""; + if ($page == $current_page) { + $paginator .= "$page"; + } else { + $paginator .= $this->gen_page_link($base_url, $query, $page, $name); + } + return $paginator; + } - private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string { - $next = $current_page + 1; - $prev = $current_page - 1; + private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string + { + $next = $current_page + 1; + $prev = $current_page - 1; - $at_start = ($current_page <= 3 || $total_pages <= 3); - $at_end = ($current_page >= $total_pages -2); + $at_start = ($current_page <= 3 || $total_pages <= 3); + $at_end = ($current_page >= $total_pages -2); - $first_html = $at_start ? "" : $this->gen_page_link($base_url, $query, 1, "1"); - $prev_html = $at_start ? "" : $this->gen_page_link($base_url, $query, $prev, "<<"); - $next_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $next, ">>"); - $last_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $total_pages, "$total_pages"); + $first_html = $at_start ? "" : $this->gen_page_link($base_url, $query, 1, "1"); + $prev_html = $at_start ? "" : $this->gen_page_link($base_url, $query, $prev, "<<"); + $next_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $next, ">>"); + $last_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $total_pages, "$total_pages"); - $start = $current_page-2 > 1 ? $current_page-2 : 1; - $end = $current_page+2 <= $total_pages ? $current_page+2 : $total_pages; + $start = $current_page-2 > 1 ? $current_page-2 : 1; + $end = $current_page+2 <= $total_pages ? $current_page+2 : $total_pages; - $pages = array(); - foreach(range($start, $end) as $i) { - $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); - } - $pages_html = implode(" ", $pages); + $pages = []; + foreach (range($start, $end) as $i) { + $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); + } + $pages_html = implode(" ", $pages); - if(strlen($first_html) > 0) $pdots = "..."; - else $pdots = ""; + if (strlen($first_html) > 0) { + $pdots = "..."; + } else { + $pdots = ""; + } - if(strlen($last_html) > 0) $ndots = "..."; - else $ndots = ""; + if (strlen($last_html) > 0) { + $ndots = "..."; + } else { + $ndots = ""; + } - return "
    $prev_html $first_html $pdots $pages_html $ndots $last_html $next_html
    "; - } + return "
    $prev_html $first_html $pdots $pages_html $ndots $last_html $next_html
    "; + } } - diff --git a/themes/danbooru/upload.theme.php b/themes/danbooru/upload.theme.php index a7047cf3..818702cd 100644 --- a/themes/danbooru/upload.theme.php +++ b/themes/danbooru/upload.theme.php @@ -1,14 +1,16 @@ add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); - } +class CustomUploadTheme extends UploadTheme +{ + public function display_block(Page $page) + { + // this theme links to /upload + // $page->add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); + } - public function display_page(Page $page) { - $page->disable_left(); - parent::display_page($page); - } + public function display_page(Page $page) + { + $page->disable_left(); + parent::display_page($page); + } } - diff --git a/themes/danbooru/user.theme.php b/themes/danbooru/user.theme.php index d1fa8682..4ba40100 100644 --- a/themes/danbooru/user.theme.php +++ b/themes/danbooru/user.theme.php @@ -1,12 +1,14 @@ set_title("Login"); - $page->set_heading("Login"); - $page->disable_left(); - $html = " +class CustomUserPageTheme extends UserPageTheme +{ + public function display_login_page(Page $page) + { + global $config; + $page->set_title("Login"); + $page->set_heading("Login"); + $page->disable_left(); + $html = "
    @@ -21,43 +23,52 @@ class CustomUserPageTheme extends UserPageTheme {
    "; - if($config->get_bool("login_signup_enabled")) { - $html .= "Create Account"; - } - $page->add_block(new Block("Login", $html, "main", 90)); - } + if ($config->get_bool("login_signup_enabled")) { + $html .= "Create Account"; + } + $page->add_block(new Block("Login", $html, "main", 90)); + } - public function display_user_links(Page $page, User $user, $parts) { - // no block in this theme - } - public function display_login_block(Page $page) { - // no block in this theme - } + public function display_user_links(Page $page, User $user, $parts) + { + // no block in this theme + } + public function display_login_block(Page $page) + { + // no block in this theme + } - public function display_user_block(Page $page, User $user, $parts) { - $html = ""; - $blocked = array("Pools", "Pool Changes", "Alias Editor", "My Profile"); - foreach($parts as $part) { - if(in_array($part["name"], $blocked)) continue; - $html .= "
  • {$part["name"]}"; - } - $page->add_block(new Block("User Links", $html, "user", 90)); - } + public function display_user_block(Page $page, User $user, $parts) + { + $html = ""; + $blocked = ["Pools", "Pool Changes", "Alias Editor", "My Profile"]; + foreach ($parts as $part) { + if (in_array($part["name"], $blocked)) { + continue; + } + $html .= "
  • {$part["name"]}"; + } + $page->add_block(new Block("User Links", $html, "user", 90)); + } - public function display_signup_page(Page $page) { - global $config; - $tac = $config->get_string("login_tac", ""); + public function display_signup_page(Page $page) + { + global $config; + $tac = $config->get_string("login_tac", ""); - $tfe = new TextFormattingEvent($tac); - send_event($tfe); - $tac = $tfe->formatted; - - $reca = "".captcha_get_html().""; + $tfe = new TextFormattingEvent($tac); + send_event($tfe); + $tac = $tfe->formatted; + + $reca = "".captcha_get_html().""; - if(empty($tac)) {$html = "";} - else {$html = "

    $tac

    ";} + if (empty($tac)) { + $html = ""; + } else { + $html = "

    $tac

    "; + } - $html .= " + $html .= "
    @@ -70,32 +81,33 @@ class CustomUserPageTheme extends UserPageTheme { "; - $page->set_title("Create Account"); - $page->set_heading("Create Account"); - $page->disable_left(); - $page->add_block(new Block("Signup", $html)); - } + $page->set_title("Create Account"); + $page->set_heading("Create Account"); + $page->disable_left(); + $page->add_block(new Block("Signup", $html)); + } - public function display_ip_list(Page $page, array $uploads, array $comments) { - $html = "
    Name
    "; - $html .= ""; - $html .= "
    Uploaded from: "; - foreach($uploads as $ip => $count) { - $html .= "
    $ip ($count)"; - } - $html .= "
    Commented from:"; - foreach($comments as $ip => $count) { - $html .= "
    $ip ($count)"; - } - $html .= "
    (Most recent at top)
    "; + public function display_ip_list(Page $page, array $uploads, array $comments) + { + $html = ""; + $html .= ""; + $html .= "
    Uploaded from: "; + foreach ($uploads as $ip => $count) { + $html .= "
    $ip ($count)"; + } + $html .= "
    Commented from:"; + foreach ($comments as $ip => $count) { + $html .= "
    $ip ($count)"; + } + $html .= "
    (Most recent at top)
    "; - $page->add_block(new Block("IPs", $html)); - } + $page->add_block(new Block("IPs", $html)); + } - public function display_user_page(User $duser, $stats) { - global $page; - $page->disable_left(); - parent::display_user_page($duser, $stats); - } + public function display_user_page(User $duser, $stats) + { + global $page; + $page->disable_left(); + parent::display_user_page($duser, $stats); + } } - diff --git a/themes/danbooru/view.theme.php b/themes/danbooru/view.theme.php index d7b5aae6..62f67c3b 100644 --- a/themes/danbooru/view.theme.php +++ b/themes/danbooru/view.theme.php @@ -1,52 +1,54 @@ set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); - $page->set_heading(html_escape($image->get_tag_list())); - $page->add_block(new Block("Navigation", $this->build_navigation($image), "left", 0)); - $page->add_block(new Block("Statistics", $this->build_stats($image), "left", 15)); - $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 10)); - $page->add_block(new Block(null, $this->build_pin($image), "main", 11)); - } - - private function build_stats(Image $image) { - $h_owner = html_escape($image->get_owner()->name); - $h_ownerlink = "$h_owner"; - $h_ip = html_escape($image->owner_ip); - $h_date = autodate($image->posted); - $h_filesize = to_shorthand_int($image->filesize); +class CustomViewImageTheme extends ViewImageTheme +{ + public function display_page(Image $image, $editor_parts) + { + global $page; + $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); + $page->set_heading(html_escape($image->get_tag_list())); + $page->add_block(new Block("Navigation", $this->build_navigation($image), "left", 0)); + $page->add_block(new Block("Statistics", $this->build_stats($image), "left", 15)); + $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 10)); + $page->add_block(new Block(null, $this->build_pin($image), "main", 11)); + } + + private function build_stats(Image $image) + { + $h_owner = html_escape($image->get_owner()->name); + $h_ownerlink = "$h_owner"; + $h_ip = html_escape($image->owner_ip); + $h_date = autodate($image->posted); + $h_filesize = to_shorthand_int($image->filesize); - global $user; - if($user->can("view_ip")) { - $h_ownerlink .= " ($h_ip)"; - } + global $user; + if ($user->can("view_ip")) { + $h_ownerlink .= " ($h_ip)"; + } - $html = " + $html = " Id: {$image->id}
    Posted: $h_date by $h_ownerlink
    Size: {$image->width}x{$image->height}
    Filesize: $h_filesize "; - if(!is_null($image->source)) { - $h_source = html_escape($image->source); - if(substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") { - $h_source = "http://" . $h_source; - } - $html .= "
    Source: link"; - } + if (!is_null($image->source)) { + $h_source = html_escape($image->source); + if (substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") { + $h_source = "http://" . $h_source; + } + $html .= "
    Source: link"; + } - if(ext_is_live("Ratings")) { - if($image->rating == null || $image->rating == "u"){ - $image->rating = "u"; - } - $h_rating = Ratings::rating_to_human($image->rating); - $html .= "
    Rating: $h_rating"; - } + if (ext_is_live("Ratings")) { + if ($image->rating == null || $image->rating == "u") { + $image->rating = "u"; + } + $h_rating = Ratings::rating_to_human($image->rating); + $html .= "
    Rating: $h_rating"; + } - return $html; - } + return $html; + } } - diff --git a/themes/danbooru2/admin.theme.php b/themes/danbooru2/admin.theme.php index b46694de..ef4dbe00 100644 --- a/themes/danbooru2/admin.theme.php +++ b/themes/danbooru2/admin.theme.php @@ -1,11 +1,11 @@ disable_left(); - parent::display_page(); - } +class CustomAdminPageTheme extends AdminPageTheme +{ + public function display_page() + { + global $page; + $page->disable_left(); + parent::display_page(); + } } - - diff --git a/themes/danbooru2/comment.theme.php b/themes/danbooru2/comment.theme.php index a9fef1dd..c817fa09 100644 --- a/themes/danbooru2/comment.theme.php +++ b/themes/danbooru2/comment.theme.php @@ -1,76 +1,76 @@ disable_left(); + $page->disable_left(); - // parts for the whole page - $prev = $page_number - 1; - $next = $page_number + 1; + // parts for the whole page + $prev = $page_number - 1; + $next = $page_number + 1; - $h_prev = ($page_number <= 1) ? "Prev" : - "Prev"; - $h_index = "Index"; - $h_next = ($page_number >= $total_pages) ? "Next" : - "Next"; + $h_prev = ($page_number <= 1) ? "Prev" : + "Prev"; + $h_index = "Index"; + $h_next = ($page_number >= $total_pages) ? "Next" : + "Next"; - $nav = "$h_prev | $h_index | $h_next"; + $nav = "$h_prev | $h_index | $h_next"; - $page->set_title("Comments"); - $page->set_heading("Comments"); - $page->add_block(new Block("Navigation", $nav, "left")); - $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); + $page->set_title("Comments"); + $page->set_heading("Comments"); + $page->add_block(new Block("Navigation", $nav, "left")); + $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); - // parts for each image - $position = 10; - - $comment_captcha = $config->get_bool('comment_captcha'); - $comment_limit = $config->get_int("comment_list_count", 10); - - foreach($images as $pair) { - $image = $pair[0]; - $comments = $pair[1]; + // parts for each image + $position = 10; + + $comment_captcha = $config->get_bool('comment_captcha'); + $comment_limit = $config->get_int("comment_list_count", 10); + + foreach ($images as $pair) { + $image = $pair[0]; + $comments = $pair[1]; - $thumb_html = $this->build_thumb_html($image); + $thumb_html = $this->build_thumb_html($image); - $s = "   "; - $un = $image->get_owner()->name; - $t = ""; - foreach($image->get_tag_array() as $tag) { - $u_tag = url_escape($tag); - $t .= "".html_escape($tag)." "; - } - $p = autodate($image->posted); + $s = "   "; + $un = $image->get_owner()->name; + $t = ""; + foreach ($image->get_tag_array() as $tag) { + $u_tag = url_escape($tag); + $t .= "".html_escape($tag)." "; + } + $p = autodate($image->posted); - $r = ext_is_live("Ratings") ? "Rating ".Ratings::rating_to_human($image->rating) : ""; - $comment_html = "Date $p $s User $un $s $r
    Tags $t

     "; + $r = ext_is_live("Ratings") ? "Rating ".Ratings::rating_to_human($image->rating) : ""; + $comment_html = "Date $p $s User $un $s $r
    Tags $t

     "; - $comment_count = count($comments); - if($comment_limit > 0 && $comment_count > $comment_limit) { - //$hidden = $comment_count - $comment_limit; - $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; - $comments = array_slice($comments, -$comment_limit); - } - foreach($comments as $comment) { - $comment_html .= $this->comment_to_html($comment); - } - if($can_post) { - if(!$user->is_anonymous()) { - $comment_html .= $this->build_postbox($image->id); - } - else { - if(!$comment_captcha) { - $comment_html .= $this->build_postbox($image->id); - } - else { - $comment_html .= "Add Comment"; - } - } - } + $comment_count = count($comments); + if ($comment_limit > 0 && $comment_count > $comment_limit) { + //$hidden = $comment_count - $comment_limit; + $comment_html .= "

    showing $comment_limit of $comment_count comments

    "; + $comments = array_slice($comments, -$comment_limit); + } + foreach ($comments as $comment) { + $comment_html .= $this->comment_to_html($comment); + } + if ($can_post) { + if (!$user->is_anonymous()) { + $comment_html .= $this->build_postbox($image->id); + } else { + if (!$comment_captcha) { + $comment_html .= $this->build_postbox($image->id); + } else { + $comment_html .= "Add Comment"; + } + } + } - $html = " + $html = " @@ -78,50 +78,50 @@ class CustomCommentListTheme extends CommentListTheme { "; - $page->add_block(new Block(" ", $html, "main", $position++)); - } - } + $page->add_block(new Block(" ", $html, "main", $position++)); + } + } - public function display_recent_comments($comments) { - // no recent comments in this theme - } + public function display_recent_comments($comments) + { + // no recent comments in this theme + } - protected function comment_to_html(Comment $comment, $trim=false) { - global $user; + protected function comment_to_html(Comment $comment, $trim=false) + { + global $user; - $tfe = new TextFormattingEvent($comment->comment); - send_event($tfe); + $tfe = new TextFormattingEvent($comment->comment); + send_event($tfe); - //$i_uid = int_escape($comment->owner_id); - $h_name = html_escape($comment->owner_name); - //$h_poster_ip = html_escape($comment->poster_ip); - $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); - $i_comment_id = int_escape($comment->comment_id); - $i_image_id = int_escape($comment->image_id); - $h_posted = autodate($comment->posted); + //$i_uid = int_escape($comment->owner_id); + $h_name = html_escape($comment->owner_name); + //$h_poster_ip = html_escape($comment->poster_ip); + $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); + $i_comment_id = int_escape($comment->comment_id); + $i_image_id = int_escape($comment->image_id); + $h_posted = autodate($comment->posted); - $h_userlink = "$h_name"; - $h_del = ""; - if ($user->can("delete_comment")) { - $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); - $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); - $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); - $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); - $h_del = " - Del"; - } - //$h_imagelink = $trim ? ">>>\n" : ""; - if($trim) { - return "

    $h_userlink $h_del
    $h_posted
    $h_comment

    "; - } - else { - return " + $h_userlink = "$h_name"; + $h_del = ""; + if ($user->can("delete_comment")) { + $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); + $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); + $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); + $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); + $h_del = " - Del"; + } + //$h_imagelink = $trim ? ">>>\n" : ""; + if ($trim) { + return "

    $h_userlink $h_del
    $h_posted
    $h_comment

    "; + } else { + return "
    $thumb_html $comment_html
    $h_userlink
    $h_posted$h_del
    $h_comment
    "; - } - } + } + } } - diff --git a/themes/danbooru2/custompage.class.php b/themes/danbooru2/custompage.class.php index d8aca86c..1087bfd2 100644 --- a/themes/danbooru2/custompage.class.php +++ b/themes/danbooru2/custompage.class.php @@ -1,9 +1,10 @@ left_enabled = false; - } +class CustomPage extends Page +{ + public $left_enabled = true; + public function disable_left() + { + $this->left_enabled = false; + } } - diff --git a/themes/danbooru2/ext_manager.theme.php b/themes/danbooru2/ext_manager.theme.php index 23925a0c..247406c8 100644 --- a/themes/danbooru2/ext_manager.theme.php +++ b/themes/danbooru2/ext_manager.theme.php @@ -1,15 +1,16 @@ disable_left(); - parent::display_table($page, $extensions, $editable); - } +class CustomExtManagerTheme extends ExtManagerTheme +{ + public function display_table(Page $page, array $extensions, bool $editable) + { + $page->disable_left(); + parent::display_table($page, $extensions, $editable); + } - public function display_doc(Page $page, ExtensionInfo $info) { - $page->disable_left(); - parent::display_doc($page, $info); - } + public function display_doc(Page $page, ExtensionInfo $info) + { + $page->disable_left(); + parent::display_doc($page, $info); + } } - - diff --git a/themes/danbooru2/index.theme.php b/themes/danbooru2/index.theme.php index cc6b5596..e14202e9 100644 --- a/themes/danbooru2/index.theme.php +++ b/themes/danbooru2/index.theme.php @@ -1,48 +1,48 @@ search_terms) == 0) { - $query = null; - $page_title = $config->get_string('title'); - } - else { - $search_string = implode(' ', $this->search_terms); - $query = url_escape($search_string); - $page_title = html_escape($search_string); - } + if (count($this->search_terms) == 0) { + $query = null; + $page_title = $config->get_string('title'); + } else { + $search_string = implode(' ', $this->search_terms); + $query = url_escape($search_string); + $page_title = html_escape($search_string); + } - $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); - $page->set_title($page_title); - $page->set_heading($page_title); - $page->add_block(new Block("Search", $nav, "left", 0)); - if(count($images) > 0) { - if($query) { - $page->add_block(new Block("Images", $this->build_table($images, "search=$query"), "main", 10)); - $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); - } - else { - $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10)); - $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); - } - } - else { - $page->add_block(new Block("No Images Found", "No images were found to match the search criteria")); - } - } + $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); + $page->set_title($page_title); + $page->set_heading($page_title); + $page->add_block(new Block("Search", $nav, "left", 0)); + if (count($images) > 0) { + if ($query) { + $page->add_block(new Block("Images", $this->build_table($images, "search=$query"), "main", 10)); + $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); + } else { + $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10)); + $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); + } + } else { + $page->add_block(new Block("No Images Found", "No images were found to match the search criteria")); + } + } - /** - * #param string[] $search_terms - */ - protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string { - $h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms)); - $h_search_link = make_link(); - $h_search = " + /** + * #param string[] $search_terms + */ + protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string + { + $h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms)); + $h_search_link = make_link(); + $h_search = "

    @@ -50,20 +50,20 @@ class CustomIndexTheme extends IndexTheme {
    "; - return $h_search; - } + return $h_search; + } - /** - * #param Image[] $images - */ - protected function build_table(array $images, string $query): string { - $h_query = html_escape($query); - $table = "
    "; - foreach($images as $image) { - $table .= "\t" . $this->build_thumb_html($image) . "\n"; - } - $table .= "
    "; - return $table; - } + /** + * #param Image[] $images + */ + protected function build_table(array $images, string $query): string + { + $h_query = html_escape($query); + $table = "
    "; + foreach ($images as $image) { + $table .= "\t" . $this->build_thumb_html($image) . "\n"; + } + $table .= "
    "; + return $table; + } } - diff --git a/themes/danbooru2/layout.class.php b/themes/danbooru2/layout.class.php index 7c1fa3f6..b78d5f93 100644 --- a/themes/danbooru2/layout.class.php +++ b/themes/danbooru2/layout.class.php @@ -26,12 +26,12 @@ Changes in this theme include - $site_name and $front_name retreival from config added. - $custom_link and $title_link preparation just before html is outputed. - Altered outputed html to include the custom links and removed heading - from being displayed (subheading is still displayed) + from being displayed (subheading is still displayed) - Note that only the sidebar has been left aligned. Could not properly left align the main block because blocks without headers currently do not have ids on there div elements. (this was a problem because paginator block must be centered and everything else left aligned) - + Tips - You can change custom links to point to whatever pages you want as well as adding more custom links. @@ -42,180 +42,190 @@ Tips * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -class Layout { - public function display_page($page) { - global $config, $user; +class Layout +{ + public function display_page($page) + { + global $config, $user; - //$theme_name = $config->get_string('theme'); - //$base_href = $config->get_string('base_href'); - //$data_href = get_base_href(); - $contact_link = contact_link(); - $header_html = $page->get_all_html_headers(); + //$theme_name = $config->get_string('theme'); + //$base_href = $config->get_string('base_href'); + //$data_href = get_base_href(); + $contact_link = contact_link(); + $header_html = $page->get_all_html_headers(); - $left_block_html = ""; - $user_block_html = ""; - $main_block_html = ""; - $sub_block_html = ""; + $left_block_html = ""; + $user_block_html = ""; + $main_block_html = ""; + $sub_block_html = ""; - foreach($page->blocks as $block) { - switch($block->section) { - case "left": - $left_block_html .= $block->get_html(true); - break; - case "user": - $user_block_html .= $block->body; // $this->block_to_html($block, true); - break; - case "subheading": - $sub_block_html .= $block->body; // $this->block_to_html($block, true); - break; - case "main": - if($block->header == "Images") { - $block->header = " "; - } - $main_block_html .= $block->get_html(false); - break; - default: - print "

    error: {$block->header} using an unknown section ({$block->section})"; - break; - } - } + foreach ($page->blocks as $block) { + switch ($block->section) { + case "left": + $left_block_html .= $block->get_html(true); + break; + case "user": + $user_block_html .= $block->body; // $this->block_to_html($block, true); + break; + case "subheading": + $sub_block_html .= $block->body; // $this->block_to_html($block, true); + break; + case "main": + if ($block->header == "Images") { + $block->header = " "; + } + $main_block_html .= $block->get_html(false); + break; + default: + print "

    error: {$block->header} using an unknown section ({$block->section})"; + break; + } + } - $debug = get_debug_info(); + $debug = get_debug_info(); - $contact = empty($contact_link) ? "" : "
    Contact"; + $contact = empty($contact_link) ? "" : "
    Contact"; - if(empty($this->subheading)) { - $subheading = ""; - } - else { - $subheading = "

    {$this->subheading}
    "; - } + if (empty($this->subheading)) { + $subheading = ""; + } else { + $subheading = "
    {$this->subheading}
    "; + } - $site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page - $main_page = $config->get_string('main_page'); // bzchan: change from normal default to get main page for top of page + $site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page + $main_page = $config->get_string('main_page'); // bzchan: change from normal default to get main page for top of page - // bzchan: CUSTOM LINKS are prepared here, change these to whatever you like - $custom_links = ""; - if($user->is_anonymous()) { - $custom_links .= $this->navlinks(make_link('user_admin/login'), "Sign in", array("user", "user_admin", "setup", "admin")); - } - else { - $custom_links .= $this->navlinks(make_link('user'), "My Account", array("user", "user_admin")); - } - if($user->is_admin()) { - $custom_links .= $this->navlinks(make_link('admin'), "Admin", array("admin", "ext_manager", "setup")); - } - $custom_links .= $this->navlinks(make_link('post/list'), "Posts", array("post", "upload", "", "random_image")); - $custom_links .= $this->navlinks(make_link('comment/list'), "Comments", array("comment")); - $custom_links .= $this->navlinks(make_link('tags'), "Tags", array("tags", "alias")); - if(class_exists("Pools")) { - $custom_links .= $this->navlinks(make_link('pool/list'), "Pools", array("pool")); - } - if(class_exists("Wiki")) { - $custom_links .= $this->navlinks(make_link('wiki'), "Wiki", array("wiki")); - $custom_links .= $this->navlinks(make_link('wiki/more'), "More »", array("wiki/more")); - } + // bzchan: CUSTOM LINKS are prepared here, change these to whatever you like + $custom_links = ""; + if ($user->is_anonymous()) { + $custom_links .= $this->navlinks(make_link('user_admin/login'), "Sign in", ["user", "user_admin", "setup", "admin"]); + } else { + $custom_links .= $this->navlinks(make_link('user'), "My Account", ["user", "user_admin"]); + } + if ($user->is_admin()) { + $custom_links .= $this->navlinks(make_link('admin'), "Admin", ["admin", "ext_manager", "setup"]); + } + $custom_links .= $this->navlinks(make_link('post/list'), "Posts", ["post", "upload", "", "random_image"]); + $custom_links .= $this->navlinks(make_link('comment/list'), "Comments", ["comment"]); + $custom_links .= $this->navlinks(make_link('tags'), "Tags", ["tags", "alias"]); + if (class_exists("Pools")) { + $custom_links .= $this->navlinks(make_link('pool/list'), "Pools", ["pool"]); + } + if (class_exists("Wiki")) { + $custom_links .= $this->navlinks(make_link('wiki'), "Wiki", ["wiki"]); + $custom_links .= $this->navlinks(make_link('wiki/more'), "More »", ["wiki/more"]); + } - $custom_sublinks = ""; - // hack - $username = url_escape($user->name); - // hack - $qp = explode("/", ltrim(_get_query(), "/")); - // php sucks - switch($qp[0]) { - default: - case "ext_doc": - $custom_sublinks .= $user_block_html; - break; - case "user": - case "user_admin": - if($user->is_anonymous()) { - $custom_sublinks .= "
  • Sign up
  • "; - // $custom_sublinks .= "
  • Reset Password
  • "; - // $custom_sublinks .= "
  • Login Reminder
  • "; - } else { - $custom_sublinks .= "
  • Sign out
  • "; - } - break; - case "": - # FIXME: this assumes that the front page is - # post/list; in 99% of case it will either be - # post/list or home, and in the latter case - # the subnav links aren't shown, but it would - # be nice to be correct - case "random_image": - case "post": - case "upload": - if(class_exists("NumericScore")){ $custom_sublinks .= "
  • Popular by Day/Month/Year
  • ";} - $custom_sublinks .= "
  • Listing
  • "; - if(class_exists("Favorites")){ $custom_sublinks .= "
  • My Favorites
  • ";} - if(class_exists("RSS_Images")){ $custom_sublinks .= "
  • Feed
  • ";} - if(class_exists("RandomImage")){ $custom_sublinks .= "
  • Random
  • ";} - $custom_sublinks .= "
  • Upload
  • "; - if(class_exists("Wiki")){ $custom_sublinks .= "
  • Help
  • "; - }else{ $custom_sublinks .= "
  • Help
  • ";} - break; - case "comment": - $custom_sublinks .= "
  • All
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "pool": - $custom_sublinks .= "
  • List
  • "; - $custom_sublinks .= "
  • Create
  • "; - $custom_sublinks .= "
  • Changes
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "wiki": - $custom_sublinks .= "
  • Index
  • "; - $custom_sublinks .= "
  • Rules
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "tags": - case "alias": - $custom_sublinks .= "
  • Map
  • "; - $custom_sublinks .= "
  • Alphabetic
  • "; - $custom_sublinks .= "
  • Popularity
  • "; - $custom_sublinks .= "
  • Categories
  • "; - $custom_sublinks .= "
  • Aliases
  • "; - $custom_sublinks .= "
  • Help
  • "; - break; - case "admin": - case "ext_manager": - case "setup": - if($user->is_admin()) { - $custom_sublinks .= "
  • Extension Manager
  • "; - $custom_sublinks .= "
  • Board Config
  • "; - $custom_sublinks .= "
  • Alias Editor
  • "; - } else { - $custom_sublinks .= "
  • I think you might be lost
  • "; - } - break; - } + $custom_sublinks = ""; + // hack + $username = url_escape($user->name); + // hack + $qp = explode("/", ltrim(_get_query(), "/")); + // php sucks + switch ($qp[0]) { + default: + case "ext_doc": + $custom_sublinks .= $user_block_html; + break; + case "user": + case "user_admin": + if ($user->is_anonymous()) { + $custom_sublinks .= "
  • Sign up
  • "; + // $custom_sublinks .= "
  • Reset Password
  • "; + // $custom_sublinks .= "
  • Login Reminder
  • "; + } else { + $custom_sublinks .= "
  • Sign out
  • "; + } + break; + case "": + # FIXME: this assumes that the front page is + # post/list; in 99% of case it will either be + # post/list or home, and in the latter case + # the subnav links aren't shown, but it would + # be nice to be correct + case "random_image": + case "post": + case "upload": + if (class_exists("NumericScore")) { + $custom_sublinks .= "
  • Popular by Day/Month/Year
  • "; + } + $custom_sublinks .= "
  • Listing
  • "; + if (class_exists("Favorites")) { + $custom_sublinks .= "
  • My Favorites
  • "; + } + if (class_exists("RSS_Images")) { + $custom_sublinks .= "
  • Feed
  • "; + } + if (class_exists("RandomImage")) { + $custom_sublinks .= "
  • Random
  • "; + } + $custom_sublinks .= "
  • Upload
  • "; + if (class_exists("Wiki")) { + $custom_sublinks .= "
  • Help
  • "; + } else { + $custom_sublinks .= "
  • Help
  • "; + } + break; + case "comment": + $custom_sublinks .= "
  • All
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "pool": + $custom_sublinks .= "
  • List
  • "; + $custom_sublinks .= "
  • Create
  • "; + $custom_sublinks .= "
  • Changes
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "wiki": + $custom_sublinks .= "
  • Index
  • "; + $custom_sublinks .= "
  • Rules
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "tags": + case "alias": + $custom_sublinks .= "
  • Map
  • "; + $custom_sublinks .= "
  • Alphabetic
  • "; + $custom_sublinks .= "
  • Popularity
  • "; + $custom_sublinks .= "
  • Categories
  • "; + $custom_sublinks .= "
  • Aliases
  • "; + $custom_sublinks .= "
  • Help
  • "; + break; + case "admin": + case "ext_manager": + case "setup": + if ($user->is_admin()) { + $custom_sublinks .= "
  • Extension Manager
  • "; + $custom_sublinks .= "
  • Board Config
  • "; + $custom_sublinks .= "
  • Alias Editor
  • "; + } else { + $custom_sublinks .= "
  • I think you might be lost
  • "; + } + break; + } - // bzchan: failed attempt to add heading after title_link (failure was it looked bad) - //if($this->heading==$site_name)$this->heading = ''; - //$title_link = "

    $site_name/$this->heading

    "; + // bzchan: failed attempt to add heading after title_link (failure was it looked bad) + //if($this->heading==$site_name)$this->heading = ''; + //$title_link = "

    $site_name/$this->heading

    "; - // bzchan: prepare main title link - $title_link = "

    $site_name

    "; + // bzchan: prepare main title link + $title_link = "

    $site_name

    "; - if($page->left_enabled) { - $left = ""; - $withleft = "withleft"; - } - else { - $left = ""; - $withleft = "noleft"; - } + if ($page->left_enabled) { + $left = ""; + $withleft = "withleft"; + } else { + $left = ""; + $withleft = "noleft"; + } - $flash = $page->get_cookie("flash_message"); - $flash_html = ""; - if($flash) { - $flash_html = "".nl2br(html_escape($flash))." [X]"; - } + $flash = $page->get_cookie("flash_message"); + $flash_html = ""; + if ($flash) { + $flash_html = "".nl2br(html_escape($flash))." [X]"; + } - print << @@ -257,28 +267,30 @@ $header_html EOD; - } + } - private function navlinks(string $link, string $desc, array $pages_matched): string { - $html = ""; - $url = _get_query(); + private function navlinks(string $link, string $desc, array $pages_matched): string + { + $html = ""; + $url = _get_query(); - $re1='.*?'; - $re2='((?:[a-z][a-z_]+))'; + $re1='.*?'; + $re2='((?:[a-z][a-z_]+))'; - if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) { - $url=$matches[1][0]; - } - - $count_pages_matched = count($pages_matched); - - for($i=0; $i < $count_pages_matched; $i++) { - if($url == $pages_matched[$i]) { - $html = "
  • $desc
  • "; - } - } - if(empty($html)) {$html = "
  • $desc
  • ";} - return $html; - } + if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) { + $url=$matches[1][0]; + } + + $count_pages_matched = count($pages_matched); + + for ($i=0; $i < $count_pages_matched; $i++) { + if ($url == $pages_matched[$i]) { + $html = "
  • $desc
  • "; + } + } + if (empty($html)) { + $html = "
  • $desc
  • "; + } + return $html; + } } - diff --git a/themes/danbooru2/tag_list.theme.php b/themes/danbooru2/tag_list.theme.php index 6628ca29..780c4d1f 100644 --- a/themes/danbooru2/tag_list.theme.php +++ b/themes/danbooru2/tag_list.theme.php @@ -1,9 +1,10 @@ disable_left(); - parent::display_page($page); - } +class CustomTagListTheme extends TagListTheme +{ + public function display_page(Page $page) + { + $page->disable_left(); + parent::display_page($page); + } } - diff --git a/themes/danbooru2/themelet.class.php b/themes/danbooru2/themelet.class.php index 54321c64..a00a75d4 100644 --- a/themes/danbooru2/themelet.class.php +++ b/themes/danbooru2/themelet.class.php @@ -1,51 +1,66 @@ build_paginator($page_number, $total_pages, $base, $query); - $page->add_block(new Block(null, $body, "main", 90)); - } +class Themelet extends BaseThemelet +{ + public function display_paginator(Page $page, string $base, ?string $query, int $page_number, int $total_pages, bool $show_random = false) + { + if ($total_pages == 0) { + $total_pages = 1; + } + $body = $this->build_paginator($page_number, $total_pages, $base, $query); + $page->add_block(new Block(null, $body, "main", 90)); + } - private function gen_page_link(string $base_url, string $query, string $page, string $name): string { - $link = make_link("$base_url/$page", $query); - return "$name"; - } + private function gen_page_link(string $base_url, string $query, string $page, string $name): string + { + $link = make_link("$base_url/$page", $query); + return "$name"; + } - private function gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string { - $paginator = ""; - if($page == $current_page) $paginator .= "$page"; - else $paginator .= $this->gen_page_link($base_url, $query, $page, $name); - return $paginator; - } + private function gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string + { + $paginator = ""; + if ($page == $current_page) { + $paginator .= "$page"; + } else { + $paginator .= $this->gen_page_link($base_url, $query, $page, $name); + } + return $paginator; + } - private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string { - $next = $current_page + 1; - $prev = $current_page - 1; + private function build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string + { + $next = $current_page + 1; + $prev = $current_page - 1; - $at_start = ($current_page <= 3 || $total_pages <= 3); - $at_end = ($current_page >= $total_pages -2); + $at_start = ($current_page <= 3 || $total_pages <= 3); + $at_end = ($current_page >= $total_pages -2); - $first_html = $at_start ? "" : $this->gen_page_link($base_url, $query, 1, "1"); - $prev_html = $at_start ? "" : $this->gen_page_link($base_url, $query, $prev, "<<"); - $next_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $next, ">>"); - $last_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $total_pages, "$total_pages"); + $first_html = $at_start ? "" : $this->gen_page_link($base_url, $query, 1, "1"); + $prev_html = $at_start ? "" : $this->gen_page_link($base_url, $query, $prev, "<<"); + $next_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $next, ">>"); + $last_html = $at_end ? "" : $this->gen_page_link($base_url, $query, $total_pages, "$total_pages"); - $start = $current_page-2 > 1 ? $current_page-2 : 1; - $end = $current_page+2 <= $total_pages ? $current_page+2 : $total_pages; + $start = $current_page-2 > 1 ? $current_page-2 : 1; + $end = $current_page+2 <= $total_pages ? $current_page+2 : $total_pages; - $pages = array(); - foreach(range($start, $end) as $i) { - $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); - } - $pages_html = implode(" ", $pages); + $pages = []; + foreach (range($start, $end) as $i) { + $pages[] = $this->gen_page_link_block($base_url, $query, $i, $current_page, $i); + } + $pages_html = implode(" ", $pages); - if(strlen($first_html) > 0) $pdots = "..."; - else $pdots = ""; + if (strlen($first_html) > 0) { + $pdots = "..."; + } else { + $pdots = ""; + } - if(strlen($last_html) > 0) $ndots = "..."; - else $ndots = ""; + if (strlen($last_html) > 0) { + $ndots = "..."; + } else { + $ndots = ""; + } - return "
    $prev_html $first_html $pdots $pages_html $ndots $last_html $next_html
    "; - } + return "
    $prev_html $first_html $pdots $pages_html $ndots $last_html $next_html
    "; + } } - diff --git a/themes/danbooru2/upload.theme.php b/themes/danbooru2/upload.theme.php index a7047cf3..818702cd 100644 --- a/themes/danbooru2/upload.theme.php +++ b/themes/danbooru2/upload.theme.php @@ -1,14 +1,16 @@ add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); - } +class CustomUploadTheme extends UploadTheme +{ + public function display_block(Page $page) + { + // this theme links to /upload + // $page->add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); + } - public function display_page(Page $page) { - $page->disable_left(); - parent::display_page($page); - } + public function display_page(Page $page) + { + $page->disable_left(); + parent::display_page($page); + } } - diff --git a/themes/danbooru2/user.theme.php b/themes/danbooru2/user.theme.php index d1fa8682..4ba40100 100644 --- a/themes/danbooru2/user.theme.php +++ b/themes/danbooru2/user.theme.php @@ -1,12 +1,14 @@ set_title("Login"); - $page->set_heading("Login"); - $page->disable_left(); - $html = " +class CustomUserPageTheme extends UserPageTheme +{ + public function display_login_page(Page $page) + { + global $config; + $page->set_title("Login"); + $page->set_heading("Login"); + $page->disable_left(); + $html = "
    @@ -21,43 +23,52 @@ class CustomUserPageTheme extends UserPageTheme {
    "; - if($config->get_bool("login_signup_enabled")) { - $html .= "Create Account"; - } - $page->add_block(new Block("Login", $html, "main", 90)); - } + if ($config->get_bool("login_signup_enabled")) { + $html .= "Create Account"; + } + $page->add_block(new Block("Login", $html, "main", 90)); + } - public function display_user_links(Page $page, User $user, $parts) { - // no block in this theme - } - public function display_login_block(Page $page) { - // no block in this theme - } + public function display_user_links(Page $page, User $user, $parts) + { + // no block in this theme + } + public function display_login_block(Page $page) + { + // no block in this theme + } - public function display_user_block(Page $page, User $user, $parts) { - $html = ""; - $blocked = array("Pools", "Pool Changes", "Alias Editor", "My Profile"); - foreach($parts as $part) { - if(in_array($part["name"], $blocked)) continue; - $html .= "
  • {$part["name"]}"; - } - $page->add_block(new Block("User Links", $html, "user", 90)); - } + public function display_user_block(Page $page, User $user, $parts) + { + $html = ""; + $blocked = ["Pools", "Pool Changes", "Alias Editor", "My Profile"]; + foreach ($parts as $part) { + if (in_array($part["name"], $blocked)) { + continue; + } + $html .= "
  • {$part["name"]}"; + } + $page->add_block(new Block("User Links", $html, "user", 90)); + } - public function display_signup_page(Page $page) { - global $config; - $tac = $config->get_string("login_tac", ""); + public function display_signup_page(Page $page) + { + global $config; + $tac = $config->get_string("login_tac", ""); - $tfe = new TextFormattingEvent($tac); - send_event($tfe); - $tac = $tfe->formatted; - - $reca = "".captcha_get_html().""; + $tfe = new TextFormattingEvent($tac); + send_event($tfe); + $tac = $tfe->formatted; + + $reca = "".captcha_get_html().""; - if(empty($tac)) {$html = "";} - else {$html = "

    $tac

    ";} + if (empty($tac)) { + $html = ""; + } else { + $html = "

    $tac

    "; + } - $html .= " + $html .= "
    @@ -70,32 +81,33 @@ class CustomUserPageTheme extends UserPageTheme { "; - $page->set_title("Create Account"); - $page->set_heading("Create Account"); - $page->disable_left(); - $page->add_block(new Block("Signup", $html)); - } + $page->set_title("Create Account"); + $page->set_heading("Create Account"); + $page->disable_left(); + $page->add_block(new Block("Signup", $html)); + } - public function display_ip_list(Page $page, array $uploads, array $comments) { - $html = "
    Name
    "; - $html .= ""; - $html .= "
    Uploaded from: "; - foreach($uploads as $ip => $count) { - $html .= "
    $ip ($count)"; - } - $html .= "
    Commented from:"; - foreach($comments as $ip => $count) { - $html .= "
    $ip ($count)"; - } - $html .= "
    (Most recent at top)
    "; + public function display_ip_list(Page $page, array $uploads, array $comments) + { + $html = ""; + $html .= ""; + $html .= "
    Uploaded from: "; + foreach ($uploads as $ip => $count) { + $html .= "
    $ip ($count)"; + } + $html .= "
    Commented from:"; + foreach ($comments as $ip => $count) { + $html .= "
    $ip ($count)"; + } + $html .= "
    (Most recent at top)
    "; - $page->add_block(new Block("IPs", $html)); - } + $page->add_block(new Block("IPs", $html)); + } - public function display_user_page(User $duser, $stats) { - global $page; - $page->disable_left(); - parent::display_user_page($duser, $stats); - } + public function display_user_page(User $duser, $stats) + { + global $page; + $page->disable_left(); + parent::display_user_page($duser, $stats); + } } - diff --git a/themes/danbooru2/view.theme.php b/themes/danbooru2/view.theme.php index cf78d354..589d054c 100644 --- a/themes/danbooru2/view.theme.php +++ b/themes/danbooru2/view.theme.php @@ -1,58 +1,62 @@ set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); - $page->set_heading(html_escape($image->get_tag_list())); - $page->add_block(new Block("Search", $this->build_navigation($image), "left", 0)); - $page->add_block(new Block("Information", $this->build_information($image), "left", 15)); - $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 15)); - } +class CustomViewImageTheme extends ViewImageTheme +{ + public function display_page(Image $image, $editor_parts) + { + global $page; + $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); + $page->set_heading(html_escape($image->get_tag_list())); + $page->add_block(new Block("Search", $this->build_navigation($image), "left", 0)); + $page->add_block(new Block("Information", $this->build_information($image), "left", 15)); + $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 15)); + } - private function build_information(Image $image): string { - $h_owner = html_escape($image->get_owner()->name); - $h_ownerlink = "$h_owner"; - $h_ip = html_escape($image->owner_ip); - $h_date = autodate($image->posted); - $h_filesize = to_shorthand_int($image->filesize); + private function build_information(Image $image): string + { + $h_owner = html_escape($image->get_owner()->name); + $h_ownerlink = "$h_owner"; + $h_ip = html_escape($image->owner_ip); + $h_date = autodate($image->posted); + $h_filesize = to_shorthand_int($image->filesize); - global $user; - if($user->can("view_ip")) { - $h_ownerlink .= " ($h_ip)"; - } + global $user; + if ($user->can("view_ip")) { + $h_ownerlink .= " ($h_ip)"; + } - $html = " + $html = " ID: {$image->id}
    Uploader: $h_ownerlink
    Date: $h_date
    Size: $h_filesize ({$image->width}x{$image->height}) "; - if(!is_null($image->source)) { - $h_source = html_escape($image->source); - if(substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") { - $h_source = "http://" . $h_source; - } - $html .= "
    Source: link"; - } + if (!is_null($image->source)) { + $h_source = html_escape($image->source); + if (substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") { + $h_source = "http://" . $h_source; + } + $html .= "
    Source: link"; + } - if(ext_is_live("Ratings")) { - if($image->rating == null || $image->rating == "u"){ - $image->rating = "u"; - } - if(ext_is_live("Ratings")) { - $h_rating = Ratings::rating_to_human($image->rating); - $html .= "
    Rating: $h_rating"; - } - } + if (ext_is_live("Ratings")) { + if ($image->rating == null || $image->rating == "u") { + $image->rating = "u"; + } + if (ext_is_live("Ratings")) { + $h_rating = Ratings::rating_to_human($image->rating); + $html .= "
    Rating: $h_rating"; + } + } - return $html; - } + return $html; + } - protected function build_navigation(Image $image): string { - //$h_pin = $this->build_pin($image); - $h_search = " + protected function build_navigation(Image $image): string + { + //$h_pin = $this->build_pin($image); + $h_search = "
    @@ -61,7 +65,6 @@ class CustomViewImageTheme extends ViewImageTheme {
    "; - return "$h_search"; - } + return "$h_search"; + } } - diff --git a/themes/default/layout.class.php b/themes/default/layout.class.php index 07526475..b2784592 100644 --- a/themes/default/layout.class.php +++ b/themes/default/layout.class.php @@ -2,55 +2,57 @@ /** * A class to turn a Page data structure into a blob of HTML */ -class Layout { - /** - * turns the Page into HTML - */ - public function display_page(Page $page) { - global $config; +class Layout +{ + /** + * turns the Page into HTML + */ + public function display_page(Page $page) + { + global $config; - //$theme_name = $config->get_string('theme', 'default'); - //$data_href = get_base_href(); - $contact_link = contact_link(); - $header_html = $page->get_all_html_headers(); + //$theme_name = $config->get_string('theme', 'default'); + //$data_href = get_base_href(); + $contact_link = contact_link(); + $header_html = $page->get_all_html_headers(); - $left_block_html = ""; - $main_block_html = ""; - $sub_block_html = ""; + $left_block_html = ""; + $main_block_html = ""; + $sub_block_html = ""; - foreach($page->blocks as $block) { - switch($block->section) { - case "left": - $left_block_html .= $block->get_html(true); - break; - case "main": - $main_block_html .= $block->get_html(false); - break; - case "subheading": - $sub_block_html .= $block->get_html(false); - break; - default: - print "

    error: {$block->header} using an unknown section ({$block->section})"; - break; - } - } + foreach ($page->blocks as $block) { + switch ($block->section) { + case "left": + $left_block_html .= $block->get_html(true); + break; + case "main": + $main_block_html .= $block->get_html(false); + break; + case "subheading": + $sub_block_html .= $block->get_html(false); + break; + default: + print "

    error: {$block->header} using an unknown section ({$block->section})"; + break; + } + } - $debug = get_debug_info(); + $debug = get_debug_info(); - $contact = empty($contact_link) ? "" : "
    Contact"; + $contact = empty($contact_link) ? "" : "
    Contact"; - $wrapper = ""; - if(strlen($page->heading) > 100) { - $wrapper = ' style="height: 3em; overflow: auto;"'; - } + $wrapper = ""; + if (strlen($page->heading) > 100) { + $wrapper = ' style="height: 3em; overflow: auto;"'; + } - $flash = $page->get_cookie("flash_message"); - $flash_html = ""; - if($flash) { - $flash_html = "".nl2br(html_escape($flash))." [X]"; - } + $flash = $page->get_cookie("flash_message"); + $flash_html = ""; + if ($flash) { + $flash_html = "".nl2br(html_escape($flash))." [X]"; + } - print << @@ -86,6 +88,5 @@ $header_html EOD; - } + } } - diff --git a/themes/default/themelet.class.php b/themes/default/themelet.class.php index 77c927c3..636defd6 100644 --- a/themes/default/themelet.class.php +++ b/themes/default/themelet.class.php @@ -1,3 +1,4 @@ get_string('title'); - $page->set_title($page_title); - $page->set_heading($page_title); - $page->disable_left(); - $page->add_block(new Block(null, $this->build_upload_box(), "main", 0)); - $page->add_block(new Block(null, "


    ", "main", 80)); - $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); + $page_title = $config->get_string('title'); + $page->set_title($page_title); + $page->set_heading($page_title); + $page->disable_left(); + $page->add_block(new Block(null, $this->build_upload_box(), "main", 0)); + $page->add_block(new Block(null, "
    ", "main", 80)); + $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); - // parts for each image - $position = 10; - foreach($images as $pair) { - $image = $pair[0]; - $comments = $pair[1]; + // parts for each image + $position = 10; + foreach ($images as $pair) { + $image = $pair[0]; + $comments = $pair[1]; - $h_filename = html_escape($image->filename); - $h_filesize = to_shorthand_int($image->filesize); - $w = $image->width; - $h = $image->height; + $h_filename = html_escape($image->filename); + $h_filesize = to_shorthand_int($image->filesize); + $w = $image->width; + $h = $image->height; - $comment_html = ""; - $comment_id = 0; - foreach($comments as $comment) { - $this->inner_id = $comment_id++; - $comment_html .= $this->comment_to_html($comment, false); - } + $comment_html = ""; + $comment_id = 0; + foreach ($comments as $comment) { + $this->inner_id = $comment_id++; + $comment_html .= $this->comment_to_html($comment, false); + } - $html = "

     


    "; - $html .= "File: id}")."\">$h_filename - ($h_filesize, {$w}x{$h}) - "; - $html .= html_escape($image->get_tag_list()); - $html .= "
    "; - $html .= "
    " . $this->build_thumb_html($image) . "
    "; - $html .= "
    $comment_html
    "; - $html .= "
    "; + $html = "

     


    "; + $html .= "File: id}")."\">$h_filename - ($h_filesize, {$w}x{$h}) - "; + $html .= html_escape($image->get_tag_list()); + $html .= "
    "; + $html .= "
    " . $this->build_thumb_html($image) . "
    "; + $html .= "
    $comment_html
    "; + $html .= "
    "; - $page->add_block(new Block(null, $html, "main", $position++)); - } - } - - public function display_recent_comments($comments) { - // sidebar fails in this theme - } + $page->add_block(new Block(null, $html, "main", $position++)); + } + } + + public function display_recent_comments($comments) + { + // sidebar fails in this theme + } - public function build_upload_box() { - return "[[ insert upload-and-comment extension here ]]"; - } + public function build_upload_box() + { + return "[[ insert upload-and-comment extension here ]]"; + } - protected function comment_to_html(Comment $comment, $trim=false) { - $inner_id = $this->inner_id; // because custom themes can't add params, because PHP - global $user; + protected function comment_to_html(Comment $comment, $trim=false) + { + $inner_id = $this->inner_id; // because custom themes can't add params, because PHP + global $user; - $tfe = new TextFormattingEvent($comment->comment); - send_event($tfe); + $tfe = new TextFormattingEvent($comment->comment); + send_event($tfe); - //$i_uid = int_escape($comment->owner_id); - $h_name = html_escape($comment->owner_name); - //$h_poster_ip = html_escape($comment->poster_ip); - $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); - $i_comment_id = int_escape($comment->comment_id); - $i_image_id = int_escape($comment->image_id); + //$i_uid = int_escape($comment->owner_id); + $h_name = html_escape($comment->owner_name); + //$h_poster_ip = html_escape($comment->poster_ip); + $h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted); + $i_comment_id = int_escape($comment->comment_id); + $i_image_id = int_escape($comment->image_id); - $h_userlink = "$h_name"; - $h_date = $comment->posted; - $h_del = ""; - if ($user->can("delete_comment")) { - $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); - $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); - $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); - $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); - $h_del = " - Del"; - } - $h_reply = "[Reply]"; + $h_userlink = "$h_name"; + $h_date = $comment->posted; + $h_del = ""; + if ($user->can("delete_comment")) { + $comment_preview = substr(html_unescape($tfe->stripped), 0, 50); + $j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview"); + $h_delete_script = html_escape("return confirm($j_delete_confirm_message);"); + $h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id"); + $h_del = " - Del"; + } + $h_reply = "[Reply]"; - if($inner_id == 0) { - return "
    $h_userlink$h_del $h_date No.$i_comment_id $h_reply

    $h_comment

    "; - } - else { - return "
    >>". - "
    $h_userlink$h_del $h_date No.$i_comment_id $h_reply

    $h_comment

    " . - "
    "; - } - } + if ($inner_id == 0) { + return "
    $h_userlink$h_del $h_date No.$i_comment_id $h_reply

    $h_comment

    "; + } else { + return "
    >>". + "
    $h_userlink$h_del $h_date No.$i_comment_id $h_reply

    $h_comment

    " . + "
    "; + } + } } - diff --git a/themes/futaba/custompage.class.php b/themes/futaba/custompage.class.php index d8aca86c..1087bfd2 100644 --- a/themes/futaba/custompage.class.php +++ b/themes/futaba/custompage.class.php @@ -1,9 +1,10 @@ left_enabled = false; - } +class CustomPage extends Page +{ + public $left_enabled = true; + public function disable_left() + { + $this->left_enabled = false; + } } - diff --git a/themes/futaba/layout.class.php b/themes/futaba/layout.class.php index 37a797bf..01b84712 100644 --- a/themes/futaba/layout.class.php +++ b/themes/futaba/layout.class.php @@ -1,62 +1,62 @@ get_string('theme', 'default'); - $data_href = get_base_href(); - $contact_link = contact_link(); - $header_html = $page->get_all_html_headers(); + $theme_name = $config->get_string('theme', 'default'); + $data_href = get_base_href(); + $contact_link = contact_link(); + $header_html = $page->get_all_html_headers(); - $left_block_html = ""; - $main_block_html = ""; - $sub_block_html = ""; + $left_block_html = ""; + $main_block_html = ""; + $sub_block_html = ""; - foreach($page->blocks as $block) { - switch($block->section) { - case "left": - $left_block_html .= $block->get_html(true); - break; - case "main": - $main_block_html .= $block->get_html(false); - break; - case "subheading": - $sub_block_html .= $block->body; // $this->block_to_html($block, true); - break; - default: - print "

    error: {$block->header} using an unknown section ({$block->section})"; - break; - } - } + foreach ($page->blocks as $block) { + switch ($block->section) { + case "left": + $left_block_html .= $block->get_html(true); + break; + case "main": + $main_block_html .= $block->get_html(false); + break; + case "subheading": + $sub_block_html .= $block->body; // $this->block_to_html($block, true); + break; + default: + print "

    error: {$block->header} using an unknown section ({$block->section})"; + break; + } + } - $debug = get_debug_info(); + $debug = get_debug_info(); - $contact = empty($contact_link) ? "" : "
    Contact"; + $contact = empty($contact_link) ? "" : "
    Contact"; - if(empty($page->subheading)) { - $subheading = ""; - } - else { - $subheading = "

    {$page->subheading}
    "; - } + if (empty($page->subheading)) { + $subheading = ""; + } else { + $subheading = "
    {$page->subheading}
    "; + } - if($page->left_enabled) { - $left = ""; - $withleft = "withleft"; - } - else { - $left = ""; - $withleft = ""; - } + if ($page->left_enabled) { + $left = ""; + $withleft = "withleft"; + } else { + $left = ""; + $withleft = ""; + } - $flash = $page->get_cookie("flash_message"); - $flash_html = ""; - if($flash) { - $flash_html = "".nl2br(html_escape($flash))." [X]"; - } + $flash = $page->get_cookie("flash_message"); + $flash_html = ""; + if ($flash) { + $flash_html = "".nl2br(html_escape($flash))." [X]"; + } - print << @@ -94,6 +94,5 @@ $header_html EOD; - } + } } - diff --git a/themes/futaba/themelet.class.php b/themes/futaba/themelet.class.php index 4f01fda0..2e4c7a28 100644 --- a/themes/futaba/themelet.class.php +++ b/themes/futaba/themelet.class.php @@ -1,57 +1,67 @@ futaba_build_paginator($page_number, $total_pages, $base, $query); - $page->add_block(new Block(null, $body, "main", 90)); - } + /** + * Add a generic paginator. + */ + public function display_paginator(Page $page, string $base, string $query, int $page_number, int $total_pages, bool $show_random = false) + { + if ($total_pages == 0) { + $total_pages = 1; + } + $body = $this->futaba_build_paginator($page_number, $total_pages, $base, $query); + $page->add_block(new Block(null, $body, "main", 90)); + } - /** - * Generate a single HTML link. - */ - public function futaba_gen_page_link(string $base_url, string $query, string $page, string $name): string { - $link = make_link("$base_url/$page", $query); - return "[{$name}]"; - } + /** + * Generate a single HTML link. + */ + public function futaba_gen_page_link(string $base_url, string $query, string $page, string $name): string + { + $link = make_link("$base_url/$page", $query); + return "[{$name}]"; + } - public function futaba_gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string { - $paginator = ""; - if($page == $current_page) $paginator .= ""; - $paginator .= $this->futaba_gen_page_link($base_url, $query, $page, $name); - if($page == $current_page) $paginator .= ""; - return $paginator; - } + public function futaba_gen_page_link_block(string $base_url, string $query, int $page, int $current_page, string $name): string + { + $paginator = ""; + if ($page == $current_page) { + $paginator .= ""; + } + $paginator .= $this->futaba_gen_page_link($base_url, $query, $page, $name); + if ($page == $current_page) { + $paginator .= ""; + } + return $paginator; + } - public function futaba_build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string { - $next = $current_page + 1; - $prev = $current_page - 1; - //$rand = mt_rand(1, $total_pages); + public function futaba_build_paginator(int $current_page, int $total_pages, string $base_url, string $query): string + { + $next = $current_page + 1; + $prev = $current_page - 1; + //$rand = mt_rand(1, $total_pages); - $at_start = ($current_page <= 1 || $total_pages <= 1); - $at_end = ($current_page >= $total_pages); + $at_start = ($current_page <= 1 || $total_pages <= 1); + $at_end = ($current_page >= $total_pages); - //$first_html = $at_start ? "First" : $this->futaba_gen_page_link($base_url, $query, 1, "First"); - $prev_html = $at_start ? "Prev" : $this->futaba_gen_page_link($base_url, $query, $prev, "Prev"); - //$random_html = $this->futaba_gen_page_link($base_url, $query, $rand, "Random"); - $next_html = $at_end ? "Next" : $this->futaba_gen_page_link($base_url, $query, $next, "Next"); - //$last_html = $at_end ? "Last" : $this->futaba_gen_page_link($base_url, $query, $total_pages, "Last"); + //$first_html = $at_start ? "First" : $this->futaba_gen_page_link($base_url, $query, 1, "First"); + $prev_html = $at_start ? "Prev" : $this->futaba_gen_page_link($base_url, $query, $prev, "Prev"); + //$random_html = $this->futaba_gen_page_link($base_url, $query, $rand, "Random"); + $next_html = $at_end ? "Next" : $this->futaba_gen_page_link($base_url, $query, $next, "Next"); + //$last_html = $at_end ? "Last" : $this->futaba_gen_page_link($base_url, $query, $total_pages, "Last"); - $start = $current_page-5 > 1 ? $current_page-5 : 1; - $end = $start+10 < $total_pages ? $start+10 : $total_pages; + $start = $current_page-5 > 1 ? $current_page-5 : 1; + $end = $start+10 < $total_pages ? $start+10 : $total_pages; - $pages = array(); - foreach(range($start, $end) as $i) { - $pages[] = $this->futaba_gen_page_link_block($base_url, $query, $i, $current_page, $i); - } - $pages_html = implode(" ", $pages); + $pages = []; + foreach (range($start, $end) as $i) { + $pages[] = $this->futaba_gen_page_link_block($base_url, $query, $i, $current_page, $i); + } + $pages_html = implode(" ", $pages); - //return "

    $first_html | $prev_html | $random_html | $next_html | $last_html". - // "
    << $pages_html >>

    "; - return "

    {$prev_html} {$pages_html} {$next_html}

    "; - } + //return "

    $first_html | $prev_html | $random_html | $next_html | $last_html". + // "
    << $pages_html >>

    "; + return "

    {$prev_html} {$pages_html} {$next_html}

    "; + } } - diff --git a/themes/futaba/view.theme.php b/themes/futaba/view.theme.php index 54b66e88..feb06743 100644 --- a/themes/futaba/view.theme.php +++ b/themes/futaba/view.theme.php @@ -1,11 +1,12 @@ set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); - $page->set_heading(html_escape($image->get_tag_list())); - $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 10)); - } +class CustomViewImageTheme extends ViewImageTheme +{ + public function display_page(Image $image, $editor_parts) + { + global $page; + $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); + $page->set_heading(html_escape($image->get_tag_list())); + $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 10)); + } } - diff --git a/themes/lite/comment.theme.php b/themes/lite/comment.theme.php index 4c478be2..91cb684d 100644 --- a/themes/lite/comment.theme.php +++ b/themes/lite/comment.theme.php @@ -1,11 +1,14 @@ rr(parent::comment_to_html($comment, $trim)); - } +class CustomCommentListTheme extends CommentListTheme +{ + protected function comment_to_html(Comment $comment, bool $trim=false): string + { + return $this->rr(parent::comment_to_html($comment, $trim)); + } - protected function build_postbox(int $image_id): string { - return $this->rr(parent::build_postbox($image_id)); - } + protected function build_postbox(int $image_id): string + { + return $this->rr(parent::build_postbox($image_id)); + } } diff --git a/themes/lite/custompage.class.php b/themes/lite/custompage.class.php index b5c3ea29..3787d56b 100644 --- a/themes/lite/custompage.class.php +++ b/themes/lite/custompage.class.php @@ -3,12 +3,13 @@ /** * Class CustomPage */ -class CustomPage extends Page { - /** @var bool */ - public $left_enabled = true; +class CustomPage extends Page +{ + /** @var bool */ + public $left_enabled = true; - public function disable_left() { - $this->left_enabled = false; - } + public function disable_left() + { + $this->left_enabled = false; + } } - diff --git a/themes/lite/layout.class.php b/themes/lite/layout.class.php index 40abc0a6..64de13d2 100644 --- a/themes/lite/layout.class.php +++ b/themes/lite/layout.class.php @@ -7,162 +7,175 @@ * Description: A mashup of Default, Danbooru, the interface on qwebirc, and * some other sites, packaged in a light blue color. */ -class Layout { - public function display_page(Page $page) { - global $config, $user; +class Layout +{ + public function display_page(Page $page) + { + global $config, $user; - $theme_name = $config->get_string('theme', 'lite'); - $site_name = $config->get_string('title'); - $data_href = get_base_href(); - $contact_link = contact_link(); - $header_html = $page->get_all_html_headers(); + $theme_name = $config->get_string('theme', 'lite'); + $site_name = $config->get_string('title'); + $data_href = get_base_href(); + $contact_link = contact_link(); + $header_html = $page->get_all_html_headers(); - $menu = ""; + + $left_block_html = ""; + $main_block_html = ""; + $sub_block_html = ""; + $user_block_html = ""; - foreach($page->blocks as $block) { - switch($block->section) { - case "left": - $left_block_html .= $this->block_to_html($block, true, "left"); - break; - case "main": - $main_block_html .= $this->block_to_html($block, false, "main"); - break; - case "user": - $user_block_html .= $block->body; - break; - case "subheading": - $sub_block_html .= $this->block_to_html($block, false, "main"); - break; - default: - print "

    error: {$block->header} using an unknown section ({$block->section})"; - break; - } - } + foreach ($page->blocks as $block) { + switch ($block->section) { + case "left": + $left_block_html .= $this->block_to_html($block, true, "left"); + break; + case "main": + $main_block_html .= $this->block_to_html($block, false, "main"); + break; + case "user": + $user_block_html .= $block->body; + break; + case "subheading": + $sub_block_html .= $this->block_to_html($block, false, "main"); + break; + default: + print "

    error: {$block->header} using an unknown section ({$block->section})"; + break; + } + } - $custom_sublinks = "

    "; - // hack - $username = url_escape($user->name); - // hack - $qp = explode("/", ltrim(_get_query(), "/")); - $cs = ""; + $custom_sublinks = "
    "; + // hack + $username = url_escape($user->name); + // hack + $qp = explode("/", ltrim(_get_query(), "/")); + $cs = ""; - // php sucks - switch($qp[0]) { - default: - $cs = $user_block_html; - break; - case "": - # FIXME: this assumes that the front page is - # post/list; in 99% of case it will either be - # post/list or home, and in the latter case - # the subnav links aren't shown, but it would - # be nice to be correct - case "post": - if(class_exists("NumericScore")){ - $cs .= "Popular by Day/Month/Year "; - } - $cs .= "All"; - if(class_exists("Favorites")){ $cs .= "My Favorites";} - if(class_exists("RSS_Images")){ $cs .= "Feed";} - if(class_exists("Random_Image")){ $cs .= "Random Image";} - if(class_exists("Wiki")){ $cs .= "Help"; - }else{ $cs .= "Help";} - break; - case "comment": - $cs .= "All"; - $cs .= "Feed"; - $cs .= "Help"; - break; - case "pool": - $cs .= "List"; - $cs .= "Create"; - $cs .= "Changes"; - $cs .= "Help"; - break; - case "wiki": - $cs .= "Index"; - $cs .= "Rules"; - $cs .= "Help"; - break; - case "tags": - case "alias": - $cs .= "Map"; - $cs .= "Alphabetic"; - $cs .= "Popularity"; - $cs .= "Categories"; - $cs .= "Aliases"; - $cs .= "Help"; - break; - case "upload": - if(class_exists("Wiki")) { $cs .= "Guidelines"; } - break; - case "random": - $cs .= "Shuffle"; - $cs .= "Download"; - break; - case "featured": - $cs .= "Download"; - break; - } + // php sucks + switch ($qp[0]) { + default: + $cs = $user_block_html; + break; + case "": + # FIXME: this assumes that the front page is + # post/list; in 99% of case it will either be + # post/list or home, and in the latter case + # the subnav links aren't shown, but it would + # be nice to be correct + case "post": + if (class_exists("NumericScore")) { + $cs .= "Popular by Day/Month/Year "; + } + $cs .= "All"; + if (class_exists("Favorites")) { + $cs .= "My Favorites"; + } + if (class_exists("RSS_Images")) { + $cs .= "Feed"; + } + if (class_exists("Random_Image")) { + $cs .= "Random Image"; + } + if (class_exists("Wiki")) { + $cs .= "Help"; + } else { + $cs .= "Help"; + } + break; + case "comment": + $cs .= "All"; + $cs .= "Feed"; + $cs .= "Help"; + break; + case "pool": + $cs .= "List"; + $cs .= "Create"; + $cs .= "Changes"; + $cs .= "Help"; + break; + case "wiki": + $cs .= "Index"; + $cs .= "Rules"; + $cs .= "Help"; + break; + case "tags": + case "alias": + $cs .= "Map"; + $cs .= "Alphabetic"; + $cs .= "Popularity"; + $cs .= "Categories"; + $cs .= "Aliases"; + $cs .= "Help"; + break; + case "upload": + if (class_exists("Wiki")) { + $cs .= "Guidelines"; + } + break; + case "random": + $cs .= "Shuffle"; + $cs .= "Download"; + break; + case "featured": + $cs .= "Download"; + break; + } - if($cs == "") { - $custom_sublinks = ""; - } else { - $custom_sublinks .= "$cs
    "; - } + if ($cs == "") { + $custom_sublinks = ""; + } else { + $custom_sublinks .= "$cs
    "; + } - $debug = get_debug_info(); + $debug = get_debug_info(); - $contact = empty($contact_link) ? "" : "
    Contact"; - //$subheading = empty($page->subheading) ? "" : "
    {$page->subheading}
    "; + $contact = empty($contact_link) ? "" : "
    Contact"; + //$subheading = empty($page->subheading) ? "" : "
    {$page->subheading}
    "; - /*$wrapper = ""; - if(strlen($page->heading) > 100) { - $wrapper = ' style="height: 3em; overflow: auto;"'; - }*/ - if($page->left_enabled == false) { - $left_block_html = ""; - $main_block_html = "
    {$main_block_html}
    "; - } else { - $left_block_html = ""; - $main_block_html = "
    {$main_block_html}
    "; - } + /*$wrapper = ""; + if(strlen($page->heading) > 100) { + $wrapper = ' style="height: 3em; overflow: auto;"'; + }*/ + if ($page->left_enabled == false) { + $left_block_html = ""; + $main_block_html = "
    {$main_block_html}
    "; + } else { + $left_block_html = ""; + $main_block_html = "
    {$main_block_html}
    "; + } - $flash = $page->get_cookie("flash_message"); - $flash_html = ""; - if(!empty($flash)) { - $flash_html = "".nl2br(html_escape($flash))." [X]"; - } + $flash = $page->get_cookie("flash_message"); + $flash_html = ""; + if (!empty($flash)) { + $flash_html = "".nl2br(html_escape($flash))." [X]"; + } - print << @@ -196,62 +209,64 @@ class Layout { EOD; - } /* end of function display_page() */ + } /* end of function display_page() */ - public function block_to_html(Block $block, bool $hidable=false, string $salt=""): string { - $h = $block->header; - $b = $block->body; - $i = str_replace(' ', '_', $h) . $salt; - $html = "
    "; - if(!is_null($h)) { - if($salt == "main") { - $html .= ""; - } else { - $html .= ""; - } - } - if(!is_null($b)) { - if($salt =="main") { - $html .= "
    {$b}
    "; - } - else { - $html .= " + public function block_to_html(Block $block, bool $hidable=false, string $salt=""): string + { + $h = $block->header; + $b = $block->body; + $i = str_replace(' ', '_', $h) . $salt; + $html = "
    "; + if (!is_null($h)) { + if ($salt == "main") { + $html .= ""; + } else { + $html .= ""; + } + } + if (!is_null($b)) { + if ($salt =="main") { + $html .= "
    {$b}
    "; + } else { + $html .= " "; - } - } - $html .= "
    "; - return $html; - } + } + } + $html .= "
    "; + return $html; + } - /** - * #param string[] $pages_matched - */ - public function navlinks(string $link, string $desc, array $pages_matched): ?string { - /** - * Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.) - */ - $html = null; - $url = ltrim(_get_query(), "/"); + /** + * #param string[] $pages_matched + */ + public function navlinks(string $link, string $desc, array $pages_matched): ?string + { + /** + * Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.) + */ + $html = null; + $url = ltrim(_get_query(), "/"); - $re1='.*?'; - $re2='((?:[a-z][a-z_]+))'; + $re1='.*?'; + $re2='((?:[a-z][a-z_]+))'; - if (preg_match_all ("/".$re1.$re2."/is", $url, $matches)) { - $url=$matches[1][0]; - } + if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) { + $url=$matches[1][0]; + } - $count_pages_matched = count($pages_matched); + $count_pages_matched = count($pages_matched); - for($i=0; $i < $count_pages_matched; $i++) { - if($url == $pages_matched[$i]) { - $html = "{$desc}"; - } - } + for ($i=0; $i < $count_pages_matched; $i++) { + if ($url == $pages_matched[$i]) { + $html = "{$desc}"; + } + } - if(is_null($html)) {$html = "{$desc}";} - - return $html; - } + if (is_null($html)) { + $html = "{$desc}"; + } + return $html; + } } /* end of class Layout */ diff --git a/themes/lite/setup.theme.php b/themes/lite/setup.theme.php index 42a1d210..11191d8e 100644 --- a/themes/lite/setup.theme.php +++ b/themes/lite/setup.theme.php @@ -6,12 +6,14 @@ * A customised version of the Setup theme. * */ -class CustomSetupTheme extends SetupTheme { - protected function sb_to_html(SetupBlock $block) { - $h = $block->header; - $b = $block->body; - $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; - $html = " +class CustomSetupTheme extends SetupTheme +{ + protected function sb_to_html(SetupBlock $block) + { + $h = $block->header; + $b = $block->body; + $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; + $html = "