/** * This listener is run when the KernelEvents::EXCEPTION event is triggered * * @param GetResponseForExceptionEvent $event * @return null */ public function on_kernel_exception(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $message = $exception->getMessage(); if ($exception instanceof \src\exception\exception_interface) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($message), $exception->get_parameters())); } if (!$event->getRequest()->isXmlHttpRequest()) { page_header($this->user->lang('INFORMATION')); $this->template->assign_vars(array('MESSAGE_TITLE' => $this->user->lang('INFORMATION'), 'MESSAGE_TEXT' => $message)); $this->template->set_filenames(array('body' => 'message_body.html')); page_footer(true, false, false); $response = new Response($this->template->assign_display('body'), 500); } else { $data = array(); if (!empty($message)) { $data['message'] = $message; } if (defined('DEBUG')) { $data['trace'] = $exception->getTrace(); } $response = new JsonResponse($data, 500); } if ($exception instanceof HttpExceptionInterface) { $response->setStatusCode($exception->getStatusCode()); $response->headers->add($exception->getHeaders()); } $event->setResponse($response); }
/** * Generate ISO 8601 date string (RFC 3339) */ public function format_date($time) { static $zone_offset; static $offset_string; if (empty($offset_string)) { $zone_offset = $this->user->create_datetime()->getOffset(); $offset_string = src_format_timezone_offset($zone_offset); } return gmdate("Y-m-d\\TH:i:s", $time + $zone_offset) . $offset_string; }
/** * Get the notification type id from the name * * @param string $notification_type_name The name * @return int the notification_type_id * @throws \src\notification\exception */ public function get_notification_type_id($notification_type_name) { $notification_type_ids = $this->cache->get('notification_type_ids'); if ($notification_type_ids === false) { $notification_type_ids = array(); $sql = 'SELECT notification_type_id, notification_type_name FROM ' . $this->notification_types_table; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $notification_type_ids[$row['notification_type_name']] = (int) $row['notification_type_id']; } $this->db->sql_freeresult($result); $this->cache->put('notification_type_ids', $notification_type_ids); } if (!isset($notification_type_ids[$notification_type_name])) { if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name])) { throw new \src\notification\exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name)); } $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array('notification_type_name' => $notification_type_name, 'notification_type_enabled' => 1)); $this->db->sql_query($sql); $notification_type_ids[$notification_type_name] = (int) $this->db->sql_nextid(); $this->cache->put('notification_type_ids', $notification_type_ids); } return $notification_type_ids[$notification_type_name]; }
/** * Dependencies should be specified in the service definition and can be * then accessed in __construct(). Arguments are sent through the URL path * and should match the parameters of the method you are using as your * controller. * * @param \Symfony\Component\HttpFoundation\Request $request Symfony Request object * @param mixed $controller A callable (controller class, method) * @return array An array of arguments to pass to the controller * @throws \src\controller\exception */ public function getArguments(Request $request, $controller) { // At this point, $controller contains the object and method name list($object, $method) = $controller; $mirror = new \ReflectionMethod($object, $method); $arguments = array(); $parameters = $mirror->getParameters(); $attributes = $request->attributes->all(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { if (is_string($attributes[$param->name])) { $value = $attributes[$param->name]; $this->type_cast_helper->set_var($value, $attributes[$param->name], 'string', true, false); $arguments[] = $value; } else { $arguments[] = $attributes[$param->name]; } } else { if ($param->getClass() && $param->getClass()->isInstance($request)) { $arguments[] = $request; } else { if ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); } else { throw new \src\controller\exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); } } } } return $arguments; }
/** * {@inheritDoc} */ public function validate_profile_field(&$field_value, $field_data) { $field_value = (bool) $field_value; if (!$field_value && $field_data['field_required']) { return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); } return false; }
/** * Prepare to output the notification to the template * * @return array Template variables */ public function prepare_for_display() { $mark_hash = generate_link_hash('mark_notification_read'); if ($this->get_url()) { $u_mark_read = append_sid($this->src_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&hash=' . $mark_hash); } else { $redirect = ($this->user->page['page_dir'] ? $this->user->page['page_dir'] . '/' : '') . $this->user->page['page_name'] . ($this->user->page['query_string'] ? '?' . $this->user->page['query_string'] : ''); $u_mark_read = append_sid($this->src_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&hash=' . $mark_hash . '&redirect=' . urlencode($redirect)); } return array('NOTIFICATION_ID' => $this->notification_id, 'STYLING' => $this->get_style_class(), 'AVATAR' => $this->get_avatar(), 'FORMATTED_TITLE' => $this->get_title(), 'REFERENCE' => $this->get_reference(), 'FORUM' => $this->get_forum(), 'REASON' => $this->get_reason(), 'URL' => $this->get_url(), 'TIME' => $this->user->format_date($this->notification_time), 'UNREAD' => !$this->notification_read, 'U_MARK_READ' => !$this->notification_read ? $u_mark_read : ''); }
/** * Output a message * * In case of an error, please throw an exception instead * * @param string $message The message to display (must be a language variable) * @param array $parameters The parameters to use with the language var * @param string $title Title for the message (must be a language variable) * @param int $code The HTTP status code (e.g. 404, 500, 503, etc.) * @return Response A Response instance */ public function message($message, array $parameters = array(), $title = 'INFORMATION', $code = 200) { array_unshift($parameters, $message); $message_text = call_user_func_array(array($this->user, 'lang'), $parameters); $message_title = $this->user->lang($title); if ($this->request->is_ajax()) { global $refresh_data; return new JsonResponse(array('MESSAGE_TITLE' => $message_title, 'MESSAGE_TEXT' => $message_text, 'S_USER_WARNING' => false, 'S_USER_NOTICE' => false, 'REFRESH_DATA' => !empty($refresh_data) ? $refresh_data : null), $code); } $this->template->assign_vars(array('MESSAGE_TEXT' => $message_text, 'MESSAGE_TITLE' => $message_title)); return $this->render('message_body.html', $message_title, $code); }
/** * Validates the contents of the authors field * * @return boolean True when passes validation, throws exception if invalid * @throws \src\extension\exception */ public function validate_authors() { if (empty($this->metadata['authors'])) { throw new \src\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'authors')); } foreach ($this->metadata['authors'] as $author) { if (!isset($author['name'])) { throw new \src\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'author name')); } } return true; }
/** * Check accuracy of attachment statistics. * * @return bool|string Returns false if stats are correct or error message * otherwise. */ public function check_stats_accuracy() { // Get fresh stats. $stats = $this->get_attachment_stats(); // Get current files stats $num_files = (int) $this->config['num_files']; $total_size = (double) $this->config['upload_dir_size']; if ($num_files != $stats['num_files'] || $total_size != $stats['upload_dir_size']) { $u_resync = $this->u_action . '&action=stats'; return $this->user->lang('FILES_STATS_WRONG', (int) $stats['num_files'], get_formatted_filesize($stats['upload_dir_size']), '<a href="' . $u_resync . '">', '</a>'); } return false; }
/** * Wrapper for \acp_modules::get_module_infos() * * @param string $class Module Class * @param string $basename Module Basename * @return array Module Information * @throws \src\db\migration\exception */ protected function get_module_info($class, $basename) { if (!class_exists('acp_modules')) { include $this->src_root_path . 'includes/acp/acp_modules.' . $this->php_ext; $this->user->add_lang('acp/modules'); } $acp_modules = new \acp_modules(); $module = $acp_modules->get_module_infos($basename, $class, true); if (empty($module)) { throw new \src\db\migration\exception('MODULE_INFO_FILE_NOT_EXIST', $class, $basename); } return array_pop($module); }
/** * {@inheritDoc} */ public function validate_profile_field(&$field_value, $field_data) { $field_value = (int) $field_value; // retrieve option lang data if necessary if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], 1)) { $this->lang_helper->load_option_lang($field_data['lang_id']); } if (!$this->lang_helper->is_set($field_data['field_id'], $field_data['lang_id'], $field_value)) { return $this->user->lang('FIELD_INVALID_VALUE', $this->get_field_name($field_data['lang_name'])); } if ($field_value == $field_data['field_novalue'] && $field_data['field_required']) { return $this->user->lang('FIELD_REQUIRED', $this->get_field_name($field_data['lang_name'])); } return false; }
/** * {@inheritDoc} */ public function validate_profile_field(&$field_value, $field_data) { if (trim($field_value) === '' && !$field_data['field_required']) { return false; } $field_value = (int) $field_value; if ($field_value < $field_data['field_minlen']) { return $this->user->lang('FIELD_TOO_SMALL', (int) $field_data['field_minlen'], $this->get_field_name($field_data['lang_name'])); } else { if ($field_value > $field_data['field_maxlen']) { return $this->user->lang('FIELD_TOO_LARGE', (int) $field_data['field_maxlen'], $this->get_field_name($field_data['lang_name'])); } } return false; }
/** * {@inheritDoc} */ public function get_profile_value($field_value, $field_data) { $date = explode('-', $field_value); $day = isset($date[0]) ? (int) $date[0] : 0; $month = isset($date[1]) ? (int) $date[1] : 0; $year = isset($date[2]) ? (int) $date[2] : 0; if (!$day && !$month && !$year && !$field_data['field_show_novalue']) { return null; } else { if ($day && $month && $year) { // Date should display as the same date for every user regardless of timezone return $this->user->create_datetime()->setDate($year, $month, $day)->setTime(0, 0, 0)->format($this->user->lang['DATE_FORMAT'], true); } } return $field_value; }
/** * Install style(s) */ protected function action_install() { // Get list of styles to install $dirs = $this->request_vars('dir', '', true); // Get list of styles that can be installed $styles = $this->find_available(false); // Install each style $messages = array(); $installed_names = array(); $installed_dirs = array(); $last_installed = false; foreach ($dirs as $dir) { if (in_array($dir, $this->reserved_style_names)) { $messages[] = $this->user->lang('STYLE_NAME_RESERVED', htmlspecialchars($dir)); continue; } $found = false; foreach ($styles as &$style) { // Check if: // 1. Directory matches directory we are looking for // 2. Style is not installed yet // 3. Style with same name or directory hasn't been installed already within this function if ($style['style_path'] == $dir && empty($style['_installed']) && !in_array($style['style_path'], $installed_dirs) && !in_array($style['style_name'], $installed_names)) { // Install style $style['style_active'] = 1; $style['style_id'] = $this->install_style($style); $style['_installed'] = true; $found = true; $last_installed = $style['style_id']; $installed_names[] = $style['style_name']; $installed_dirs[] = $style['style_path']; $messages[] = sprintf($this->user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name'])); } } if (!$found) { $messages[] = sprintf($this->user->lang['STYLE_NOT_INSTALLED'], htmlspecialchars($dir)); } } // Show message if (!count($messages)) { trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } $message = implode('<br />', $messages); $message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=style' . '">« ' . $this->user->lang('STYLE_INSTALLED_RETURN_INSTALLED_STYLES') . '</a>'; $message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=install' . '">» ' . $this->user->lang('STYLE_INSTALLED_RETURN_UNINSTALLED_STYLES') . '</a>'; trigger_error($message, E_USER_NOTICE); }
/** * Build Array for user insertion into custom profile fields table */ public function build_insert_sql_array($cp_data) { $sql_not_in = array(); foreach ($cp_data as $key => $null) { $sql_not_in[] = strncmp($key, 'pf_', 3) === 0 ? substr($key, 3) : $key; } $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . ' ' . (sizeof($sql_not_in) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' AND l.field_id = f.field_id'; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $profile_field = $this->type_collection[$row['field_type']]; $cp_data['pf_' . $row['field_ident']] = $profile_field->get_default_field_value($row); } $this->db->sql_freeresult($result); return $cp_data; }
/** * Obtains the latest version information * * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return string Version info, includes stable and unstable data * @throws \RuntimeException */ public function get_versions($force_update = false, $force_cache = false) { $cache_file = '_versioncheck_' . $this->host . $this->path . $this->file; $info = $this->cache->get($cache_file); if ($info === false && $force_cache) { throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); } else { if ($info === false || $force_update) { try { $info = $this->file_downloader->get($this->host, $this->path, $this->file); } catch (\src\exception\runtime_exception $exception) { $prepare_parameters = array_merge(array($exception->getMessage()), $exception->get_parameters()); throw new \RuntimeException(call_user_func_array(array($this->user, 'lang'), $prepare_parameters)); } $error_string = $this->file_downloader->get_error_string(); if (!empty($error_string)) { throw new \RuntimeException($error_string); } $info = json_decode($info, true); // Sanitize any data we retrieve from a server if (!empty($info)) { $json_sanitizer = function (&$value, $key) { $type_cast_helper = new \src\request\type_cast_helper(); $type_cast_helper->set_var($value, $value, gettype($value), true); }; array_walk_recursive($info, $json_sanitizer); } if (empty($info['stable']) && empty($info['unstable'])) { $this->user->add_lang('acp/common'); throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); } $info['stable'] = empty($info['stable']) ? array() : $info['stable']; $info['unstable'] = empty($info['unstable']) ? $info['stable'] : $info['unstable']; $this->cache->put($cache_file, $info, 86400); // 24 hours } } return $info; }
/** * Return current page * * @param int $num_items the total number of items, posts, topics, etc. * @param int $per_page the number of items, posts, etc. per page * @param int $start the item which should be considered currently active, used to determine the page we're on * @return string Descriptive pagination string (e.g. "page 1 of 10") */ public function on_page($num_items, $per_page, $start) { $on_page = $this->get_on_page($per_page, $start); return $this->user->lang('PAGE_OF', $on_page, max(ceil($num_items / $per_page), 1)); }
/** * This function fills $this->search_query with the cleaned user search query * * If $terms is 'any' then the words will be extracted from the search query * and combined with | inside brackets. They will afterwards be treated like * an standard search query. * * Then it analyses the query and fills the internal arrays $must_not_contain_ids, * $must_contain_ids and $must_exclude_one_ids which are later used by keyword_search() * * @param string $keywords contains the search query string as entered by the user * @param string $terms is either 'all' (use search query as entered, default words to 'must be contained in post') * or 'any' (find all posts containing at least one of the given words) * @return boolean false if no valid keywords were found and otherwise true */ public function split_keywords($keywords, $terms) { $tokens = '+-|()*'; $keywords = trim($this->cleanup($keywords, $tokens)); // allow word|word|word without brackets if (strpos($keywords, ' ') === false && strpos($keywords, '|') !== false && strpos($keywords, '(') === false) { $keywords = '(' . $keywords . ')'; } $open_bracket = $space = false; for ($i = 0, $n = strlen($keywords); $i < $n; $i++) { if ($open_bracket !== false) { switch ($keywords[$i]) { case ')': if ($open_bracket + 1 == $i) { $keywords[$i - 1] = '|'; $keywords[$i] = '|'; } $open_bracket = false; break; case '(': $keywords[$i] = '|'; break; case '+': case '-': case ' ': $keywords[$i] = '|'; break; case '*': if ($i === 0 || $keywords[$i - 1] !== '*' && strcspn($keywords[$i - 1], $tokens) === 0) { if ($i === $n - 1 || $keywords[$i + 1] !== '*' && strcspn($keywords[$i + 1], $tokens) === 0) { $keywords = substr($keywords, 0, $i) . substr($keywords, $i + 1); } } break; } } else { switch ($keywords[$i]) { case ')': $keywords[$i] = ' '; break; case '(': $open_bracket = $i; $space = false; break; case '|': $keywords[$i] = ' '; break; case '-': case '+': $space = $keywords[$i]; break; case ' ': if ($space !== false) { $keywords[$i] = $space; } break; default: $space = false; } } } if ($open_bracket) { $keywords .= ')'; } $match = array('# +#', '#\\|\\|+#', '#(\\+|\\-)(?:\\+|\\-)+#', '#\\(\\|#', '#\\|\\)#'); $replace = array(' ', '|', '$1', '(', ')'); $keywords = preg_replace($match, $replace, $keywords); $num_keywords = sizeof(explode(' ', $keywords)); // We limit the number of allowed keywords to minimize load on the database if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords']) { trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], $num_keywords)); } // $keywords input format: each word separated by a space, words in a bracket are not separated // the user wants to search for any word, convert the search query if ($terms == 'any') { $words = array(); preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $words); if (sizeof($words[1])) { $keywords = '(' . implode('|', $words[1]) . ')'; } } // set the search_query which is shown to the user $this->search_query = $keywords; $exact_words = array(); preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $exact_words); $exact_words = $exact_words[1]; $common_ids = $words = array(); if (sizeof($exact_words)) { $sql = 'SELECT word_id, word_text, word_common FROM ' . SEARCH_WORDLIST_TABLE . ' WHERE ' . $this->db->sql_in_set('word_text', $exact_words) . ' ORDER BY word_count ASC'; $result = $this->db->sql_query($sql); // store an array of words and ids, remove common words while ($row = $this->db->sql_fetchrow($result)) { if ($row['word_common']) { $this->common_words[] = $row['word_text']; $common_ids[$row['word_text']] = (int) $row['word_id']; continue; } $words[$row['word_text']] = (int) $row['word_id']; } $this->db->sql_freeresult($result); } // Handle +, - without preceeding whitespace character $match = array('#(\\S)\\+#', '#(\\S)-#'); $replace = array('$1 +', '$1 +'); $keywords = preg_replace($match, $replace, $keywords); // now analyse the search query, first split it using the spaces $query = explode(' ', $keywords); $this->must_contain_ids = array(); $this->must_not_contain_ids = array(); $this->must_exclude_one_ids = array(); $mode = ''; $ignore_no_id = true; foreach ($query as $word) { if (empty($word)) { continue; } // words which should not be included if ($word[0] == '-') { $word = substr($word, 1); // a group of which at least one may not be in the resulting posts if ($word[0] == '(') { $word = array_unique(explode('|', substr($word, 1, -1))); $mode = 'must_exclude_one'; } else { $mode = 'must_not_contain'; } $ignore_no_id = true; } else { // no prefix is the same as a +prefix if ($word[0] == '+') { $word = substr($word, 1); } // a group of words of which at least one word should be in every resulting post if ($word[0] == '(') { $word = array_unique(explode('|', substr($word, 1, -1))); } $ignore_no_id = false; $mode = 'must_contain'; } if (empty($word)) { continue; } // if this is an array of words then retrieve an id for each if (is_array($word)) { $non_common_words = array(); $id_words = array(); foreach ($word as $i => $word_part) { if (strpos($word_part, '*') !== false) { $id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\''; $non_common_words[] = $word_part; } else { if (isset($words[$word_part])) { $id_words[] = $words[$word_part]; $non_common_words[] = $word_part; } else { $len = utf8_strlen($word_part); if ($len < $this->word_length['min'] || $len > $this->word_length['max']) { $this->common_words[] = $word_part; } } } } if (sizeof($id_words)) { sort($id_words); if (sizeof($id_words) > 1) { $this->{$mode . '_ids'}[] = $id_words; } else { $mode = $mode == 'must_exclude_one' ? 'must_not_contain' : $mode; $this->{$mode . '_ids'}[] = $id_words[0]; } } else { if (!$ignore_no_id && sizeof($non_common_words)) { trigger_error(sprintf($this->user->lang['WORDS_IN_NO_POST'], implode($this->user->lang['COMMA_SEPARATOR'], $non_common_words))); } } unset($non_common_words); } else { if (($wildcard = strpos($word, '*') !== false) || isset($words[$word])) { if ($wildcard) { $len = utf8_strlen(str_replace('*', '', $word)); if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) { $this->{$mode . '_ids'}[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word)) . '\''; } else { $this->common_words[] = $word; } } else { $this->{$mode . '_ids'}[] = $words[$word]; } } else { if (!isset($common_ids[$word])) { $len = utf8_strlen($word); if ($len < $this->word_length['min'] || $len > $this->word_length['max']) { $this->common_words[] = $word; } } } } } // Return true if all words are not common words if (sizeof($exact_words) - sizeof($this->common_words) > 0) { return true; } return false; }
/** * Performs a search on keywords depending on display specific params. You have to run split_keywords() first * * @param string $type contains either posts or topics depending on what should be searched for * @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched) * @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words) * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query * @param string $sort_key is the key of $sort_by_sql for the selected sorting * @param string $sort_dir is either a or d representing ASC and DESC * @param string $sort_days specifies the maximum amount of days a post may be old * @param array $ex_fid_ary specifies an array of forum ids which should not be searched * @param string $post_visibility specifies which types of posts the user can view in which forums * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched * @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered * @param int $start indicates the first index of the page * @param int $per_page number of ids each page is supposed to contain * @return boolean|int total number of results */ public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No keywords? No posts. if (!strlen($this->search_query) && !sizeof($author_ary)) { return false; } $id_ary = array(); $join_topic = $type != 'posts'; // Sorting if ($type == 'topics') { switch ($sort_key) { case 'a': $this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'poster_id ' . ($sort_dir == 'a' ? 'ASC' : 'DESC')); break; case 'f': $this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'forum_id ' . ($sort_dir == 'a' ? 'ASC' : 'DESC')); break; case 'i': case 's': $this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'post_subject ' . ($sort_dir == 'a' ? 'ASC' : 'DESC')); break; case 't': default: $this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'topic_last_post_time ' . ($sort_dir == 'a' ? 'ASC' : 'DESC')); break; } } else { switch ($sort_key) { case 'a': $this->sphinx->SetSortMode($sort_dir == 'a' ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'poster_id'); break; case 'f': $this->sphinx->SetSortMode($sort_dir == 'a' ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'forum_id'); break; case 'i': case 's': $this->sphinx->SetSortMode($sort_dir == 'a' ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_subject'); break; case 't': default: $this->sphinx->SetSortMode($sort_dir == 'a' ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_time'); break; } } // Most narrow filters first if ($topic_id) { $this->sphinx->SetFilter('topic_id', array($topic_id)); } $search_query_prefix = ''; switch ($fields) { case 'titleonly': // Only search the title if ($terms == 'all') { $search_query_prefix = '@title '; } // Weight for the title $this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1)); // 1 is first_post, 0 is not first post $this->sphinx->SetFilter('topic_first_post', array(1)); break; case 'msgonly': // Only search the body if ($terms == 'all') { $search_query_prefix = '@data '; } // Weight for the body $this->sphinx->SetFieldWeights(array("title" => 1, "data" => 5)); break; case 'firstpost': // More relative weight for the title, also search the body $this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1)); // 1 is first_post, 0 is not first post $this->sphinx->SetFilter('topic_first_post', array(1)); break; default: // More relative weight for the title, also search the body $this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1)); break; } if (sizeof($author_ary)) { $this->sphinx->SetFilter('poster_id', $author_ary); } // As this is not simply possible at the moment, we limit the result to approved posts. // This will make it impossible for moderators to search unapproved and softdeleted posts, // but at least it will also cause the same for normal users. $this->sphinx->SetFilter('post_visibility', array(ITEM_APPROVED)); if (sizeof($ex_fid_ary)) { // All forums that a user is allowed to access $fid_ary = array_unique(array_intersect(array_keys($this->auth->acl_getf('f_read', true)), array_keys($this->auth->acl_getf('f_search', true)))); // All forums that the user wants to and can search in $search_forums = array_diff($fid_ary, $ex_fid_ary); if (sizeof($search_forums)) { $this->sphinx->SetFilter('forum_id', $search_forums); } } $this->sphinx->SetFilter('deleted', array(0)); $this->sphinx->SetLimits($start, (int) $per_page, SPHINX_MAX_MATCHES); $result = $this->sphinx->Query($search_query_prefix . str_replace('"', '"', $this->search_query), $this->indexes); // Could be connection to localhost:9312 failed (errno=111, // msg=Connection refused) during rotate, retry if so $retries = SPHINX_CONNECT_RETRIES; while (!$result && strpos($this->sphinx->GetLastError(), "errno=111,") !== false && $retries--) { usleep(SPHINX_CONNECT_WAIT_TIME); $result = $this->sphinx->Query($search_query_prefix . str_replace('"', '"', $this->search_query), $this->indexes); } if ($this->sphinx->GetLastError()) { add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError()); if ($this->auth->acl_get('a_')) { trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError())); } else { trigger_error($this->user->lang('SPHINX_SEARCH_FAILED_LOG')); } } $result_count = $result['total_found']; if ($result_count && $start >= $result_count) { $start = floor(($result_count - 1) / $per_page) * $per_page; $this->sphinx->SetLimits((int) $start, (int) $per_page, SPHINX_MAX_MATCHES); $result = $this->sphinx->Query($search_query_prefix . str_replace('"', '"', $this->search_query), $this->indexes); // Could be connection to localhost:9312 failed (errno=111, // msg=Connection refused) during rotate, retry if so $retries = SPHINX_CONNECT_RETRIES; while (!$result && strpos($this->sphinx->GetLastError(), "errno=111,") !== false && $retries--) { usleep(SPHINX_CONNECT_WAIT_TIME); $result = $this->sphinx->Query($search_query_prefix . str_replace('"', '"', $this->search_query), $this->indexes); } } $id_ary = array(); if (isset($result['matches'])) { if ($type == 'posts') { $id_ary = array_keys($result['matches']); } else { foreach ($result['matches'] as $key => $value) { $id_ary[] = $value['attrs']['topic_id']; } } } else { return false; } $id_ary = array_slice($id_ary, 0, (int) $per_page); return $result_count; }
/** * Splits keywords entered by a user into an array of words stored in $this->split_words * Stores the tidied search query in $this->search_query * * @param string &$keywords Contains the keyword as entered by the user * @param string $terms is either 'all' or 'any' * @return bool false if no valid keywords were found and otherwise true */ public function split_keywords(&$keywords, $terms) { if ($terms == 'all') { $match = array('#\\sand\\s#iu', '#\\sor\\s#iu', '#\\snot\\s#iu', '#(^|\\s)\\+#', '#(^|\\s)-#', '#(^|\\s)\\|#'); $replace = array(' +', ' |', ' -', ' +', ' -', ' |'); $keywords = preg_replace($match, $replace, $keywords); } // Filter out as above $split_keywords = preg_replace("#[\n\r\t]+#", ' ', trim(htmlspecialchars_decode($keywords))); // Split words $split_keywords = preg_replace('#([^\\p{L}\\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords))); $matches = array(); preg_match_all('#(?:[^\\p{L}\\p{N}*"()]|^)([+\\-|]?(?:[\\p{L}\\p{N}*"()]+\'?)*[\\p{L}\\p{N}*"()])(?:[^\\p{L}\\p{N}*"()]|$)#u', $split_keywords, $matches); $this->split_words = $matches[1]; // We limit the number of allowed keywords to minimize load on the database if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords']) { trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], sizeof($this->split_words))); } // to allow phrase search, we need to concatenate quoted words $tmp_split_words = array(); $phrase = ''; foreach ($this->split_words as $word) { if ($phrase) { $phrase .= ' ' . $word; if (strpos($word, '"') !== false && substr_count($word, '"') % 2 == 1) { $tmp_split_words[] = $phrase; $phrase = ''; } } else { if (strpos($word, '"') !== false && substr_count($word, '"') % 2 == 1) { $phrase = $word; } else { $tmp_split_words[] = $word; } } } if ($phrase) { $tmp_split_words[] = $phrase; } $this->split_words = $tmp_split_words; unset($tmp_split_words); unset($phrase); foreach ($this->split_words as $i => $word) { $clean_word = preg_replace('#^[+\\-|"]#', '', $word); // check word length $clean_len = utf8_strlen(str_replace('*', '', $clean_word)); if ($clean_len < $this->config['fulltext_mysql_min_word_len'] || $clean_len > $this->config['fulltext_mysql_max_word_len']) { $this->common_words[] = $word; unset($this->split_words[$i]); } } if ($terms == 'any') { $this->search_query = ''; foreach ($this->split_words as $word) { if (strpos($word, '+') === 0 || strpos($word, '-') === 0 || strpos($word, '|') === 0) { $word = substr($word, 1); } $this->search_query .= $word . ' '; } } else { $this->search_query = ''; foreach ($this->split_words as $word) { if (strpos($word, '+') === 0 || strpos($word, '-') === 0) { $this->search_query .= $word . ' '; } else { if (strpos($word, '|') === 0) { $this->search_query .= substr($word, 1) . ' '; } else { $this->search_query .= '+' . $word . ' '; } } } } $this->search_query = utf8_htmlspecialchars($this->search_query); if ($this->search_query) { $this->split_words = array_values($this->split_words); sort($this->split_words); return true; } return false; }
/** * Sends an error message back to the client via JSON response * * @param int $code The error code * @param string $msg The translation string of the message to be sent * * @return null */ public function emit_error($code, $msg) { $json_response = new \src\json_response(); $json_response->send(array('jsonrpc' => '2.0', 'id' => 'id', 'error' => array('code' => $code, 'message' => $this->user->lang($msg)))); }
/** * {@inheritDoc} */ public function get_name() { return $this->user->lang('FIELD_' . strtoupper($this->get_name_short())); }
/** * {@inheritDoc} */ public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '') { $this->entry_count = 0; $this->last_page_offset = $offset; $topic_id_list = $reportee_id_list = array(); $profile_url = $this->get_is_admin() && $this->src_admin_path ? append_sid("{$this->src_admin_path}index.{$this->php_ext}", 'i=users&mode=overview') : append_sid("{$this->src_root_path}memberlist.{$this->php_ext}", 'mode=viewprofile'); switch ($mode) { case 'admin': $log_type = LOG_ADMIN; $sql_additional = ''; break; case 'mod': $log_type = LOG_MOD; $sql_additional = ''; if ($topic_id) { $sql_additional = 'AND l.topic_id = ' . (int) $topic_id; } else { if (is_array($forum_id)) { $sql_additional = 'AND ' . $this->db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); } else { if ($forum_id) { $sql_additional = 'AND l.forum_id = ' . (int) $forum_id; } } } break; case 'user': $log_type = LOG_USERS; $sql_additional = 'AND l.reportee_id = ' . (int) $user_id; break; case 'users': $log_type = LOG_USERS; $sql_additional = ''; break; case 'critical': $log_type = LOG_CRITICAL; $sql_additional = ''; break; default: $log_type = false; $sql_additional = ''; } /** * Overwrite log type and limitations before we count and get the logs * * NOTE: if log_type is false, no entries will be returned. * * @event core.get_logs_modify_type * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type Limit logs to a certain type. If log_type * is false, no entries will be returned. * @var string sql_additional Additional conditions for the entries, * e.g.: 'AND l.forum_id = 1' * @since 3.1.0-a1 */ $vars = array('mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional'); extract($this->dispatcher->trigger_event('core.get_logs_modify_type', compact($vars))); if ($log_type === false) { $this->last_page_offset = 0; return array(); } $sql_keywords = ''; if (!empty($keywords)) { // Get the SQL condition for our keywords $sql_keywords = $this->generate_sql_keyword($keywords); } $get_logs_sql_ary = array('SELECT' => 'l.*, u.username, u.username_clean, u.user_colour', 'FROM' => array($this->log_table => 'l', USERS_TABLE => 'u'), 'WHERE' => 'l.log_type = ' . (int) $log_type . "\n\t\t\t\t\tAND l.user_id = u.user_id\n\t\t\t\t\t{$sql_keywords}\n\t\t\t\t\t{$sql_additional}", 'ORDER_BY' => $sort_by); if ($log_time) { $get_logs_sql_ary['WHERE'] = 'l.log_time >= ' . (int) $log_time . ' AND ' . $get_logs_sql_ary['WHERE']; } /** * Modify the query to obtain the logs data * * @event core.get_logs_main_query_before * @var array get_logs_sql_ary The array in the format of the query builder with the query * to get the log count and the log list * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type Limit logs to a certain type. If log_type * is false, no entries will be returned. * @var string sql_additional Additional conditions for the entries, * e.g.: 'AND l.forum_id = 1' * @since 3.1.5-RC1 */ $vars = array('get_logs_sql_ary', 'mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional'); extract($this->dispatcher->trigger_event('core.get_logs_main_query_before', compact($vars))); if ($count_logs) { $count_logs_sql_ary = $get_logs_sql_ary; $count_logs_sql_ary['SELECT'] = 'COUNT(l.log_id) AS total_entries'; unset($count_logs_sql_ary['ORDER_BY']); $sql = $this->db->sql_build_query('SELECT', $count_logs_sql_ary); $result = $this->db->sql_query($sql); $this->entry_count = (int) $this->db->sql_fetchfield('total_entries'); $this->db->sql_freeresult($result); if ($this->entry_count == 0) { // Save the queries, because there are no logs to display $this->last_page_offset = 0; return array(); } // Return the user to the last page that is valid while ($this->last_page_offset >= $this->entry_count) { $this->last_page_offset = max(0, $this->last_page_offset - $limit); } } $sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary); $result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset); $i = 0; $log = array(); while ($row = $this->db->sql_fetchrow($result)) { $row['forum_id'] = (int) $row['forum_id']; if ($row['topic_id']) { $topic_id_list[] = (int) $row['topic_id']; } if ($row['reportee_id']) { $reportee_id_list[] = (int) $row['reportee_id']; } $log_entry_data = array('id' => (int) $row['log_id'], 'reportee_id' => (int) $row['reportee_id'], 'reportee_username' => '', 'reportee_username_full' => '', 'user_id' => (int) $row['user_id'], 'username' => $row['username'], 'username_full' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url), 'ip' => $row['log_ip'], 'time' => (int) $row['log_time'], 'forum_id' => (int) $row['forum_id'], 'topic_id' => (int) $row['topic_id'], 'viewforum' => $row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id']) ? append_sid("{$this->src_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false, 'action' => isset($this->user->lang[$row['log_operation']]) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}'); /** * Modify the entry's data before it is returned * * @event core.get_logs_modify_entry_data * @var array row Entry data from the database * @var array log_entry_data Entry's data which is returned * @since 3.1.0-a1 */ $vars = array('row', 'log_entry_data'); extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars))); $log[$i] = $log_entry_data; if (!empty($row['log_data'])) { $log_data_ary = unserialize($row['log_data']); $log_data_ary = $log_data_ary !== false ? $log_data_ary : array(); if (isset($this->user->lang[$row['log_operation']])) { // Check if there are more occurrences of % than // arguments, if there are we fill out the arguments // array. It doesn't matter if we add more arguments than // placeholders. $num_args = 0; if (!is_array($this->user->lang[$row['log_operation']])) { $num_args = substr_count($this->user->lang[$row['log_operation']], '%'); } else { foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string) { $num_args = max($num_args, substr_count($plural_string, '%')); } } if ($num_args - sizeof($log_data_ary) > 0) { $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), '')); } $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary); $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments); // If within the admin panel we do not censor text out if ($this->get_is_admin()) { $log[$i]['action'] = bbcode_nl2br($log[$i]['action']); } else { $log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action'])); } } else { if (!empty($log_data_ary)) { $log[$i]['action'] .= '<br />' . implode('', $log_data_ary); } } /* Apply make_clickable... has to be seen if it is for good. :/ // Seems to be not for the moment, reconsider later... $log[$i]['action'] = make_clickable($log[$i]['action']); */ } else { $log[$i]['action'] = $this->user->lang($log[$i]['action']); } $i++; } $this->db->sql_freeresult($result); /** * Get some additional data after we got all log entries * * @event core.get_logs_get_additional_data * @var array log Array with all our log entries * @var array topic_id_list Array of topic ids, for which we * get the permission data * @var array reportee_id_list Array of additional user IDs we * get the username strings for * @since 3.1.0-a1 */ $vars = array('log', 'topic_id_list', 'reportee_id_list'); extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars))); if (sizeof($topic_id_list)) { $topic_auth = $this->get_topic_auth($topic_id_list); foreach ($log as $key => $row) { $log[$key]['viewtopic'] = isset($topic_auth['f_read'][$row['topic_id']]) ? append_sid("{$this->src_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id']) : false; $log[$key]['viewlogs'] = isset($topic_auth['m_'][$row['topic_id']]) ? append_sid("{$this->src_root_path}mcp.{$this->php_ext}", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $this->user->session_id) : false; } } if (sizeof($reportee_id_list)) { $reportee_data_list = $this->get_reportee_data($reportee_id_list); foreach ($log as $key => $row) { if (!isset($reportee_data_list[$row['reportee_id']])) { continue; } $log[$key]['reportee_username'] = $reportee_data_list[$row['reportee_id']]['username']; $log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_data_list[$row['reportee_id']]['username'], $reportee_data_list[$row['reportee_id']]['user_colour'], false, $profile_url); } } /** * Allow modifying or execute extra final filter on log entries * * @event core.get_logs_after * @var array log Array with all our log entries * @var array topic_id_list Array of topic ids, for which we * get the permission data * @var array reportee_id_list Array of additional user IDs we * get the username strings for * @var string mode Mode of the entries we display * @var bool count_logs Do we count all matching entries? * @var int limit Limit the number of entries * @var int offset Offset when fetching the entries * @var mixed forum_id Limit entries to the forum_id, * can also be an array of forum_ids * @var int topic_id Limit entries to the topic_id * @var int user_id Limit entries to the user_id * @var int log_time Limit maximum age of log entries * @var string sort_by SQL order option * @var string keywords Will only return entries that have the * keywords in log_operation or log_data * @var string profile_url URL to the users profile * @var int log_type The type of logs it was filtered * @since 3.1.3-RC1 */ $vars = array('log', 'topic_id_list', 'reportee_id_list', 'mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type'); extract($this->dispatcher->trigger_event('core.get_logs_after', compact($vars))); return $log; }
/** * Replace "error" strings with their real, localized form * * @param \src\user src User object * @param array $error Array containing error strings * Key values can either be a string with a language key or an array * that will be passed to vsprintf() with the language key in the * first array key. * * @return array Array containing the localized error strings */ public function localize_errors(\src\user $user, $error) { foreach ($error as $key => $lang) { if (is_array($lang)) { $lang_key = array_shift($lang); $error[$key] = vsprintf($user->lang($lang_key), $lang); } else { $error[$key] = $user->lang("{$lang}"); } } return $error; }
/** * Options to pick a timezone and date/time * * @param \src\template\template $template src template object * @param \src\user $user Object of the current user * @param string $default A timezone to select * @param boolean $truncate Shall we truncate the options text * * @return array Returns an array containing the options for the time selector. */ function src_timezone_select($template, $user, $default = '', $truncate = false) { static $timezones; $default_offset = ''; if (!isset($timezones)) { $unsorted_timezones = src_get_timezone_identifiers($default); $timezones = array(); foreach ($unsorted_timezones as $timezone) { $tz = new DateTimeZone($timezone); $dt = $user->create_datetime('now', $tz); $offset = $dt->getOffset(); $current_time = $dt->format($user->lang['DATETIME_FORMAT'], true); $offset_string = src_format_timezone_offset($offset, true); $timezones['UTC' . $offset_string . ' - ' . $timezone] = array('tz' => $timezone, 'offset' => $offset_string, 'current' => $current_time); if ($timezone === $default) { $default_offset = 'UTC' . $offset_string; } } unset($unsorted_timezones); uksort($timezones, 'src_tz_select_compare'); } $tz_select = $opt_group = ''; foreach ($timezones as $key => $timezone) { if ($opt_group != $timezone['offset']) { // Generate tz_select for backwards compatibility $tz_select .= $opt_group ? '</optgroup>' : ''; $tz_select .= '<optgroup label="' . $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']) . '">'; $opt_group = $timezone['offset']; $template->assign_block_vars('timezone_select', array('LABEL' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']), 'VALUE' => $key . ' - ' . $timezone['current'])); $selected = !empty($default_offset) && strpos($key, $default_offset) !== false ? ' selected="selected"' : ''; $template->assign_block_vars('timezone_date', array('VALUE' => $key . ' - ' . $timezone['current'], 'SELECTED' => !empty($selected), 'TITLE' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']))); } $label = $timezone['tz']; if (isset($user->lang['timezones'][$label])) { $label = $user->lang['timezones'][$label]; } $title = $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $label); if ($truncate) { $label = truncate_string($label, 50, 255, false, '...'); } // Also generate timezone_select for backwards compatibility $selected = $timezone['tz'] === $default ? ' selected="selected"' : ''; $tz_select .= '<option title="' . $title . '" value="' . $timezone['tz'] . '"' . $selected . '>' . $label . '</option>'; $template->assign_block_vars('timezone_select.timezone_options', array('TITLE' => $title, 'VALUE' => $timezone['tz'], 'SELECTED' => !empty($selected), 'LABEL' => $label)); } $tz_select .= '</optgroup>'; return $tz_select; }
function get_passworded_forums() { return $this->user->get_passworded_forums(); }
/** * Returns the language string of a permission * * @param string $permission Identifier of the permission * @return string Language string */ public function get_permission_lang($permission) { return isset($this->permissions[$permission]['lang']) ? $this->user->lang($this->permissions[$permission]['lang']) : $this->user->lang('ACL_' . strtoupper($permission)); }
/** * Output all the notification methods to the template * * @param \src\notification\manager $src_notifications * @param \src\template\template $template * @param \src\user $user * @param string $block */ public function output_notification_methods(\src\notification\manager $src_notifications, \src\template\template $template, \src\user $user, $block = 'notification_methods') { $notification_methods = $src_notifications->get_subscription_methods(); foreach ($notification_methods as $method => $method_data) { $template->assign_block_vars($block, array('METHOD' => $method_data['id'], 'NAME' => $user->lang($method_data['lang']))); } }