<?php /* Question2Answer by Gideon Greenspan and contributors http://www.question2answer.org/ Description: Functions used in the admin center pages 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. More about this license: http://www.question2answer.org/license.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../../'); exit; } /** * Return true if user is logged in with admin privileges. If not, return false * and set up $qa_content with the appropriate title and error message * @param array $qa_content * @return bool */ function qa_admin_check_privileges(&$qa_content) { if (!qa_is_logged_in()) { require_once QA_INCLUDE_DIR . 'app/format.php'; $qa_content = qa_content_prepare(); $qa_content['title'] = qa_lang_html('admin/admin_title'); $qa_content['error'] = qa_insert_login_links(qa_lang_html('admin/not_logged_in'), qa_request()); return false; } elseif (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN) { $qa_content = qa_content_prepare(); $qa_content['title'] = qa_lang_html('admin/admin_title'); $qa_content['error'] = qa_lang_html('admin/no_privileges'); return false; } return true; } /** * Return a sorted array of available languages, [short code] => [long name] * @return array */ function qa_admin_language_options() { if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } /** * @deprecated The hardcoded language ids will be removed in favor of language metadata files. * See qa-lang/en-GB directory for a clear example of how to use them. */ $codetolanguage = array( // 2-letter language codes as per ISO 639-1 'ar' => 'Arabic - العربية', 'az' => 'Azerbaijani - Azərbaycanca', 'bg' => 'Bulgarian - Български', 'bn' => 'Bengali - বাংলা', 'ca' => 'Catalan - Català', 'cs' => 'Czech - Čeština', 'cy' => 'Welsh - Cymraeg', 'da' => 'Danish - Dansk', 'de' => 'German - Deutsch', 'el' => 'Greek - Ελληνικά', 'en-GB' => 'English (UK)', 'es' => 'Spanish - Español', 'et' => 'Estonian - Eesti', 'fa' => 'Persian - فارسی', 'fi' => 'Finnish - Suomi', 'fr' => 'French - Français', 'he' => 'Hebrew - עברית', 'hr' => 'Croatian - Hrvatski', 'hu' => 'Hungarian - Magyar', 'id' => 'Indonesian - Bahasa Indonesia', 'is' => 'Icelandic - Íslenska', 'it' => 'Italian - Italiano', 'ja' => 'Japanese - 日本語', 'ka' => 'Georgian - ქართული ენა', 'kh' => 'Khmer - ភាសាខ្មែរ', 'ko' => 'Korean - 한국어', 'ku-CKB' => 'Kurdish Central - کورد', 'lt' => 'Lithuanian - Lietuvių', 'lv' => 'Latvian - Latviešu', 'nl' => 'Dutch - Nederlands', 'no' => 'Norwegian - Norsk', 'pl' => 'Polish - Polski', 'pt' => 'Portuguese - Português', 'ro' => 'Romanian - Română', 'ru' => 'Russian - Русский', 'sk' => 'Slovak - Slovenčina', 'sl' => 'Slovenian - Slovenščina', 'sq' => 'Albanian - Shqip', 'sr' => 'Serbian - Српски', 'sv' => 'Swedish - Svenska', 'th' => 'Thai - ไทย', 'tr' => 'Turkish - Türkçe', 'ug' => 'Uyghur - ئۇيغۇرچە', 'uk' => 'Ukrainian - Українська', 'uz' => 'Uzbek - ўзбек', 'vi' => 'Vietnamese - Tiếng Việt', 'zh-TW' => 'Chinese Traditional - 繁體中文', 'zh' => 'Chinese Simplified - 简体中文', ); $options = array('' => 'English (US)'); // find all language folders $metadataUtil = new \Q2A\Util\Metadata(); foreach (glob(QA_LANG_DIR . '*', GLOB_ONLYDIR) as $directory) { $code = basename($directory); $metadata = $metadataUtil->fetchFromAddonPath($directory); if (isset($metadata['name'])) { $options[$code] = $metadata['name']; } elseif (isset($codetolanguage[$code])) { // otherwise use an entry from above $options[$code] = $codetolanguage[$code]; } } asort($options, SORT_STRING); return $options; } /** * Return a sorted array of available themes, [theme name] => [theme name] * @return array */ function qa_admin_theme_options() { if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } $metadataUtil = new \Q2A\Util\Metadata(); foreach (glob(QA_THEME_DIR . '*', GLOB_ONLYDIR) as $directory) { $theme = basename($directory); $metadata = $metadataUtil->fetchFromAddonPath($directory); if (empty($metadata)) { // limit theme parsing to first 8kB $contents = @file_get_contents($directory . '/qa-styles.css', false, null, 0, 8192); $metadata = qa_addon_metadata($contents, 'Theme'); } $options[$theme] = isset($metadata['name']) ? $metadata['name'] : $theme; } asort($options, SORT_STRING); return $options; } /** * Return an array of widget placement options, with keys matching the database value * @return array */ function qa_admin_place_options() { return array( 'FT' => qa_lang_html('options/place_full_top'), 'FH' => qa_lang_html('options/place_full_below_nav'), 'FL' => qa_lang_html('options/place_full_below_content'), 'FB' => qa_lang_html('options/place_full_below_footer'), 'MT' => qa_lang_html('options/place_main_top'), 'MH' => qa_lang_html('options/place_main_below_title'), 'ML' => qa_lang_html('options/place_main_below_lists'), 'MB' => qa_lang_html('options/place_main_bottom'), 'ST' => qa_lang_html('options/place_side_top'), 'SH' => qa_lang_html('options/place_side_below_sidebar'), 'SL' => qa_lang_html('options/place_side_low'), 'SB' => qa_lang_html('options/place_side_last'), ); } /** * Return an array of page size options up to $maximum, [page size] => [page size] * @param int $maximum * @return array */ function qa_admin_page_size_options($maximum) { $rawoptions = array(5, 10, 15, 20, 25, 30, 40, 50, 60, 80, 100, 120, 150, 200, 250, 300, 400, 500, 600, 800, 1000); $options = array(); foreach ($rawoptions as $rawoption) { if ($rawoption > $maximum) break; $options[$rawoption] = $rawoption; } return $options; } /** * Return an array of options representing matching precision, [value] => [label] * @return array */ function qa_admin_match_options() { return array( 5 => qa_lang_html('options/match_5'), 4 => qa_lang_html('options/match_4'), 3 => qa_lang_html('options/match_3'), 2 => qa_lang_html('options/match_2'), 1 => qa_lang_html('options/match_1'), ); } /** * Return an array of options representing permission restrictions, [value] => [label] * ranging from $widest to $narrowest. Set $doconfirms to whether email confirmations are on * @param int $widest * @param int $narrowest * @param bool $doconfirms * @param bool $dopoints * @return array */ function qa_admin_permit_options($widest, $narrowest, $doconfirms = true, $dopoints = true) { require_once QA_INCLUDE_DIR . 'app/options.php'; $options = array( QA_PERMIT_ALL => qa_lang_html('options/permit_all'), QA_PERMIT_USERS => qa_lang_html('options/permit_users'), QA_PERMIT_CONFIRMED => qa_lang_html('options/permit_confirmed'), QA_PERMIT_POINTS => qa_lang_html('options/permit_points'), QA_PERMIT_POINTS_CONFIRMED => qa_lang_html('options/permit_points_confirmed'), QA_PERMIT_APPROVED => qa_lang_html('options/permit_approved'), QA_PERMIT_APPROVED_POINTS => qa_lang_html('options/permit_approved_points'), QA_PERMIT_EXPERTS => qa_lang_html('options/permit_experts'), QA_PERMIT_EDITORS => qa_lang_html('options/permit_editors'), QA_PERMIT_MODERATORS => qa_lang_html('options/permit_moderators'), QA_PERMIT_ADMINS => qa_lang_html('options/permit_admins'), QA_PERMIT_SUPERS => qa_lang_html('options/permit_supers'), ); foreach ($options as $key => $label) { if ($key < $narrowest || $key > $widest) unset($options[$key]); } if (!$doconfirms) { unset($options[QA_PERMIT_CONFIRMED]); unset($options[QA_PERMIT_POINTS_CONFIRMED]); } if (!$dopoints) { unset($options[QA_PERMIT_POINTS]); unset($options[QA_PERMIT_POINTS_CONFIRMED]); unset($options[QA_PERMIT_APPROVED_POINTS]); } if (QA_FINAL_EXTERNAL_USERS || !qa_opt('moderate_users')) { unset($options[QA_PERMIT_APPROVED]); unset($options[QA_PERMIT_APPROVED_POINTS]); } return $options; } /** * Return the sub navigation structure common to admin pages * @return array */ function qa_admin_sub_navigation() { if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } $navigation = array(); $level = qa_get_logged_in_level(); if ($level >= QA_USER_LEVEL_ADMIN) { $navigation['admin/general'] = array( 'label' => qa_lang_html('admin/general_title'), 'url' => qa_path_html('admin/general'), ); $navigation['admin/emails'] = array( 'label' => qa_lang_html('admin/emails_title'), 'url' => qa_path_html('admin/emails'), ); $navigation['admin/users'] = array( 'label' => qa_lang_html('admin/users_title'), 'url' => qa_path_html('admin/users'), 'selected_on' => array('admin/users$', 'admin/userfields$', 'admin/usertitles$'), ); $navigation['admin/layout'] = array( 'label' => qa_lang_html('admin/layout_title'), 'url' => qa_path_html('admin/layout'), ); $navigation['admin/posting'] = array( 'label' => qa_lang_html('admin/posting_title'), 'url' => qa_path_html('admin/posting'), ); $navigation['admin/viewing'] = array( 'label' => qa_lang_html('admin/viewing_title'), 'url' => qa_path_html('admin/viewing'), ); $navigation['admin/lists'] = array( 'label' => qa_lang_html('admin/lists_title'), 'url' => qa_path_html('admin/lists'), ); if (qa_using_categories()) $navigation['admin/categories'] = array( 'label' => qa_lang_html('admin/categories_title'), 'url' => qa_path_html('admin/categories'), ); $navigation['admin/permissions'] = array( 'label' => qa_lang_html('admin/permissions_title'), 'url' => qa_path_html('admin/permissions'), ); $navigation['admin/pages'] = array( 'label' => qa_lang_html('admin/pages_title'), 'url' => qa_path_html('admin/pages'), ); $navigation['admin/feeds'] = array( 'label' => qa_lang_html('admin/feeds_title'), 'url' => qa_path_html('admin/feeds'), ); $navigation['admin/points'] = array( 'label' => qa_lang_html('admin/points_title'), 'url' => qa_path_html('admin/points'), ); $navigation['admin/spam'] = array( 'label' => qa_lang_html('admin/spam_title'), 'url' => qa_path_html('admin/spam'), ); $navigation['admin/caching'] = array( 'label' => qa_lang_html('admin/caching_title'), 'url' => qa_path_html('admin/caching'), ); $navigation['admin/stats'] = array( 'label' => qa_lang_html('admin/stats_title'), 'url' => qa_path_html('admin/stats'), ); if (!QA_FINAL_EXTERNAL_USERS) $navigation['admin/mailing'] = array( 'label' => qa_lang_html('admin/mailing_title'), 'url' => qa_path_html('admin/mailing'), ); $navigation['admin/plugins'] = array( 'label' => qa_lang_html('admin/plugins_title'), 'url' => qa_path_html('admin/plugins'), ); } if (!qa_user_maximum_permit_error('permit_moderate')) { $count = qa_user_permit_error('permit_moderate') ? 0 : (int)qa_opt('cache_queuedcount'); // if only in some categories don't show cached count $navigation['admin/moderate'] = array( 'label' => qa_lang_html_sub('admin/moderate_title', '<span class="qa-nav-sub-counter-moderate">' . qa_html(qa_format_number($count)) . '</span>'), 'url' => qa_path_html('admin/moderate'), ); } if (qa_opt('flagging_of_posts') && !qa_user_maximum_permit_error('permit_hide_show')) { $count = qa_user_permit_error('permit_hide_show') ? 0 : (int)qa_opt('cache_flaggedcount'); // if only in some categories don't show cached count $navigation['admin/flagged'] = array( 'label' => qa_lang_html_sub('admin/flagged_title', '<span class="qa-nav-sub-counter-flagged">' . qa_html(qa_format_number($count)) . '</span>'), 'url' => qa_path_html('admin/flagged'), ); } if (!qa_user_maximum_permit_error('permit_hide_show') || !qa_user_maximum_permit_error('permit_delete_hidden')) { $count = qa_user_permit_error('permit_hide_show') ? 0 : (int)qa_opt('cache_hiddencount'); $navigation['admin/hidden'] = array( 'label' => qa_lang_html_sub('admin/hidden_title', '<span class="qa-nav-sub-counter-hidden">' . qa_html(qa_format_number($count)) . '</span>'), 'url' => qa_path_html('admin/hidden'), ); } if (!QA_FINAL_EXTERNAL_USERS && qa_opt('moderate_users') && $level >= QA_USER_LEVEL_MODERATOR) { $count = (int)qa_opt('cache_uapprovecount'); $navigation['admin/approve'] = array( 'label' => qa_lang_html_sub('admin/approve_users_title', '<span class="qa-nav-sub-counter-approve">' . qa_html(qa_format_number($count)) . '</span>'), 'url' => qa_path_html('admin/approve'), ); } return $navigation; } /** * Return the error that needs to displayed on all admin pages, or null if none * @return string|null */ function qa_admin_page_error() { if (file_exists(QA_INCLUDE_DIR . 'db/install.php')) // file can be removed for extra security include_once QA_INCLUDE_DIR . 'db/install.php'; if (defined('QA_DB_VERSION_CURRENT') && qa_opt('db_version') < QA_DB_VERSION_CURRENT && qa_get_logged_in_level() >= QA_USER_LEVEL_ADMIN) { return strtr( qa_lang_html('admin/upgrade_db'), array( '^1' => '<a href="' . qa_path_html('install') . '">', '^2' => '</a>', ) ); } elseif (defined('QA_BLOBS_DIRECTORY') && !is_writable(QA_BLOBS_DIRECTORY)) { return qa_lang_html_sub('admin/blobs_directory_error', qa_html(QA_BLOBS_DIRECTORY)); } return null; } /** * Return an HTML fragment to display for a URL test which has passed * @return string */ function qa_admin_url_test_html() { return '; font-size:9px; color:#060; font-weight:bold; font-family:arial,sans-serif; border-color:#060;">OK<'; } /** * Returns whether a URL path beginning with $requestpart is reserved by the engine or a plugin page module * @param string $requestpart * @return bool */ function qa_admin_is_slug_reserved($requestpart) { $requestpart = trim(strtolower($requestpart)); $routing = qa_page_routing(); if (isset($routing[$requestpart]) || isset($routing[$requestpart . '/']) || is_numeric($requestpart)) return true; $pathmap = qa_get_request_map(); foreach ($pathmap as $mappedrequest) { if (trim(strtolower($mappedrequest)) == $requestpart) return true; } switch ($requestpart) { case '': case 'qa': case 'feed': case 'install': case 'url': case 'image': case 'ajax': return true; } $pagemodules = qa_load_modules_with('page', 'match_request'); foreach ($pagemodules as $pagemodule) { if ($pagemodule->match_request($requestpart)) return true; } return false; } /** * Returns true if admin (hidden/flagged/approve/moderate) page $action performed on $entityid is permitted by the * logged in user and was processed successfully * @param int $entityid * @param string $action * @return bool */ function qa_admin_single_click($entityid, $action) { $userid = qa_get_logged_in_userid(); if (!QA_FINAL_EXTERNAL_USERS && ($action == 'userapprove' || $action == 'userblock')) { // approve/block moderated users require_once QA_INCLUDE_DIR . 'db/selects.php'; $useraccount = qa_db_select_with_pending(qa_db_user_account_selectspec($entityid, true)); if (isset($useraccount) && qa_get_logged_in_level() >= QA_USER_LEVEL_MODERATOR) { switch ($action) { case 'userapprove': if ($useraccount['level'] <= QA_USER_LEVEL_APPROVED) { // don't demote higher level users require_once QA_INCLUDE_DIR . 'app/users-edit.php'; qa_set_user_level($useraccount['userid'], $useraccount['handle'], QA_USER_LEVEL_APPROVED, $useraccount['level']); return true; } break; case 'userblock': require_once QA_INCLUDE_DIR . 'app/users-edit.php'; qa_set_user_blocked($useraccount['userid'], $useraccount['handle'], true); return true; break; } } } else { // something to do with a post require_once QA_INCLUDE_DIR . 'app/posts.php'; $post = qa_post_get_full($entityid); if (isset($post)) { $queued = (substr($post['type'], 1) == '_QUEUED'); switch ($action) { case 'approve': if ($queued && !qa_user_post_permit_error('permit_moderate', $post)) { qa_post_set_status($entityid, QA_POST_STATUS_NORMAL, $userid); return true; } break; case 'reject': if ($queued && !qa_user_post_permit_error('permit_moderate', $post)) { qa_post_set_status($entityid, QA_POST_STATUS_HIDDEN, $userid); return true; } break; case 'hide': if (!$queued && !qa_user_post_permit_error('permit_hide_show', $post)) { qa_post_set_status($entityid, QA_POST_STATUS_HIDDEN, $userid); return true; } break; case 'reshow': if ($post['hidden'] && !qa_user_post_permit_error('permit_hide_show', $post)) { qa_post_set_status($entityid, QA_POST_STATUS_NORMAL, $userid); return true; } break; case 'delete': if ($post['hidden'] && !qa_user_post_permit_error('permit_delete_hidden', $post)) { qa_post_delete($entityid); return true; } break; case 'clearflags': require_once QA_INCLUDE_DIR . 'app/votes.php'; if (!qa_user_post_permit_error('permit_hide_show', $post)) { qa_flags_clear_all($post, $userid, qa_get_logged_in_handle(), null); return true; } break; } } } return false; } /** * Returns true if admin (hidden/flagged/approve/moderate) page $action performed on $entityid is permitted by the * logged in user and was processed successfully * @param int $entityid * @param string $action * @return array */ function qa_admin_single_click_array($entityid, $action) { $userid = qa_get_logged_in_userid(); $response = array(); if (!QA_FINAL_EXTERNAL_USERS && ($action === 'userapprove' || $action === 'userblock')) { // approve/block moderated users require_once QA_INCLUDE_DIR . 'db/selects.php'; $useraccount = qa_db_select_with_pending(qa_db_user_account_selectspec($entityid, true)); if (isset($useraccount) && qa_get_logged_in_level() >= QA_USER_LEVEL_MODERATOR) { switch ($action) { case 'userapprove': if ($useraccount['level'] >= QA_USER_LEVEL_APPROVED) { // don't demote higher level users $response['result'] = 'error'; $response['error']['type'] = 'user-already-approved'; $response['error']['message'] = qa_lang_html('main/general_error'); } else { require_once QA_INCLUDE_DIR . 'app/users-edit.php'; qa_set_user_level($useraccount['userid'], $useraccount['handle'], QA_USER_LEVEL_APPROVED, $useraccount['level']); $response['result'] = 'success'; $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-approve', 'html' => max((int)qa_opt('cache_uapprovecount') - 1, 0), ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } break; case 'userblock': require_once QA_INCLUDE_DIR . 'app/users-edit.php'; qa_set_user_blocked($useraccount['userid'], $useraccount['handle'], true); $response['result'] = 'success'; $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-approve', 'html' => max((int)qa_opt('cache_uapprovecount') - 1, 0), ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); break; default: } } } else { // something to do with a post require_once QA_INCLUDE_DIR . 'app/posts.php'; $post = qa_db_single_select(qa_db_full_post_selectspec(null, $entityid)); // Handle non-existent posts if ($post === null) { switch ($action) { case 'approve': case 'reject': $entityCount = (int)qa_opt('cache_queuedcount'); $selector = '.qa-nav-sub-counter-moderate'; break; case 'reshow': case 'delete': $entityCount = (int)qa_opt('cache_hiddencount'); $selector = '.qa-nav-sub-counter-hidden'; break; case 'hide': case 'clearflags': $entityCount = (int)qa_opt('cache_flaggedcount'); $selector = '.qa-nav-sub-counter-flagged'; break; default: $selector = ''; $entityCount = 0; } return array( 'result' => 'error', 'error' => array( 'type' => 'post-not-found', 'message' => qa_lang_html('main/general_error'), ), 'domUpdates' => array( array( 'selector' => $selector, 'html' => $entityCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ), ); } $queued = (substr($post['type'], 1) == '_QUEUED'); switch ($action) { case 'approve': case 'reject': $entityCount = (int)qa_opt('cache_queuedcount'); $hiddenCount = (int)qa_opt('cache_hiddencount'); if (!$queued) { $response['result'] = 'error'; $response['error']['type'] = 'post-not-queued'; $response['error']['message'] = qa_lang_html('main/general_error'); $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-moderate', 'html' => $entityCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } elseif (qa_user_post_permit_error('permit_moderate', $post) !== false) { $response['result'] = 'error'; $response['error']['type'] = 'no-permission'; $response['error']['message'] = qa_lang_html('users/no_permission'); $response['error']['severity'] = 'fatal'; } else { if ($action === 'approve') { qa_post_set_status($entityid, QA_POST_STATUS_NORMAL, $userid); } else { // 'reject' qa_post_set_status($entityid, QA_POST_STATUS_HIDDEN, $userid); $hiddenCount++; } $response['result'] = 'success'; $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-moderate', 'html' => max($entityCount - 1, 0), ), array( 'selector' => '.qa-nav-sub-counter-hidden', 'html' => $hiddenCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } break; case 'reshow': case 'delete': $entityCount = (int)qa_opt('cache_hiddencount'); if (!$post['hidden']) { $response['result'] = 'error'; $response['error']['type'] = 'post-not-hidden'; $response['error']['message'] = qa_lang_html('main/general_error'); $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-hidden', 'html' => $entityCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } elseif (qa_user_post_permit_error('permit_hide_show', $post) !== false) { $response['result'] = 'error'; $response['error']['type'] = 'no-permission'; $response['error']['message'] = qa_lang_html('users/no_permission'); $response['error']['severity'] = 'fatal'; } else { if ($action === 'reshow') { qa_post_set_status($entityid, QA_POST_STATUS_NORMAL, $userid); } else { // 'delete' qa_post_delete($entityid); } $response['result'] = 'success'; $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-hidden', 'html' => max($entityCount - 1, 0), ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } break; case 'hide': case 'clearflags': $entityCount = (int)qa_opt('cache_flaggedcount'); $hiddenCount = (int)qa_opt('cache_hiddencount'); if ($action === 'hide' && $queued) { $response['result'] = 'error'; $response['error']['type'] = 'post-queued'; $response['error']['message'] = qa_lang_html('main/general_error'); $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-flagged', 'html' => $entityCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } elseif (qa_user_post_permit_error('permit_hide_show', $post) !== false) { $response['result'] = 'error'; $response['error']['type'] = 'no-permission'; $response['error']['message'] = qa_lang_html('users/no_permission'); $response['error']['severity'] = 'fatal'; } else { if ($action === 'hide') { qa_post_set_status($entityid, QA_POST_STATUS_HIDDEN, $userid); $hiddenCount++; } else { // 'clearflags' require_once QA_INCLUDE_DIR . 'app/votes.php'; qa_flags_clear_all($post, $userid, qa_get_logged_in_handle(), null); } $response['result'] = 'success'; $response['domUpdates'] = array( array( 'selector' => '.qa-nav-sub-counter-flagged', 'html' => max($entityCount - 1, 0), ), array( 'selector' => '.qa-nav-sub-counter-hidden', 'html' => $hiddenCount, ), array( 'selector' => '#p' . $entityid, 'action' => 'conceal', ), ); } break; default: } } return $response; } /** * Checks for a POSTed click on an admin (hidden/flagged/approve/moderate) page, and refresh the page if processed successfully (non Ajax) * @return string|null */ function qa_admin_check_clicks() { if (!qa_is_http_post()) { return null; } foreach ($_POST as $field => $value) { if (strpos($field, 'admin_') !== 0) { continue; } @list($dummy, $entityid, $action) = explode('_', $field); if (strlen($entityid) && strlen($action)) { if (!qa_check_form_security_code('admin/click', qa_post_text('code'))) return qa_lang_html('misc/form_security_again'); elseif (qa_admin_single_click($entityid, $action)) qa_redirect(qa_request()); } } return null; } /** * Retrieve metadata information from the $contents of a qa-theme.php or qa-plugin.php file, mapping via $fields. * * @deprecated Deprecated from 1.7; use `qa_addon_metadata($contents, $type)` instead. * @param string $contents * @param array $fields * @return array */ function qa_admin_addon_metadata($contents, $fields) { $metadata = array(); foreach ($fields as $key => $field) { if (preg_match('/' . str_replace(' ', '[ \t]*', preg_quote($field, '/')) . ':[ \t]*([^\n\f]*)[\n\f]/i', $contents, $matches)) $metadata[$key] = trim($matches[1]); } return $metadata; } /** * Return the hash code for the plugin in $directory (without trailing slash), used for in-page navigation on admin/plugins page * @param string $directory * @return mixed */ function qa_admin_plugin_directory_hash($directory) { $pluginManager = new \Q2A\Plugin\PluginManager(); $hashes = $pluginManager->getHashesForPlugins(array($directory)); return reset($hashes); } /** * Return the URL (relative to the current page) to navigate to the options panel for the plugin in $directory (without trailing slash) * @param string $directory * @return mixed|string */ function qa_admin_plugin_options_path($directory) { $hash = qa_admin_plugin_directory_hash($directory); return qa_path_html('admin/plugins', array('show' => $hash), null, null, $hash); } /** * Return the URL (relative to the current page) to navigate to the options panel for plugin module $name of $type * @param string $type * @param string $name * @return mixed|string */ function qa_admin_module_options_path($type, $name) { $info = qa_get_module_info($type, $name); $dir = basename($info['directory']); return qa_admin_plugin_options_path($dir); }