public function output_widget($region, $place, $themeobject, $template, $request, $qa_content) { require_once QA_INCLUDE_DIR . 'db/selects.php'; $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, (int) qa_opt('tag_cloud_count_tags'))); $maxcount = reset($populartags); // $themeobject->output(sprintf('<h2 style="margin-top: 0; padding-top: 0;">%s</h2>', qa_lang_html('main/popular_tags'))); // $themeobject->output('<div style="font-size: 10px;">'); $themeobject->output(sprintf('<div class="panel panel-primary" style="padding: 0;"><div class="panel-heading"><h3 class="panel-title">%s</h3></div>', qa_lang_html('main/popular_tags'))); $themeobject->output('<div class="panel-body">'); $maxsize = qa_opt('tag_cloud_font_size'); $minsize = qa_opt('tag_cloud_minimal_font_size'); $scale = qa_opt('tag_cloud_size_popular'); $blockwordspreg = qa_get_block_words_preg(); foreach ($populartags as $tag => $count) { $matches = qa_block_words_match_all($tag, $blockwordspreg); if (empty($matches)) { if ($scale) { $size = number_format($maxsize * $count / $maxcount, 1); if ($size < $minsize) { $size = $minsize; } } else { $size = $maxsize; } $themeobject->output(sprintf('<a href="%s" style="font-size: %dpx; vertical-align: baseline;">%s</a>', qa_path_html('tag/' . $tag), $size, qa_html($tag))); } } // $themeobject->output('</div>'); $themeobject->output('</div></div>'); }
public function test__qa_block_words_match_all() { $test1 = qa_block_words_match_all('onion belt', ''); $wordpreg = qa_block_words_to_preg($this->blockWordString); $test2 = qa_block_words_match_all('tried an ocean boat', $wordpreg); // matches are returned as array of [offset] => [length] $expected = array(0 => 5, 9 => 5, 15 => 4); $this->assertEmpty($test1); $this->assertEquals($expected, $test2); }
function output_widget($region, $place, $themeobject, $template, $request, $qa_content) { require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; $widget_opt = @$themeobject->current_widget['param']['options']; if (@$themeobject->current_widget['param']['locations']['show_title']) { $themeobject->output('<h3 class="widget-title">' . qa_lang('cleanstrap/tags') . '<a href="' . qa_path_html('tags') . '">' . qa_lang('cleanstrap/view_all') . '</a></h3>'); } $to_show = (int) $widget_opt['cs_tags_count']; $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, !empty($to_show) ? $to_show : 20)); reset($populartags); $themeobject->output('<div class="ra-tags-widget clearfix">'); $blockwordspreg = qa_get_block_words_preg(); foreach ($populartags as $tag => $count) { if (count(qa_block_words_match_all($tag, $blockwordspreg))) { continue; } // skip censored tags $themeobject->output('<a href="' . qa_path_html('tag/' . $tag) . '" class="widget-tag">' . qa_html($tag) . '<span>' . $count . '</span></a>'); } $themeobject->output('</div>'); }
function qa_post_html_fields($post, $userid, $cookieid, $usershtml, $dummy, $options = array()) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } require_once QA_INCLUDE_DIR . 'app/updates.php'; if (isset($options['blockwordspreg'])) { require_once QA_INCLUDE_DIR . 'util/string.php'; } $fields = array('raw' => $post); // Useful stuff used throughout function $postid = $post['postid']; $isquestion = $post['basetype'] == 'Q'; $isanswer = $post['basetype'] == 'A'; $isbyuser = qa_post_is_by_user($post, $userid, $cookieid); $anchor = urlencode(qa_anchor($post['basetype'], $postid)); $elementid = isset($options['elementid']) ? $options['elementid'] : $anchor; $microformats = @$options['microformats']; $isselected = @$options['isselected']; $favoritedview = @$options['favoritedview']; $favoritemap = $favoritedview ? qa_get_favorite_non_qs_map() : array(); // High level information $fields['hidden'] = @$post['hidden']; $fields['tags'] = 'id="' . qa_html($elementid) . '"'; $fields['classes'] = $isquestion && $favoritedview && @$post['userfavoriteq'] ? 'qa-q-favorited' : ''; if ($isquestion && isset($post['closedbyid'])) { $fields['classes'] = ltrim($fields['classes'] . ' qa-q-closed'); } if ($microformats) { $fields['classes'] .= ' hentry ' . ($isquestion ? 'question' : ($isanswer ? $isselected ? 'answer answer-selected' : 'answer' : 'comment')); } // Question-specific stuff (title, URL, tags, answer count, category) if ($isquestion) { if (isset($post['title'])) { $fields['url'] = qa_q_path_html($postid, $post['title']); if (isset($options['blockwordspreg'])) { $post['title'] = qa_block_words_replace($post['title'], $options['blockwordspreg']); } $fields['title'] = qa_html($post['title']); if ($microformats) { $fields['title'] = '<span class="entry-title">' . $fields['title'] . '</span>'; } /*if (isset($post['score'])) // useful for setting match thresholds $fields['title'].=' <small>('.$post['score'].')</small>';*/ } if (@$options['tagsview'] && isset($post['tags'])) { $fields['q_tags'] = array(); $tags = qa_tagstring_to_tags($post['tags']); foreach ($tags as $tag) { if (isset($options['blockwordspreg']) && count(qa_block_words_match_all($tag, $options['blockwordspreg']))) { // skip censored tags continue; } $fields['q_tags'][] = qa_tag_html($tag, $microformats, @$favoritemap['tag'][qa_strtolower($tag)]); } } if (@$options['answersview'] && isset($post['acount'])) { $fields['answers_raw'] = $post['acount']; $fields['answers'] = $post['acount'] == 1 ? qa_lang_html_sub_split('main/1_answer', '1', '1') : qa_lang_html_sub_split('main/x_answers', number_format($post['acount'])); $fields['answer_selected'] = isset($post['selchildid']); } if (@$options['viewsview'] && isset($post['views'])) { $fields['views_raw'] = $post['views']; $fields['views'] = $post['views'] == 1 ? qa_lang_html_sub_split('main/1_view', '1', '1') : qa_lang_html_sub_split('main/x_views', number_format($post['views'])); } if (@$options['categoryview'] && isset($post['categoryname']) && isset($post['categorybackpath'])) { $favoriteclass = ''; if (count(@$favoritemap['category'])) { if (@$favoritemap['category'][$post['categorybackpath']]) { $favoriteclass = ' qa-cat-favorited'; } else { foreach ($favoritemap['category'] as $categorybackpath => $dummy) { if (substr('/' . $post['categorybackpath'], -strlen($categorybackpath)) == $categorybackpath) { $favoriteclass = ' qa-cat-parent-favorited'; } } } } $fields['where'] = qa_lang_html_sub_split('main/in_category_x', '<a href="' . qa_path_html(@$options['categorypathprefix'] . implode('/', array_reverse(explode('/', $post['categorybackpath'])))) . '" class="qa-category-link' . $favoriteclass . '">' . qa_html($post['categoryname']) . '</a>'); } } // Answer-specific stuff (selection) if ($isanswer) { $fields['selected'] = $isselected; if ($isselected) { $fields['select_text'] = qa_lang_html('question/select_text'); } } // Post content if (@$options['contentview'] && isset($post['content'])) { $viewer = qa_load_viewer($post['content'], $post['format']); $fields['content'] = $viewer->get_html($post['content'], $post['format'], array('blockwordspreg' => @$options['blockwordspreg'], 'showurllinks' => @$options['showurllinks'], 'linksnewwindow' => @$options['linksnewwindow'])); if ($microformats) { $fields['content'] = '<div class="entry-content">' . $fields['content'] . '</div>'; } $fields['content'] = '<a name="' . qa_html($postid) . '"></a>' . $fields['content']; // this is for backwards compatibility with any existing links using the old style of anchor // that contained the post id only (changed to be valid under W3C specifications) } // Voting stuff if (@$options['voteview']) { $voteview = $options['voteview']; // Calculate raw values and pass through if (@$options['ovoteview'] && isset($post['opostid'])) { $upvotes = (int) @$post['oupvotes']; $downvotes = (int) @$post['odownvotes']; $fields['vote_opostid'] = true; // for voters/flaggers layer } else { $upvotes = (int) @$post['upvotes']; $downvotes = (int) @$post['downvotes']; } $netvotes = (int) ($upvotes - $downvotes); $fields['upvotes_raw'] = $upvotes; $fields['downvotes_raw'] = $downvotes; $fields['netvotes_raw'] = $netvotes; // Create HTML versions... $upvoteshtml = qa_html($upvotes); $downvoteshtml = qa_html($downvotes); if ($netvotes >= 1) { $netvoteshtml = '+' . qa_html($netvotes); } elseif ($netvotes <= -1) { $netvoteshtml = '–' . qa_html(-$netvotes); } else { $netvoteshtml = '0'; } // ...with microformats if appropriate if ($microformats) { $netvoteshtml .= '<span class="votes-up"><span class="value-title" title="' . $upvoteshtml . '"></span></span>' . '<span class="votes-down"><span class="value-title" title="' . $downvoteshtml . '"></span></span>'; $upvoteshtml = '<span class="votes-up">' . $upvoteshtml . '</span>'; $downvoteshtml = '<span class="votes-down">' . $downvoteshtml . '</span>'; } // Pass information on vote viewing // $voteview will be one of: // updown, updown-disabled-page, updown-disabled-level, updown-uponly-level, updown-disabled-approve, updown-uponly-approve // net, net-disabled-page, net-disabled-level, net-uponly-level, net-disabled-approve, net-uponly-approve $fields['vote_view'] = substr($voteview, 0, 6) == 'updown' ? 'updown' : 'net'; $fields['vote_on_page'] = strpos($voteview, '-disabled-page') ? 'disabled' : 'enabled'; $fields['upvotes_view'] = $upvotes == 1 ? qa_lang_html_sub_split('main/1_liked', $upvoteshtml, '1') : qa_lang_html_sub_split('main/x_liked', $upvoteshtml); $fields['downvotes_view'] = $downvotes == 1 ? qa_lang_html_sub_split('main/1_disliked', $downvoteshtml, '1') : qa_lang_html_sub_split('main/x_disliked', $downvoteshtml); $fields['netvotes_view'] = abs($netvotes) == 1 ? qa_lang_html_sub_split('main/1_vote', $netvoteshtml, '1') : qa_lang_html_sub_split('main/x_votes', $netvoteshtml); // Voting buttons $fields['vote_tags'] = 'id="voting_' . qa_html($postid) . '"'; $onclick = 'onclick="return qa_vote_click(this);"'; if ($fields['hidden']) { $fields['vote_state'] = 'disabled'; $fields['vote_up_tags'] = 'title="' . qa_lang_html($isanswer ? 'main/vote_disabled_hidden_a' : 'main/vote_disabled_hidden_q') . '"'; $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif ($isbyuser) { $fields['vote_state'] = 'disabled'; $fields['vote_up_tags'] = 'title="' . qa_lang_html($isanswer ? 'main/vote_disabled_my_a' : 'main/vote_disabled_my_q') . '"'; $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif (strpos($voteview, '-disabled-')) { $fields['vote_state'] = @$post['uservote'] > 0 ? 'voted_up_disabled' : (@$post['uservote'] < 0 ? 'voted_down_disabled' : 'disabled'); if (strpos($voteview, '-disabled-page')) { $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_q_page_only') . '"'; } elseif (strpos($voteview, '-disabled-approve')) { $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_approve') . '"'; } else { $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_level') . '"'; } $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif (@$post['uservote'] > 0) { $fields['vote_state'] = 'voted_up'; $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/voted_up_popup') . '" name="' . qa_html('vote_' . $postid . '_0_' . $elementid) . '" ' . $onclick; $fields['vote_down_tags'] = ' '; } elseif (@$post['uservote'] < 0) { $fields['vote_state'] = 'voted_down'; $fields['vote_up_tags'] = ' '; $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/voted_down_popup') . '" name="' . qa_html('vote_' . $postid . '_0_' . $elementid) . '" ' . $onclick; } else { $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_up_popup') . '" name="' . qa_html('vote_' . $postid . '_1_' . $elementid) . '" ' . $onclick; if (strpos($voteview, '-uponly-level')) { $fields['vote_state'] = 'up_only'; $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_disabled_down') . '"'; } elseif (strpos($voteview, '-uponly-approve')) { $fields['vote_state'] = 'up_only'; $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_disabled_down_approve') . '"'; } else { $fields['vote_state'] = 'enabled'; $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_down_popup') . '" name="' . qa_html('vote_' . $postid . '_-1_' . $elementid) . '" ' . $onclick; } } } // Flag count if (@$options['flagsview'] && @$post['flagcount']) { $fields['flags'] = $post['flagcount'] == 1 ? qa_lang_html_sub_split('main/1_flag', '1', '1') : qa_lang_html_sub_split('main/x_flags', $post['flagcount']); } // Created when and by whom $fields['meta_order'] = qa_lang_html('main/meta_order'); // sets ordering of meta elements which can be language-specific if (@$options['whatview']) { $fields['what'] = qa_lang_html($isquestion ? 'main/asked' : ($isanswer ? 'main/answered' : 'main/commented')); if (@$options['whatlink'] && strlen(@$options['q_request'])) { $fields['what_url'] = $post['basetype'] == 'Q' ? qa_path_html($options['q_request']) : qa_path_html($options['q_request'], array('show' => $postid), null, null, qa_anchor($post['basetype'], $postid)); } } if (isset($post['created']) && @$options['whenview']) { $fields['when'] = qa_when_to_html($post['created'], @$options['fulldatedays']); if ($microformats) { $fields['when']['data'] = '<span class="published"><span class="value-title" title="' . gmdate('Y-m-d\\TH:i:sO', $post['created']) . '">' . $fields['when']['data'] . '</span></span>'; } } if (@$options['whoview']) { $fields['who'] = qa_who_to_html($isbyuser, @$post['userid'], $usershtml, @$options['ipview'] ? @$post['createip'] : null, $microformats, $post['name']); if (isset($post['points'])) { if (@$options['pointsview']) { $fields['who']['points'] = $post['points'] == 1 ? qa_lang_html_sub_split('main/1_point', '1', '1') : qa_lang_html_sub_split('main/x_points', qa_html(number_format($post['points']))); } if (isset($options['pointstitle'])) { $fields['who']['title'] = qa_get_points_title_html($post['points'], $options['pointstitle']); } } if (isset($post['level'])) { $fields['who']['level'] = qa_html(qa_user_level_string($post['level'])); } } if (@$options['avatarsize'] > 0) { if (QA_FINAL_EXTERNAL_USERS) { $fields['avatar'] = qa_get_external_avatar_html($post['userid'], $options['avatarsize'], false); } else { $fields['avatar'] = qa_get_user_avatar_html(@$post['flags'], @$post['email'], @$post['handle'], @$post['avatarblobid'], @$post['avatarwidth'], @$post['avatarheight'], $options['avatarsize']); } } // Updated when and by whom if (@$options['updateview'] && isset($post['updated']) && ($post['updatetype'] != QA_UPDATE_SELECTED || $isselected) && (!isset($post['created']) || $post['hidden'] && $post['updatetype'] == QA_UPDATE_VISIBLE || isset($post['closedbyid']) && $post['updatetype'] == QA_UPDATE_CLOSED || abs($post['updated'] - $post['created']) > 300 || $post['lastuserid'] != $post['userid'])) { switch ($post['updatetype']) { case QA_UPDATE_TYPE: case QA_UPDATE_PARENT: $langstring = 'main/moved'; break; case QA_UPDATE_CATEGORY: $langstring = 'main/recategorized'; break; case QA_UPDATE_VISIBLE: $langstring = $post['hidden'] ? 'main/hidden' : 'main/reshown'; break; case QA_UPDATE_CLOSED: $langstring = isset($post['closedbyid']) ? 'main/closed' : 'main/reopened'; break; case QA_UPDATE_TAGS: $langstring = 'main/retagged'; break; case QA_UPDATE_SELECTED: $langstring = 'main/selected'; break; default: $langstring = 'main/edited'; break; } $fields['what_2'] = qa_lang_html($langstring); if (@$options['whenview']) { $fields['when_2'] = qa_when_to_html($post['updated'], @$options['fulldatedays']); if ($microformats) { $fields['when_2']['data'] = '<span class="updated"><span class="value-title" title="' . gmdate('Y-m-d\\TH:i:sO', $post['updated']) . '">' . $fields['when_2']['data'] . '</span></span>'; } } if (isset($post['lastuserid']) && @$options['whoview']) { $fields['who_2'] = qa_who_to_html(isset($userid) && $post['lastuserid'] == $userid, $post['lastuserid'], $usershtml, @$options['ipview'] ? $post['lastip'] : null, false); } } elseif ($microformats && @$options['whenview']) { // quick fix for incorrect microformats (missing 'updated' class) $fields['when']['data'] = str_replace('<span class="published">', '<span class="published updated">', $fields['when']['data']); } // That's it! return $fields; }
function qa_block_words_replace($string, $wordspreg, $character = '*') { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (strlen($wordspreg)) { $matches = qa_block_words_match_all($string, $wordspreg); krsort($matches, SORT_NUMERIC); foreach ($matches as $start => $length) { // get length again below to deal with multi-byte characters $string = substr_replace($string, str_repeat($character, qa_strlen(substr($string, $start, $length))), $start, $length); } } return $string; }
function output_widget($region, $place, $themeobject, $template, $request, $qa_content) { require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, (int) qa_opt('tag_cloud_count_tags'))); reset($populartags); $maxcount = current($populartags); $themeobject->output('<h2 style="margin-top:0; padding-top:0;">', qa_lang_html('main/popular_tags'), '</h2>'); $themeobject->output('<div style="font-size:10px;">'); $maxsize = qa_opt('tag_cloud_font_size'); $scale = qa_opt('tag_cloud_size_popular'); $blockwordspreg = qa_get_block_words_preg(); foreach ($populartags as $tag => $count) { if (count(qa_block_words_match_all($tag, $blockwordspreg))) { continue; } // skip censored tags $size = number_format($scale ? $maxsize * $count / $maxcount : $maxsize, 1); if ($size >= 5 || !$scale) { $themeobject->output('<a href="' . qa_path_html('tag/' . $tag) . '" style="font-size:' . $size . 'px; vertical-align:baseline;">' . qa_html($tag) . '</a>'); } } $themeobject->output('</div>'); }
function get_html($content, $format, $options) { if ($format == 'html') { $html = qa_sanitize_html($content, @$options['linksnewwindow'], false); // sanitize again for display, for extra safety, and due to new window setting if (isset($options['blockwordspreg'])) { // filtering out blocked words inline within HTML is pretty complex, e.g. p<B>oo</B>p must be caught require_once QA_INCLUDE_DIR . 'qa-util-string.php'; $html = preg_replace('/<\\s*(' . $this->htmllineseparators . ')[^A-Za-z0-9]/i', "\n\\0", $html); // tags to single new line $html = preg_replace('/<\\s*(' . $this->htmlparagraphseparators . ')[^A-Za-z0-9]/i', "\n\n\\0", $html); // tags to double new line preg_match_all('/<[^>]*>/', $html, $pregmatches, PREG_OFFSET_CAPTURE); // find tag positions and lengths $tagmatches = $pregmatches[0]; $text = preg_replace('/<[^>]*>/', '', $html); // effectively strip_tags() but use same regexp as above to ensure consistency $blockmatches = qa_block_words_match_all($text, $options['blockwordspreg']); // search for blocked words within text $nexttagmatch = array_shift($tagmatches); $texttohtml = 0; $htmlshift = 0; foreach ($blockmatches as $textoffset => $textlength) { while (isset($nexttagmatch) && $nexttagmatch[1] <= $textoffset + $texttohtml) { // keep text and html in sync $texttohtml += strlen($nexttagmatch[0]); $nexttagmatch = array_shift($tagmatches); } while (1) { $replacepart = $textlength; if (isset($nexttagmatch)) { $replacepart = min($replacepart, $nexttagmatch[1] - ($textoffset + $texttohtml)); } // stop replacing early if we hit an HTML tag $replacelength = qa_strlen(substr($text, $textoffset, $replacepart)); // to work with multi-byte characters $html = substr_replace($html, str_repeat('*', $replacelength), $textoffset + $texttohtml + $htmlshift, $replacepart); $htmlshift += $replacelength - $replacepart; // HTML might have moved around if we replaced multi-byte characters if ($replacepart >= $textlength) { break; } // we have replaced everything expected, otherwise more left (due to hitting an HTML tag) $textlength -= $replacepart; $textoffset += $replacepart; $texttohtml += strlen($nexttagmatch[0]); $nexttagmatch = array_shift($tagmatches); } } } if (@$options['showurllinks']) { // we need to ensure here that we don't put new links inside existing ones require_once QA_INCLUDE_DIR . 'qa-util-string.php'; $htmlunlinkeds = array_reverse(preg_split('|<[Aa]\\s+[^>]+>.*</[Aa]\\s*>|', $html, -1, PREG_SPLIT_OFFSET_CAPTURE)); // start from end so we substitute correctly foreach ($htmlunlinkeds as $htmlunlinked) { // and that we don't detect links inside HTML, e.g. <IMG SRC="http://..."> $thishtmluntaggeds = array_reverse(preg_split('/<[^>]*>/', $htmlunlinked[0], -1, PREG_SPLIT_OFFSET_CAPTURE)); // again, start from end foreach ($thishtmluntaggeds as $thishtmluntagged) { $innerhtml = $thishtmluntagged[0]; if (is_numeric(strpos($innerhtml, '://'))) { // quick test first $newhtml = qa_html_convert_urls($innerhtml, qa_opt('links_in_new_window')); $html = substr_replace($html, $newhtml, $htmlunlinked[1] + $thishtmluntagged[1], strlen($innerhtml)); } } } } } elseif ($format == '') { if (isset($options['blockwordspreg'])) { require_once QA_INCLUDE_DIR . 'qa-util-string.php'; $content = qa_block_words_replace($content, $options['blockwordspreg']); } $html = qa_html($content, true); if (@$options['showurllinks']) { require_once QA_INCLUDE_DIR . 'qa-app-format.php'; $html = qa_html_convert_urls($html, qa_opt('links_in_new_window')); } } else { $html = '[no viewer found for format: ' . qa_html($format) . ']'; } // for unknown formats return $html; }
function qa_block_words_replace($string, $wordspreg, $character = '*') { if (strlen($wordspreg)) { $matches = qa_block_words_match_all($string, $wordspreg); krsort($matches, SORT_NUMERIC); foreach ($matches as $start => $length) { // get length again below to deal with multi-byte characters $string = substr_replace($string, str_repeat($character, qa_strlen(substr($string, $start, $length))), $start, $length); } } return $string; }
function qa_post_html_fields($post, $userid, $cookieid, $usershtml, $dummy, $options = array()) { if (isset($options['blockwordspreg'])) { require_once QA_INCLUDE_DIR . 'qa-util-string.php'; } $fields = array(); $fields['raw'] = $post; // Useful stuff used throughout function $postid = $post['postid']; $isquestion = $post['basetype'] == 'Q'; $isanswer = $post['basetype'] == 'A'; $isbyuser = qa_post_is_by_user($post, $userid, $cookieid); $anchor = urlencode(qa_anchor($post['basetype'], $postid)); $microformats = @$options['microformats']; $isselected = @$options['isselected']; // High level information $fields['hidden'] = $post['hidden']; $fields['tags'] = 'ID="' . $anchor . '"'; if ($microformats) { $fields['classes'] = 'hentry ' . ($isquestion ? 'question' : ($isanswer ? $isselected ? 'answer answer-selected' : 'answer' : 'comment')); } // Question-specific stuff (title, URL, tags, answer count, category) if ($isquestion) { if (isset($post['title'])) { if (isset($options['blockwordspreg'])) { $post['title'] = qa_block_words_replace($post['title'], $options['blockwordspreg']); } $fields['title'] = qa_html($post['title']); if ($microformats) { $fields['title'] = '<SPAN CLASS="entry-title">' . $fields['title'] . '</SPAN>'; } $fields['url'] = qa_path_html(qa_q_request($postid, $post['title'])); /*if (isset($post['score'])) // useful for setting match thresholds $fields['title'].=' <SMALL>('.$post['score'].')</SMALL>';*/ } if (@$options['tagsview'] && isset($post['tags'])) { $fields['q_tags'] = array(); $tags = qa_tagstring_to_tags($post['tags']); foreach ($tags as $tag) { if (isset($options['blockwordspreg']) && count(qa_block_words_match_all($tag, $options['blockwordspreg']))) { // skip censored tags continue; } $fields['q_tags'][] = qa_tag_html($tag, $microformats); } } if (@$options['answersview'] && isset($post['acount'])) { $fields['answers_raw'] = $post['acount']; $fields['answers'] = $post['acount'] == 1 ? qa_lang_html_sub_split('main/1_answer', '1', '1') : qa_lang_html_sub_split('main/x_answers', number_format($post['acount'])); $fields['answer_selected'] = isset($post['selchildid']); } if (@$options['viewsview'] && isset($post['views'])) { $fields['views_raw'] = $post['views']; $fields['views'] = $post['views'] == 1 ? qa_lang_html_sub_split('main/1_view', '1', '1') : qa_lang_html_sub_split('main/x_views', number_format($post['views'])); } if (isset($post['categoryname']) && isset($post['categorybackpath'])) { $fields['where'] = qa_lang_html_sub_split('main/in_category_x', '<A HREF="' . qa_path_html(@$options['categorypathprefix'] . implode('/', array_reverse(explode('/', $post['categorybackpath'])))) . '" CLASS="qa-category-link">' . qa_html($post['categoryname']) . '</A>'); } } // Answer-specific stuff (selection) if ($isanswer) { $fields['selected'] = $isselected; if ($isselected) { $fields['select_text'] = qa_lang_html('question/select_text'); } } // Post content if (!empty($post['content'])) { $viewer = qa_load_viewer($post['content'], $post['format']); $fields['content'] = $viewer->get_html($post['content'], $post['format'], array('blockwordspreg' => @$options['blockwordspreg'], 'showurllinks' => @$options['showurllinks'], 'linksnewwindow' => @$options['linksnewwindow'])); if ($microformats) { $fields['content'] = '<SPAN CLASS="entry-content">' . $fields['content'] . '</SPAN>'; } $fields['content'] = '<A NAME="' . qa_html($postid) . '"></A>' . $fields['content']; // this is for backwards compatibility with any existing links using the old style of anchor // that contained the post id only (changed to be valid under W3C specifications) } // Voting stuff if (@$options['voteview']) { $voteview = $options['voteview']; // Calculate raw values and pass through $upvotes = (int) @$post['upvotes']; $downvotes = (int) @$post['downvotes']; $netvotes = (int) ($upvotes - $downvotes); $fields['upvotes_raw'] = $upvotes; $fields['downvotes_raw'] = $downvotes; $fields['netvotes_raw'] = $netvotes; // Create HTML versions... $upvoteshtml = qa_html($upvotes); $downvoteshtml = qa_html($downvotes); if ($netvotes >= 1) { $netvoteshtml = '+' . qa_html($netvotes); } elseif ($netvotes <= -1) { $netvoteshtml = '–' . qa_html(-$netvotes); } else { $netvoteshtml = '0'; } // ...with microformats if appropriate if ($microformats) { $netvoteshtml .= '<SPAN CLASS="votes-up"><SPAN CLASS="value-title" TITLE="' . $upvoteshtml . '"></SPAN></SPAN>' . '<SPAN CLASS="votes-down"><SPAN CLASS="value-title" TITLE="' . $downvoteshtml . '"></SPAN></SPAN>'; $upvoteshtml = '<SPAN CLASS="votes-up">' . $upvoteshtml . '</SPAN>'; $downvoteshtml = '<SPAN CLASS="votes-down">' . $downvoteshtml . '</SPAN>'; } // Pass information on vote viewing // $voteview will be one of: updown, net, updown-disabled-level, net-disabled-level, updown-disabled-page, net-disabled-page $fields['vote_view'] = substr($voteview, 0, 6) == 'updown' ? 'updown' : 'net'; $fields['upvotes_view'] = $upvotes == 1 ? qa_lang_html_sub_split('main/1_liked', $upvoteshtml, '1') : qa_lang_html_sub_split('main/x_liked', $upvoteshtml); $fields['downvotes_view'] = $downvotes == 1 ? qa_lang_html_sub_split('main/1_disliked', $downvoteshtml, '1') : qa_lang_html_sub_split('main/x_disliked', $downvoteshtml); $fields['netvotes_view'] = abs($netvotes) == 1 ? qa_lang_html_sub_split('main/1_vote', $netvoteshtml, '1') : qa_lang_html_sub_split('main/x_votes', $netvoteshtml); // Voting buttons $fields['vote_tags'] = 'ID="voting_' . qa_html($postid) . '"'; $onclick = 'onClick="return qa_vote_click(this);"'; if ($fields['hidden']) { $fields['vote_state'] = 'disabled'; $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html($isanswer ? 'main/vote_disabled_hidden_a' : 'main/vote_disabled_hidden_q') . '"'; $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif ($isbyuser) { $fields['vote_state'] = 'disabled'; $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html($isanswer ? 'main/vote_disabled_my_a' : 'main/vote_disabled_my_q') . '"'; $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif (strpos($voteview, '-disabled-')) { $fields['vote_state'] = @$post['uservote'] > 0 ? 'voted_up_disabled' : (@$post['uservote'] < 0 ? 'voted_down_disabled' : 'disabled'); if (strpos($voteview, '-disabled-page')) { $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_disabled_q_page_only') . '"'; } else { $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_disabled_level') . '"'; } $fields['vote_down_tags'] = $fields['vote_up_tags']; } elseif (@$post['uservote'] > 0) { $fields['vote_state'] = 'voted_up'; $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/voted_up_popup') . '" NAME="' . qa_html('vote_' . $postid . '_0_' . $anchor) . '"' . $onclick; $fields['vote_down_tags'] = ' '; } elseif (@$post['uservote'] < 0) { $fields['vote_state'] = 'voted_down'; $fields['vote_up_tags'] = ' '; $fields['vote_down_tags'] = 'TITLE="' . qa_lang_html('main/voted_down_popup') . '" NAME="' . qa_html('vote_' . $postid . '_0_' . $anchor) . '" ' . $onclick; } else { $fields['vote_state'] = 'enabled'; $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_up_popup') . '" NAME="' . qa_html('vote_' . $postid . '_1_' . $anchor) . '" ' . $onclick; $fields['vote_down_tags'] = 'TITLE="' . qa_lang_html('main/vote_down_popup') . '" NAME="' . qa_html('vote_' . $postid . '_-1_' . $anchor) . '" ' . $onclick; } } // Flag count if (@$options['flagsview'] && @$post['flagcount']) { $fields['flags'] = $post['flagcount'] == 1 ? qa_lang_html_sub_split('main/1_flag', '1', '1') : qa_lang_html_sub_split('main/x_flags', $post['flagcount']); } // Created when and by whom $fields['meta_order'] = qa_lang_html('main/meta_order'); // sets ordering of meta elements which can be language-specific $fields['what'] = qa_lang_html($isquestion ? 'main/asked' : ($isanswer ? 'main/answered' : 'main/commented')); if (@$options['whatlink'] && !$isquestion) { $fields['what_url'] = '#' . qa_html(urlencode($anchor)); } if (isset($post['created']) && @$options['whenview']) { $whenhtml = qa_html(qa_time_to_string(qa_opt('db_time') - $post['created'])); if ($microformats) { $whenhtml = '<SPAN CLASS="published"><SPAN CLASS="value-title" TITLE="' . gmdate('Y-m-d\\TH:i:sO', $post['created']) . '"></SPAN>' . $whenhtml . '</SPAN>'; } $fields['when'] = qa_lang_html_sub_split('main/x_ago', $whenhtml); } if (@$options['whoview']) { $fields['who'] = qa_who_to_html($isbyuser, @$post['userid'], $usershtml, @$options['ipview'] ? @$post['createip'] : null, $microformats); if (isset($post['points'])) { if (@$options['pointsview']) { $fields['who']['points'] = $post['points'] == 1 ? qa_lang_html_sub_split('main/1_point', '1', '1') : qa_lang_html_sub_split('main/x_points', qa_html(number_format($post['points']))); } if (isset($options['pointstitle'])) { $fields['who']['title'] = qa_get_points_title_html($post['points'], $options['pointstitle']); } } if (isset($post['level'])) { $fields['who']['level'] = qa_html(qa_user_level_string($post['level'])); } } if (!QA_FINAL_EXTERNAL_USERS && @$options['avatarsize'] > 0) { $fields['avatar'] = qa_get_user_avatar_html($post['flags'], $post['email'], $post['handle'], $post['avatarblobid'], $post['avatarwidth'], $post['avatarheight'], $options['avatarsize']); } // Updated when and by whom if (isset($post['updated']) && (!isset($post['created']) || $post['hidden'] || abs($post['updated'] - $post['created']) > 300 || $post['lastuserid'] != $post['userid'])) { if (@$options['whenview']) { $whenhtml = qa_html(qa_time_to_string(qa_opt('db_time') - $post['updated'])); if ($microformats) { $whenhtml = '<SPAN CLASS="updated"><SPAN CLASS="value-title" TITLE="' . gmdate('Y-m-d\\TH:i:sO', $post['updated']) . '"></SPAN>' . $whenhtml . '</SPAN>'; } $fields['when_2'] = qa_lang_html_sub_split($fields['hidden'] ? 'question/hidden_x_ago' : 'question/edited_x_ago', $whenhtml); } else { $fields['when_2']['prefix'] = qa_lang_html($fields['hidden'] ? 'question/hidden' : 'main/edited'); } if ($fields['hidden'] && $post['flagcount'] && !isset($post['lastuserid'])) { } else { $fields['who_2'] = qa_who_to_html(isset($userid) && $post['lastuserid'] == $userid, $post['lastuserid'], $usershtml, @$options['ipview'] ? $post['lastip'] : null, false); } } // That's it! return $fields; }
function get_html($content, $format, $options) { if ($format == 'html') { $html = qa_sanitize_html($content, @$options['linksnewwindow']); // sanitize again for display, for extra safety, and due to new window setting if (isset($options['blockwordspreg'])) { // filtering out blocked words inline within HTML is pretty complex, e.g. p<B>oo</B>p must be caught require_once QA_INCLUDE_DIR . 'qa-util-string.php'; $html = preg_replace('/<\\s*(' . $this->htmllineseparators . ')[^A-Za-z0-9]/i', "\n\\0", $html); // tags to single new line $html = preg_replace('/<\\s*(' . $this->htmlparagraphseparators . ')[^A-Za-z0-9]/i', "\n\n\\0", $html); // tags to double new line preg_match_all('/<[^>]*>/', $html, $pregmatches, PREG_OFFSET_CAPTURE); // find tag positions and lengths $tagmatches = $pregmatches[0]; $text = preg_replace('/<[^>]*>/', '', $html); // effectively strip_tags() but use same regexp as above to ensure consistency $blockmatches = qa_block_words_match_all($text, $options['blockwordspreg']); // search for blocked words within text $nexttagmatch = array_shift($tagmatches); $texttohtml = 0; $htmlshift = 0; foreach ($blockmatches as $textoffset => $textlength) { while (isset($nexttagmatch) && $nexttagmatch[1] <= $textoffset + $texttohtml) { // keep text and html in sync $texttohtml += strlen($nexttagmatch[0]); $nexttagmatch = array_shift($tagmatches); } while (1) { $replacepart = $textlength; if (isset($nexttagmatch)) { $replacepart = min($replacepart, $nexttagmatch[1] - ($textoffset + $texttohtml)); } // stop replacing early if we hit an HTML tag $replacelength = qa_strlen(substr($text, $textoffset, $replacepart)); // to work with multi-byte characters $html = substr_replace($html, str_repeat('*', $replacelength), $textoffset + $texttohtml + $htmlshift, $replacepart); $htmlshift += $replacelength - $replacepart; // HTML might have moved around if we replaced multi-byte characters if ($replacepart >= $textlength) { break; } // we have replaced everything expected, otherwise more left (due to hitting an HTML tag) $textlength -= $replacepart; $textoffset += $replacepart; $texttohtml += strlen($nexttagmatch[0]); $nexttagmatch = array_shift($tagmatches); } } } } else { if (isset($options['blockwordspreg'])) { require_once QA_INCLUDE_DIR . 'qa-util-string.php'; $content = qa_block_words_replace($content, $options['blockwordspreg']); } $html = qa_html($content, true); if (@$options['showurllinks']) { require_once QA_INCLUDE_DIR . 'qa-app-format.php'; $html = qa_html_convert_urls($html, qa_opt('links_in_new_window')); } } return $html; }