aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/adm/style/acp_forums.html4
-rw-r--r--phpBB/adm/style/acp_users_signature.html2
-rw-r--r--phpBB/assets/javascript/core.js159
-rw-r--r--phpBB/config/feed.yml98
-rw-r--r--phpBB/config/services.yml1
-rw-r--r--phpBB/download/file.php2
-rw-r--r--phpBB/feed.php1180
-rw-r--r--phpBB/includes/acp/acp_groups.php2
-rw-r--r--phpBB/includes/feed/base.php259
-rw-r--r--phpBB/includes/feed/factory.php129
-rw-r--r--phpBB/includes/feed/forum.php147
-rw-r--r--phpBB/includes/feed/forums.php72
-rw-r--r--phpBB/includes/feed/helper.php159
-rw-r--r--phpBB/includes/feed/news.php112
-rw-r--r--phpBB/includes/feed/overall.php97
-rw-r--r--phpBB/includes/feed/post_base.php57
-rw-r--r--phpBB/includes/feed/topic.php116
-rw-r--r--phpBB/includes/feed/topic_base.php59
-rw-r--r--phpBB/includes/feed/topics.php91
-rw-r--r--phpBB/includes/feed/topics_active.php136
-rw-r--r--phpBB/includes/functions_download.php33
-rw-r--r--phpBB/includes/functions_user.php2
-rw-r--r--phpBB/includes/search/fulltext_mysql.php11
-rw-r--r--phpBB/includes/ucp/ucp_groups.php19
-rw-r--r--phpBB/install/install_update.php4
-rw-r--r--phpBB/language/en/acp/search.php2
-rw-r--r--phpBB/styles/prosilver/template/editor.js77
-rw-r--r--phpBB/styles/prosilver/theme/common.css19
-rw-r--r--phpBB/styles/prosilver/theme/tweaks.css19
-rw-r--r--phpBB/styles/subsilver2/template/editor.js1
30 files changed, 1797 insertions, 1272 deletions
diff --git a/phpBB/adm/style/acp_forums.html b/phpBB/adm/style/acp_forums.html
index c3772a22e3..38369ee207 100644
--- a/phpBB/adm/style/acp_forums.html
+++ b/phpBB/adm/style/acp_forums.html
@@ -152,7 +152,7 @@
</dl>
<dl>
<dt><label for="forum_desc">{L_FORUM_DESC}{L_COLON}</label><br /><span>{L_FORUM_DESC_EXPLAIN}</span></dt>
- <dd><textarea id="forum_desc" name="forum_desc" rows="5" cols="45">{FORUM_DESC}</textarea></dd>
+ <dd><textarea id="forum_desc" name="forum_desc" rows="5" cols="45" data-bbcode="true">{FORUM_DESC}</textarea></dd>
<dd><label><input type="checkbox" class="radio" name="desc_parse_bbcode"<!-- IF S_DESC_BBCODE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_BBCODE}</label>
<label><input type="checkbox" class="radio" name="desc_parse_smilies"<!-- IF S_DESC_SMILIES_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_SMILIES}</label>
<label><input type="checkbox" class="radio" name="desc_parse_urls"<!-- IF S_DESC_URLS_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_URLS}</label></dd>
@@ -316,7 +316,7 @@
<!-- ENDIF -->
<dl>
<dt><label for="forum_rules">{L_FORUM_RULES}{L_COLON}</label><br /><span>{L_FORUM_RULES_EXPLAIN}</span></dt>
- <dd><textarea id="forum_rules" name="forum_rules" rows="4" cols="70">{FORUM_RULES_PLAIN}</textarea></dd>
+ <dd><textarea id="forum_rules" name="forum_rules" rows="4" cols="70" data-bbcode="true">{FORUM_RULES_PLAIN}</textarea></dd>
<dd><label><input type="checkbox" class="radio" name="rules_parse_bbcode"<!-- IF S_BBCODE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_BBCODE}</label>
<label><input type="checkbox" class="radio" name="rules_parse_smilies"<!-- IF S_SMILIES_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_SMILIES}</label>
<label><input type="checkbox" class="radio" name="rules_parse_urls"<!-- IF S_URLS_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_URLS}</label></dd>
diff --git a/phpBB/adm/style/acp_users_signature.html b/phpBB/adm/style/acp_users_signature.html
index c9cc053eec..2b4964803e 100644
--- a/phpBB/adm/style/acp_users_signature.html
+++ b/phpBB/adm/style/acp_users_signature.html
@@ -92,7 +92,7 @@
// ]]>
</script>
</dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 90px;"><textarea name="signature" rows="10" cols="60" style="width: 95%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();">{SIGNATURE}</textarea></dd>
+ <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 90px;"><textarea name="signature" rows="10" cols="60" style="width: 95%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();" data-bbcode="true">{SIGNATURE}</textarea></dd>
<dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 90px; margin-top: 5px;">
<!-- IF S_BBCODE_ALLOWED -->
<label><input type="checkbox" class="radio" name="disable_bbcode"{S_BBCODE_CHECKED} /> {L_DISABLE_BBCODE}</label>
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js
index e0f1dc1eef..cdba6f9d26 100644
--- a/phpBB/assets/javascript/core.js
+++ b/phpBB/assets/javascript/core.js
@@ -678,5 +678,164 @@ phpbb.resizeTextArea = function(items, options) {
});
};
+/**
+* Check if cursor in textarea is currently inside a bbcode tag
+*
+* @param {object} textarea Textarea DOM object
+* @param {Array} startTags List of start tags to look for
+* For example, Array('[code]', '[code=')
+* @param {Array} endTags List of end tags to look for
+* For example, Array('[/code]')
+*
+* @return {boolean} True if cursor is in bbcode tag
+*/
+phpbb.inBBCodeTag = function(textarea, startTags, endTags) {
+ var start = textarea.selectionStart,
+ lastEnd = -1,
+ lastStart = -1,
+ i, index, value;
+
+ if (typeof start !== 'number') {
+ return false;
+ }
+
+ value = textarea.value.toLowerCase();
+
+ for (i = 0; i < startTags.length; i++) {
+ var tagLength = startTags[i].length;
+ if (start >= tagLength) {
+ index = value.lastIndexOf(startTags[i], start - tagLength);
+ lastStart = Math.max(lastStart, index);
+ }
+ }
+ if (lastStart == -1) return false;
+
+ if (start > 0) {
+ for (i = 0; i < endTags.length; i++) {
+ index = value.lastIndexOf(endTags[i], start - 1);
+ lastEnd = Math.max(lastEnd, index);
+ }
+ }
+
+ return (lastEnd < lastStart);
+}
+
+
+/**
+* Adjust textarea to manage code bbcode
+*
+* This function allows to use tab characters when typing code
+* and keeps indentation of previous line of code when adding new
+* line while typing code.
+*
+* Editor's functionality is changed only when cursor is between
+* [code] and [/code] bbcode tags.
+*
+* @param {object} textarea Textarea DOM object to apply editor to
+*/
+phpbb.applyCodeEditor = function(textarea) {
+ // list of allowed start and end bbcode code tags, in lower case
+ var startTags = ['[code]', '[code='],
+ startTagsEnd = ']',
+ endTags = ['[/code]'];
+
+ if (!textarea || typeof textarea.selectionStart !== 'number') {
+ return;
+ }
+
+ if ($(textarea).data('code-editor') === true) {
+ return;
+ }
+
+ function inTag() {
+ return phpbb.inBBCodeTag(textarea, startTags, endTags);
+ }
+
+ /**
+ * Get line of text before cursor
+ *
+ * @param {boolean} stripCodeStart If true, only part of line
+ * after [code] tag will be returned.
+ *
+ * @return {string} Line of text
+ */
+ function getLastLine(stripCodeStart) {
+ var start = textarea.selectionStart,
+ value = textarea.value,
+ index = value.lastIndexOf("\n", start - 1);
+
+ value = value.substring(index + 1, start);
+
+ if (stripCodeStart) {
+ for (var i = 0; i < startTags.length; i++) {
+ index = value.lastIndexOf(startTags[i]);
+ if (index >= 0) {
+ var tagLength = startTags[i].length;
+
+ value = value.substring(index + tagLength);
+ if (startTags[i].lastIndexOf(startTagsEnd) != tagLength) {
+ index = value.indexOf(startTagsEnd);
+
+ if (index >= 0) {
+ value = value.substr(index + 1);
+ }
+ }
+ }
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Append text at cursor position
+ *
+ * @param {string} Text Text to append
+ */
+ function appendText(text) {
+ var start = textarea.selectionStart,
+ end = textarea.selectionEnd,
+ value = textarea.value;
+
+ textarea.value = value.substr(0, start) + text + value.substr(end);
+ textarea.selectionStart = textarea.selectionEnd = start + text.length;
+ }
+
+ $(textarea).data('code-editor', true).on('keydown', function(event) {
+ var key = event.keyCode || event.which;
+
+ // intercept tabs
+ if (key == 9) {
+ if (inTag()) {
+ appendText("\t");
+ event.preventDefault();
+ return;
+ }
+ }
+
+ // intercept new line characters
+ if (key == 13) {
+ if (inTag()) {
+ var lastLine = getLastLine(true),
+ code = '' + /^\s*/g.exec(lastLine);
+
+ if (code.length > 0) {
+ appendText("\n" + code);
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ });
+};
+
+/**
+* Apply code editor to all textarea elements with data-bbcode attribute
+*/
+$(document).ready(function() {
+ $('textarea[data-bbcode]').each(function() {
+ phpbb.applyCodeEditor(this);
+ });
+});
})(jQuery); // Avoid conflicts with other libraries
diff --git a/phpBB/config/feed.yml b/phpBB/config/feed.yml
new file mode 100644
index 0000000000..59eeafd458
--- /dev/null
+++ b/phpBB/config/feed.yml
@@ -0,0 +1,98 @@
+services:
+ feed.helper:
+ class: phpbb_feed_helper
+ arguments:
+ - @config
+ - @user
+ - %core.root_path%
+
+ feed.factory:
+ class: phpbb_feed_factory
+ arguments:
+ - @service_container
+ - @config
+ - @dbal.conn
+
+ feed.forum:
+ class: phpbb_feed_forum
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.forums:
+ class: phpbb_feed_forums
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.news:
+ class: phpbb_feed_news
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.overall:
+ class: phpbb_feed_overall
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.topic:
+ class: phpbb_feed_topic
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.topics:
+ class: phpbb_feed_topics
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
+
+ feed.topics_active:
+ class: phpbb_feed_topics_active
+ scope: prototype
+ arguments:
+ - @feed.helper
+ - @config
+ - @dbal.conn
+ - @cache.driver
+ - @user
+ - @auth
+ - %core.php_ext%
diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml
index 7a0fddf0c1..bb96953bcf 100644
--- a/phpBB/config/services.yml
+++ b/phpBB/config/services.yml
@@ -4,6 +4,7 @@ imports:
- { resource: notifications.yml }
- { resource: migrator.yml }
- { resource: avatars.yml }
+ - { resource: feed.yml }
services:
auth:
diff --git a/phpBB/download/file.php b/phpBB/download/file.php
index eee2090da0..cf7128b25b 100644
--- a/phpBB/download/file.php
+++ b/phpBB/download/file.php
@@ -279,7 +279,7 @@ else if ($download_id)
phpbb_increment_downloads($db, $attachment['attach_id']);
}
- if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && ((strpos(strtolower($user->browser), 'msie') !== false) && (strpos(strtolower($user->browser), 'msie 8.0') === false)))
+ if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && (strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7))
{
wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']);
file_gc();
diff --git a/phpBB/feed.php b/phpBB/feed.php
index 0dce22fb0c..35cd7fda3f 100644
--- a/phpBB/feed.php
+++ b/phpBB/feed.php
@@ -59,10 +59,12 @@ if ($forum_id || $topic_id || $mode)
}
// This boards URL
-$board_url = generate_board_url();
+$phpbb_feed_helper = $phpbb_container->get('feed.helper');
+$board_url = $phpbb_feed_helper->get_board_url();
// Get correct feed object
-$feed = phpbb_feed_factory::init($mode, $forum_id, $topic_id);
+$phpbb_feed_factory = $phpbb_container->get('feed.factory');
+$feed = $phpbb_feed_factory->get_feed($mode, $forum_id, $topic_id);
// No feed found
if ($feed === false)
@@ -99,13 +101,13 @@ while ($row = $feed->get_item())
$item_row = array(
'author' => ($feed->get('creator') !== NULL) ? $row[$feed->get('creator')] : '',
- 'published' => ($published > 0) ? feed_format_date($published) : '',
- 'updated' => ($updated > 0) ? feed_format_date($updated) : '',
+ 'published' => ($published > 0) ? $phpbb_feed_helper->format_date($published) : '',
+ 'updated' => ($updated > 0) ? $phpbb_feed_helper->format_date($updated) : '',
'link' => '',
'title' => censor_text($title),
'category' => ($config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $phpEx . '?f=' . $row['forum_id'] : '',
'category_name' => ($config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '',
- 'description' => censor_text(feed_generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options)),
+ 'description' => censor_text($phpbb_feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options)),
'statistics' => '',
);
@@ -127,11 +129,11 @@ if (!$feed_updated_time)
// FEED_IMAGE is not used (atom)
$global_vars = array_merge($global_vars, array(
'FEED_IMAGE' => '',
- 'SELF_LINK' => feed_append_sid('/feed.' . $phpEx, $params),
+ 'SELF_LINK' => $phpbb_feed_helper->append_sid('feed.' . $phpEx, $params),
'FEED_LINK' => $board_url . '/index.' . $phpEx,
'FEED_TITLE' => $config['sitename'],
'FEED_SUBTITLE' => $config['site_desc'],
- 'FEED_UPDATED' => feed_format_date($feed_updated_time),
+ 'FEED_UPDATED' => $phpbb_feed_helper->format_date($feed_updated_time),
'FEED_LANG' => $user->lang['USER_LANG'],
'FEED_AUTHOR' => $config['sitename'],
));
@@ -231,1167 +233,3 @@ echo '</feed>';
garbage_collection();
exit_handler();
-
-/**
-* Run links through append_sid(), prepend generate_board_url() and remove session id
-**/
-function feed_append_sid($url, $params)
-{
- global $board_url;
-
- return append_sid($board_url . $url, $params, true, '');
-}
-
-/**
-* Generate ISO 8601 date string (RFC 3339)
-**/
-function feed_format_date($time)
-{
- static $zone_offset;
- static $offset_string;
-
- if (empty($offset_string))
- {
- global $user;
-
- $zone_offset = $user->create_datetime()->getOffset();
- $offset_string = phpbb_format_timezone_offset($zone_offset);
- }
-
- return gmdate("Y-m-d\TH:i:s", $time + $zone_offset) . $offset_string;
-}
-
-/**
-* Generate text content
-**/
-function feed_generate_content($content, $uid, $bitfield, $options)
-{
- global $user, $config, $phpbb_root_path, $phpEx, $board_url;
-
- if (empty($content))
- {
- return '';
- }
-
- // Prepare some bbcodes for better parsing
- $content = preg_replace("#\[quote(=&quot;.*?&quot;)?:$uid\]\s*(.*?)\s*\[/quote:$uid\]#si", "[quote$1:$uid]<br />$2<br />[/quote:$uid]", $content);
-
- $content = generate_text_for_display($content, $uid, $bitfield, $options);
-
- // Add newlines
- $content = str_replace('<br />', '<br />' . "\n", $content);
-
- // Convert smiley Relative paths to Absolute path, Windows style
- $content = str_replace($phpbb_root_path . $config['smilies_path'], $board_url . '/' . $config['smilies_path'], $content);
-
- // Remove "Select all" link and mouse events
- $content = str_replace('<a href="#" onclick="selectCode(this); return false;">' . $user->lang['SELECT_ALL_CODE'] . '</a>', '', $content);
- $content = preg_replace('#(onkeypress|onclick)="(.*?)"#si', '', $content);
-
- // Firefox does not support CSS for feeds, though
-
- // Remove font sizes
-// $content = preg_replace('#<span style="font-size: [0-9]+%; line-height: [0-9]+%;">([^>]+)</span>#iU', '\1', $content);
-
- // Make text strong :P
-// $content = preg_replace('#<span style="font-weight: bold?">(.*?)</span>#iU', '<strong>\1</strong>', $content);
-
- // Italic
-// $content = preg_replace('#<span style="font-style: italic?">([^<]+)</span>#iU', '<em>\1</em>', $content);
-
- // Underline
-// $content = preg_replace('#<span style="text-decoration: underline?">([^<]+)</span>#iU', '<u>\1</u>', $content);
-
- // Remove embed Windows Media Streams
- $content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--<!\[endif\]-->#si', '', $content);
-
- // Do not use &lt; and &gt;, because we want to retain code contained in [code][/code]
-
- // Remove embed and objects
- $content = preg_replace( '#<(object|embed)(.*?) (value|src)=(.*?) ([^[]+)(object|embed)>#si',' <a href=$4 target="_blank"><strong>$1</strong></a> ',$content);
-
- // Remove some specials html tag, because somewhere there are a mod to allow html tags ;)
- $content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', ' <strong>$1</strong> ', $content);
-
- // Remove Comments from inline attachments [ia]
- $content = preg_replace('#<div class="(inline-attachment|attachtitle)">(.*?)<!-- ia(.*?) -->(.*?)<!-- ia(.*?) -->(.*?)</div>#si','$4',$content);
-
- // Replace some entities with their unicode counterpart
- $entities = array(
- '&nbsp;' => "\xC2\xA0",
- '&bull;' => "\xE2\x80\xA2",
- '&middot;' => "\xC2\xB7",
- '&copy;' => "\xC2\xA9",
- );
-
- $content = str_replace(array_keys($entities), array_values($entities), $content);
-
- // Remove CDATA blocks. ;)
- $content = preg_replace('#\<\!\[CDATA\[(.*?)\]\]\>#s', '', $content);
-
- // Other control characters
- $content = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $content);
-
- return $content;
-}
-
-/**
-* Factory class to return correct object
-* @package phpBB3
-*/
-class phpbb_feed_factory
-{
- /**
- * Return correct object for specified mode
- *
- * @param string $mode The feeds mode.
- * @param int $forum_id Forum id specified by the script if forum feed provided.
- * @param int $topic_id Topic id specified by the script if topic feed provided.
- *
- * @return object Returns correct feeds object for specified mode.
- */
- function init($mode, $forum_id, $topic_id)
- {
- global $config;
-
- switch ($mode)
- {
- case 'forums':
- if (!$config['feed_overall_forums'])
- {
- return false;
- }
-
- return new phpbb_feed_forums();
- break;
-
- case 'topics':
- case 'topics_new':
- if (!$config['feed_topics_new'])
- {
- return false;
- }
-
- return new phpbb_feed_topics();
- break;
-
- case 'topics_active':
- if (!$config['feed_topics_active'])
- {
- return false;
- }
-
- return new phpbb_feed_topics_active();
- break;
-
- case 'news':
- global $db;
-
- // Get at least one news forum
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE . '
- WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
- $result = $db->sql_query_limit($sql, 1, 0, 600);
- $s_feed_news = (int) $db->sql_fetchfield('forum_id');
- $db->sql_freeresult($result);
-
- if (!$s_feed_news)
- {
- return false;
- }
-
- return new phpbb_feed_news();
- break;
-
- default:
- if ($topic_id && $config['feed_topic'])
- {
- return new phpbb_feed_topic($topic_id);
- }
- else if ($forum_id && $config['feed_forum'])
- {
- return new phpbb_feed_forum($forum_id);
- }
- else if ($config['feed_overall'])
- {
- return new phpbb_feed_overall();
- }
-
- return false;
- break;
- }
- }
-}
-
-/**
-* Base class with some generic functions and settings.
-*
-* @package phpBB3
-*/
-class phpbb_feed_base
-{
- /**
- * SQL Query to be executed to get feed items
- */
- var $sql = array();
-
- /**
- * Keys specified for retrieval of title, content, etc.
- */
- var $keys = array();
-
- /**
- * Number of items to fetch. Usually overwritten by $config['feed_something']
- */
- var $num_items = 15;
-
- /**
- * Separator for title elements to separate items (for example forum / topic)
- */
- var $separator = "\xE2\x80\xA2"; // &bull;
-
- /**
- * Separator for the statistics row (Posted by, post date, replies, etc.)
- */
- var $separator_stats = "\xE2\x80\x94"; // &mdash;
-
- /**
- * Constructor
- */
- function phpbb_feed_base()
- {
- global $config;
-
- $this->set_keys();
-
- // Allow num_items to be string
- if (is_string($this->num_items))
- {
- $this->num_items = (int) $config[$this->num_items];
-
- // A precaution
- if (!$this->num_items)
- {
- $this->num_items = 10;
- }
- }
- }
-
- /**
- * Set keys.
- */
- function set_keys()
- {
- }
-
- /**
- * Open feed
- */
- function open()
- {
- }
-
- /**
- * Close feed
- */
- function close()
- {
- global $db;
-
- if (!empty($this->result))
- {
- $db->sql_freeresult($this->result);
- }
- }
-
- /**
- * Set key
- */
- function set($key, $value)
- {
- $this->keys[$key] = $value;
- }
-
- /**
- * Get key
- */
- function get($key)
- {
- return (isset($this->keys[$key])) ? $this->keys[$key] : NULL;
- }
-
- function get_readable_forums()
- {
- global $auth;
- static $forum_ids;
-
- if (!isset($forum_ids))
- {
- $forum_ids = array_keys($auth->acl_getf('f_read', true));
- }
-
- return $forum_ids;
- }
-
- function get_moderator_approve_forums()
- {
- global $auth;
- static $forum_ids;
-
- if (!isset($forum_ids))
- {
- $forum_ids = array_keys($auth->acl_getf('m_approve', true));
- }
-
- return $forum_ids;
- }
-
- function is_moderator_approve_forum($forum_id)
- {
- static $forum_ids;
-
- if (!isset($forum_ids))
- {
- $forum_ids = array_flip($this->get_moderator_approve_forums());
- }
-
- return (isset($forum_ids[$forum_id])) ? true : false;
- }
-
- function get_excluded_forums()
- {
- global $db, $cache;
- static $forum_ids;
-
- // Matches acp/acp_board.php
- $cache_name = 'feed_excluded_forum_ids';
-
- if (!isset($forum_ids) && ($forum_ids = $cache->get('_' . $cache_name)) === false)
- {
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE . '
- WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '<> 0');
- $result = $db->sql_query($sql);
-
- $forum_ids = array();
- while ($forum_id = (int) $db->sql_fetchfield('forum_id'))
- {
- $forum_ids[$forum_id] = $forum_id;
- }
- $db->sql_freeresult($result);
-
- $cache->put('_' . $cache_name, $forum_ids);
- }
-
- return $forum_ids;
- }
-
- function is_excluded_forum($forum_id)
- {
- $forum_ids = $this->get_excluded_forums();
-
- return isset($forum_ids[$forum_id]) ? true : false;
- }
-
- function get_passworded_forums()
- {
- global $user;
-
- return $user->get_passworded_forums();
- }
-
- function get_item()
- {
- global $db, $cache;
- static $result;
-
- if (!isset($result))
- {
- if (!$this->get_sql())
- {
- return false;
- }
-
- // Query database
- $sql = $db->sql_build_query('SELECT', $this->sql);
- $result = $db->sql_query_limit($sql, $this->num_items);
- }
-
- return $db->sql_fetchrow($result);
- }
-
- function user_viewprofile($row)
- {
- global $phpEx, $user;
-
- $author_id = (int) $row[$this->get('author_id')];
-
- if ($author_id == ANONYMOUS)
- {
- // Since we cannot link to a profile, we just return GUEST
- // instead of $row['username']
- return $user->lang['GUEST'];
- }
-
- return '<a href="' . feed_append_sid('/memberlist.' . $phpEx, 'mode=viewprofile&amp;u=' . $author_id) . '">' . $row[$this->get('creator')] . '</a>';
- }
-}
-
-/**
-* Abstract class for post based feeds
-*
-* @package phpBB3
-*/
-class phpbb_feed_post_base extends phpbb_feed_base
-{
- var $num_items = 'feed_limit_post';
-
- function set_keys()
- {
- $this->set('title', 'post_subject');
- $this->set('title2', 'topic_title');
-
- $this->set('author_id', 'user_id');
- $this->set('creator', 'username');
- $this->set('published', 'post_time');
- $this->set('updated', 'post_edit_time');
- $this->set('text', 'post_text');
-
- $this->set('bitfield', 'bbcode_bitfield');
- $this->set('bbcode_uid','bbcode_uid');
-
- $this->set('enable_bbcode', 'enable_bbcode');
- $this->set('enable_smilies', 'enable_smilies');
- $this->set('enable_magic_url', 'enable_magic_url');
- }
-
- function adjust_item(&$item_row, &$row)
- {
- global $phpEx, $config, $user;
-
- $item_row['link'] = feed_append_sid('/viewtopic.' . $phpEx, "t={$row['topic_id']}&amp;p={$row['post_id']}#p{$row['post_id']}");
-
- if ($config['feed_item_statistics'])
- {
- $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
- . ' ' . $this->separator_stats . ' ' . $user->format_date($row[$this->get('published')])
- . (($this->is_moderator_approve_forum($row['forum_id']) && !$row['post_approved']) ? ' ' . $this->separator_stats . ' ' . $user->lang['POST_UNAPPROVED'] : '');
- }
- }
-}
-
-/**
-* Abstract class for topic based feeds
-*
-* @package phpBB3
-*/
-class phpbb_feed_topic_base extends phpbb_feed_base
-{
- var $num_items = 'feed_limit_topic';
-
- function set_keys()
- {
- $this->set('title', 'topic_title');
- $this->set('title2', 'forum_name');
-
- $this->set('author_id', 'topic_poster');
- $this->set('creator', 'topic_first_poster_name');
- $this->set('published', 'post_time');
- $this->set('updated', 'post_edit_time');
- $this->set('text', 'post_text');
-
- $this->set('bitfield', 'bbcode_bitfield');
- $this->set('bbcode_uid','bbcode_uid');
-
- $this->set('enable_bbcode', 'enable_bbcode');
- $this->set('enable_smilies', 'enable_smilies');
- $this->set('enable_magic_url', 'enable_magic_url');
- }
-
- function adjust_item(&$item_row, &$row)
- {
- global $phpEx, $config, $user;
-
- $item_row['link'] = feed_append_sid('/viewtopic.' . $phpEx, 't=' . $row['topic_id'] . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']);
-
- if ($config['feed_item_statistics'])
- {
- $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
- . ' ' . $this->separator_stats . ' ' . $user->format_date($row[$this->get('published')])
- . ' ' . $this->separator_stats . ' ' . $user->lang['REPLIES'] . ' ' . (($this->is_moderator_approve_forum($row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'])
- . ' ' . $this->separator_stats . ' ' . $user->lang['VIEWS'] . ' ' . $row['topic_views']
- . (($this->is_moderator_approve_forum($row['forum_id']) && ($row['topic_replies_real'] != $row['topic_replies'])) ? ' ' . $this->separator_stats . ' ' . $user->lang['POSTS_UNAPPROVED'] : '');
- }
- }
-}
-
-/**
-* Board wide feed (aka overall feed)
-*
-* This will give you the newest {$this->num_items} posts
-* from the whole board.
-*
-* @package phpBB3
-*/
-class phpbb_feed_overall extends phpbb_feed_post_base
-{
- function get_sql()
- {
- global $auth, $db;
-
- $forum_ids = array_diff($this->get_readable_forums(), $this->get_excluded_forums(), $this->get_passworded_forums());
- if (empty($forum_ids))
- {
- return false;
- }
-
- // m_approve forums
- $fid_m_approve = $this->get_moderator_approve_forums();
- $sql_m_approve = (!empty($fid_m_approve)) ? 'OR ' . $db->sql_in_set('forum_id', $fid_m_approve) : '';
-
- // Determine topics with recent activity
- $sql = 'SELECT topic_id, topic_last_post_time
- FROM ' . TOPICS_TABLE . '
- WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . '
- AND topic_moved_id = 0
- AND (topic_approved = 1
- ' . $sql_m_approve . ')
- ORDER BY topic_last_post_time DESC';
- $result = $db->sql_query_limit($sql, $this->num_items);
-
- $topic_ids = array();
- $min_post_time = 0;
- while ($row = $db->sql_fetchrow())
- {
- $topic_ids[] = (int) $row['topic_id'];
-
- $min_post_time = (int) $row['topic_last_post_time'];
- }
- $db->sql_freeresult($result);
-
- if (empty($topic_ids))
- {
- return false;
- }
-
- // Get the actual data
- $this->sql = array(
- 'SELECT' => 'f.forum_id, f.forum_name, ' .
- 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
- 'u.username, u.user_id',
- 'FROM' => array(
- USERS_TABLE => 'u',
- POSTS_TABLE => 'p',
- ),
- 'LEFT_JOIN' => array(
- array(
- 'FROM' => array(FORUMS_TABLE => 'f'),
- 'ON' => 'f.forum_id = p.forum_id',
- ),
- ),
- 'WHERE' => $db->sql_in_set('p.topic_id', $topic_ids) . '
- AND (p.post_approved = 1
- ' . str_replace('forum_id', 'p.forum_id', $sql_m_approve) . ')
- AND p.post_time >= ' . $min_post_time . '
- AND u.user_id = p.poster_id',
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-
- function adjust_item(&$item_row, &$row)
- {
- parent::adjust_item($item_row, $row);
-
- $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
- }
-}
-
-/**
-* Forum feed
-*
-* This will give you the last {$this->num_items} posts made
-* within a specific forum.
-*
-* @package phpBB3
-*/
-class phpbb_feed_forum extends phpbb_feed_post_base
-{
- var $forum_id = 0;
- var $forum_data = array();
-
- function phpbb_feed_forum($forum_id)
- {
- parent::phpbb_feed_base();
-
- $this->forum_id = (int) $forum_id;
- }
-
- function open()
- {
- global $db, $auth;
-
- // Check if forum exists
- $sql = 'SELECT forum_id, forum_name, forum_password, forum_type, forum_options
- FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . $this->forum_id;
- $result = $db->sql_query($sql);
- $this->forum_data = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (empty($this->forum_data))
- {
- trigger_error('NO_FORUM');
- }
-
- // Forum needs to be postable
- if ($this->forum_data['forum_type'] != FORUM_POST)
- {
- trigger_error('NO_FEED');
- }
-
- // Make sure forum is not excluded from feed
- if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options']))
- {
- trigger_error('NO_FEED');
- }
-
- // Make sure we can read this forum
- if (!$auth->acl_get('f_read', $this->forum_id))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- // Make sure forum is not passworded or user is authed
- if ($this->forum_data['forum_password'])
- {
- $forum_ids_passworded = $this->get_passworded_forums();
-
- if (isset($forum_ids_passworded[$this->forum_id]))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- unset($forum_ids_passworded);
- }
- }
-
- function get_sql()
- {
- global $auth, $db;
-
- $m_approve = ($auth->acl_get('m_approve', $this->forum_id)) ? true : false;
-
- // Determine topics with recent activity
- $sql = 'SELECT topic_id, topic_last_post_time
- FROM ' . TOPICS_TABLE . '
- WHERE forum_id = ' . $this->forum_id . '
- AND topic_moved_id = 0
- ' . ((!$m_approve) ? 'AND topic_approved = 1' : '') . '
- ORDER BY topic_last_post_time DESC';
- $result = $db->sql_query_limit($sql, $this->num_items);
-
- $topic_ids = array();
- $min_post_time = 0;
- while ($row = $db->sql_fetchrow())
- {
- $topic_ids[] = (int) $row['topic_id'];
-
- $min_post_time = (int) $row['topic_last_post_time'];
- }
- $db->sql_freeresult($result);
-
- if (empty($topic_ids))
- {
- return false;
- }
-
- $this->sql = array(
- 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
- 'u.username, u.user_id',
- 'FROM' => array(
- POSTS_TABLE => 'p',
- USERS_TABLE => 'u',
- ),
- 'WHERE' => $db->sql_in_set('p.topic_id', $topic_ids) . '
- ' . ((!$m_approve) ? 'AND p.post_approved = 1' : '') . '
- AND p.post_time >= ' . $min_post_time . '
- AND p.poster_id = u.user_id',
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-
- function adjust_item(&$item_row, &$row)
- {
- parent::adjust_item($item_row, $row);
-
- $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
- }
-
- function get_item()
- {
- return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row;
- }
-}
-
-/**
-* Topic feed for a specific topic
-*
-* This will give you the last {$this->num_items} posts made within this topic.
-*
-* @package phpBB3
-*/
-class phpbb_feed_topic extends phpbb_feed_post_base
-{
- var $topic_id = 0;
- var $forum_id = 0;
- var $topic_data = array();
-
- function phpbb_feed_topic($topic_id)
- {
- parent::phpbb_feed_base();
-
- $this->topic_id = (int) $topic_id;
- }
-
- function open()
- {
- global $auth, $db, $user;
-
- $sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_approved, t.topic_title, t.topic_time, t.topic_views, t.topic_replies, t.topic_type
- FROM ' . TOPICS_TABLE . ' t
- LEFT JOIN ' . FORUMS_TABLE . ' f
- ON (f.forum_id = t.forum_id)
- WHERE t.topic_id = ' . $this->topic_id;
- $result = $db->sql_query($sql);
- $this->topic_data = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (empty($this->topic_data))
- {
- trigger_error('NO_TOPIC');
- }
-
- $this->forum_id = (int) $this->topic_data['forum_id'];
-
- // Make sure topic is either approved or user authed
- if (!$this->topic_data['topic_approved'] && !$auth->acl_get('m_approve', $this->forum_id))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- // Make sure forum is not excluded from feed
- if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options']))
- {
- trigger_error('NO_FEED');
- }
-
- // Make sure we can read this forum
- if (!$auth->acl_get('f_read', $this->forum_id))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- // Make sure forum is not passworded or user is authed
- if ($this->topic_data['forum_password'])
- {
- $forum_ids_passworded = $this->get_passworded_forums();
-
- if (isset($forum_ids_passworded[$this->forum_id]))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- unset($forum_ids_passworded);
- }
- }
-
- function get_sql()
- {
- global $auth, $db;
-
- $this->sql = array(
- 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
- 'u.username, u.user_id',
- 'FROM' => array(
- POSTS_TABLE => 'p',
- USERS_TABLE => 'u',
- ),
- 'WHERE' => 'p.topic_id = ' . $this->topic_id . '
- ' . ($this->forum_id && !$auth->acl_get('m_approve', $this->forum_id) ? 'AND p.post_approved = 1' : '') . '
- AND p.poster_id = u.user_id',
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-
- function get_item()
- {
- return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row;
- }
-}
-
-/**
-* 'All Forums' feed
-*
-* This will give you a list of all postable forums where feeds are enabled
-* including forum description, topic stats and post stats
-*
-* @package phpBB3
-*/
-class phpbb_feed_forums extends phpbb_feed_base
-{
- var $num_items = 0;
-
- function set_keys()
- {
- $this->set('title', 'forum_name');
- $this->set('text', 'forum_desc');
- $this->set('bitfield', 'forum_desc_bitfield');
- $this->set('bbcode_uid','forum_desc_uid');
- $this->set('updated', 'forum_last_post_time');
- $this->set('options', 'forum_desc_options');
- }
-
- function get_sql()
- {
- global $auth, $db;
-
- $in_fid_ary = array_diff($this->get_readable_forums(), $this->get_excluded_forums());
- if (empty($in_fid_ary))
- {
- return false;
- }
-
- // Build SQL Query
- $this->sql = array(
- 'SELECT' => 'f.forum_id, f.left_id, f.forum_name, f.forum_last_post_time,
- f.forum_desc, f.forum_desc_bitfield, f.forum_desc_uid, f.forum_desc_options,
- f.forum_topics, f.forum_posts',
- 'FROM' => array(FORUMS_TABLE => 'f'),
- 'WHERE' => 'f.forum_type = ' . FORUM_POST . '
- AND ' . $db->sql_in_set('f.forum_id', $in_fid_ary),
- 'ORDER_BY' => 'f.left_id ASC',
- );
-
- return true;
- }
-
- function adjust_item(&$item_row, &$row)
- {
- global $phpEx, $config;
-
- $item_row['link'] = feed_append_sid('/viewforum.' . $phpEx, 'f=' . $row['forum_id']);
-
- if ($config['feed_item_statistics'])
- {
- global $user;
-
- $item_row['statistics'] = $user->lang('TOTAL_TOPICS', (int) $row['forum_topics'])
- . ' ' . $this->separator_stats . ' ' . $user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts']);
- }
- }
-}
-
-/**
-* News feed
-*
-* This will give you {$this->num_items} first posts
-* of all topics in the selected news forums.
-*
-* @package phpBB3
-*/
-class phpbb_feed_news extends phpbb_feed_topic_base
-{
- function get_news_forums()
- {
- global $db, $cache;
- static $forum_ids;
-
- // Matches acp/acp_board.php
- $cache_name = 'feed_news_forum_ids';
-
- if (!isset($forum_ids) && ($forum_ids = $cache->get('_' . $cache_name)) === false)
- {
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE . '
- WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
- $result = $db->sql_query($sql);
-
- $forum_ids = array();
- while ($forum_id = (int) $db->sql_fetchfield('forum_id'))
- {
- $forum_ids[$forum_id] = $forum_id;
- }
- $db->sql_freeresult($result);
-
- $cache->put('_' . $cache_name, $forum_ids);
- }
-
- return $forum_ids;
- }
-
- function get_sql()
- {
- global $auth, $config, $db;
-
- // Determine forum ids
- $in_fid_ary = array_intersect($this->get_news_forums(), $this->get_readable_forums());
- if (empty($in_fid_ary))
- {
- return false;
- }
-
- $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
- if (empty($in_fid_ary))
- {
- return false;
- }
-
- // We really have to get the post ids first!
- $sql = 'SELECT topic_first_post_id, topic_time
- FROM ' . TOPICS_TABLE . '
- WHERE ' . $db->sql_in_set('forum_id', $in_fid_ary) . '
- AND topic_moved_id = 0
- AND topic_approved = 1
- ORDER BY topic_time DESC';
- $result = $db->sql_query_limit($sql, $this->num_items);
-
- $post_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $post_ids[] = (int) $row['topic_first_post_id'];
- }
- $db->sql_freeresult($result);
-
- if (empty($post_ids))
- {
- return false;
- }
-
- $this->sql = array(
- 'SELECT' => 'f.forum_id, f.forum_name,
- t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
- 'FROM' => array(
- TOPICS_TABLE => 't',
- POSTS_TABLE => 'p',
- ),
- 'LEFT_JOIN' => array(
- array(
- 'FROM' => array(FORUMS_TABLE => 'f'),
- 'ON' => 'p.forum_id = f.forum_id',
- ),
- ),
- 'WHERE' => 'p.topic_id = t.topic_id
- AND ' . $db->sql_in_set('p.post_id', $post_ids),
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-}
-
-/**
-* New Topics feed
-*
-* This will give you the last {$this->num_items} created topics
-* including the first post.
-*
-* @package phpBB3
-*/
-class phpbb_feed_topics extends phpbb_feed_topic_base
-{
- function get_sql()
- {
- global $db, $config;
-
- $forum_ids_read = $this->get_readable_forums();
- if (empty($forum_ids_read))
- {
- return false;
- }
-
- $in_fid_ary = array_diff($forum_ids_read, $this->get_excluded_forums(), $this->get_passworded_forums());
- if (empty($in_fid_ary))
- {
- return false;
- }
-
- // We really have to get the post ids first!
- $sql = 'SELECT topic_first_post_id, topic_time
- FROM ' . TOPICS_TABLE . '
- WHERE ' . $db->sql_in_set('forum_id', $in_fid_ary) . '
- AND topic_moved_id = 0
- AND topic_approved = 1
- ORDER BY topic_time DESC';
- $result = $db->sql_query_limit($sql, $this->num_items);
-
- $post_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $post_ids[] = (int) $row['topic_first_post_id'];
- }
- $db->sql_freeresult($result);
-
- if (empty($post_ids))
- {
- return false;
- }
-
- $this->sql = array(
- 'SELECT' => 'f.forum_id, f.forum_name,
- t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
- 'FROM' => array(
- TOPICS_TABLE => 't',
- POSTS_TABLE => 'p',
- ),
- 'LEFT_JOIN' => array(
- array(
- 'FROM' => array(FORUMS_TABLE => 'f'),
- 'ON' => 'p.forum_id = f.forum_id',
- ),
- ),
- 'WHERE' => 'p.topic_id = t.topic_id
- AND ' . $db->sql_in_set('p.post_id', $post_ids),
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-
- function adjust_item(&$item_row, &$row)
- {
- parent::adjust_item($item_row, $row);
-
- $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
- }
-}
-
-/**
-* Active Topics feed
-*
-* This will give you the last {$this->num_items} topics
-* with replies made withing the last {$this->sort_days} days
-* including the last post.
-*
-* @package phpBB3
-*/
-class phpbb_feed_topics_active extends phpbb_feed_topic_base
-{
- var $sort_days = 7;
-
- function set_keys()
- {
- parent::set_keys();
-
- $this->set('author_id', 'topic_last_poster_id');
- $this->set('creator', 'topic_last_poster_name');
- }
-
- function get_sql()
- {
- global $db, $config;
-
- $forum_ids_read = $this->get_readable_forums();
- if (empty($forum_ids_read))
- {
- return false;
- }
-
- $in_fid_ary = array_intersect($forum_ids_read, $this->get_forum_ids());
- $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
- if (empty($in_fid_ary))
- {
- return false;
- }
-
- // Search for topics in last X days
- $last_post_time_sql = ($this->sort_days) ? ' AND topic_last_post_time > ' . (time() - ($this->sort_days * 24 * 3600)) : '';
-
- // We really have to get the post ids first!
- $sql = 'SELECT topic_last_post_id, topic_last_post_time
- FROM ' . TOPICS_TABLE . '
- WHERE ' . $db->sql_in_set('forum_id', $in_fid_ary) . '
- AND topic_moved_id = 0
- AND topic_approved = 1
- ' . $last_post_time_sql . '
- ORDER BY topic_last_post_time DESC';
- $result = $db->sql_query_limit($sql, $this->num_items);
-
- $post_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $post_ids[] = (int) $row['topic_last_post_id'];
- }
- $db->sql_freeresult($result);
-
- if (empty($post_ids))
- {
- return false;
- }
-
- $this->sql = array(
- 'SELECT' => 'f.forum_id, f.forum_name,
- t.topic_id, t.topic_title, t.topic_replies, t.topic_replies_real, t.topic_views,
- t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time,
- p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
- 'FROM' => array(
- TOPICS_TABLE => 't',
- POSTS_TABLE => 'p',
- ),
- 'LEFT_JOIN' => array(
- array(
- 'FROM' => array(FORUMS_TABLE => 'f'),
- 'ON' => 'p.forum_id = f.forum_id',
- ),
- ),
- 'WHERE' => 'p.topic_id = t.topic_id
- AND ' . $db->sql_in_set('p.post_id', $post_ids),
- 'ORDER_BY' => 'p.post_time DESC',
- );
-
- return true;
- }
-
- function get_forum_ids()
- {
- global $db, $cache;
- static $forum_ids;
-
- $cache_name = 'feed_topic_active_forum_ids';
-
- if (!isset($forum_ids) && ($forum_ids = $cache->get('_' . $cache_name)) === false)
- {
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE . '
- WHERE forum_type = ' . FORUM_POST . '
- AND ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '= 0') . '
- AND ' . $db->sql_bit_and('forum_flags', log(FORUM_FLAG_ACTIVE_TOPICS, 2), '<> 0');
- $result = $db->sql_query($sql);
-
- $forum_ids = array();
- while ($forum_id = (int) $db->sql_fetchfield('forum_id'))
- {
- $forum_ids[$forum_id] = $forum_id;
- }
- $db->sql_freeresult($result);
-
- $cache->put('_' . $cache_name, $forum_ids, 180);
- }
-
- return $forum_ids;
- }
-
- function adjust_item(&$item_row, &$row)
- {
- parent::adjust_item($item_row, $row);
-
- $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
- }
-}
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 847ccfb3cc..c79699d465 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -591,7 +591,7 @@ class acp_groups
$avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true);
- if (!$update)
+ if (isset($phpbb_avatar_manager) && !$update)
{
// Merge any avatar errors into the primary error array
$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
diff --git a/phpBB/includes/feed/base.php b/phpBB/includes/feed/base.php
new file mode 100644
index 0000000000..af28ee8dc8
--- /dev/null
+++ b/phpBB/includes/feed/base.php
@@ -0,0 +1,259 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base class with some generic functions and settings.
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_base
+{
+ /**
+ * Feed helper object
+ * @var phpbb_feed_helper
+ */
+ protected $helper;
+
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_db_driver */
+ protected $db;
+
+ /** @var phpbb_cache_driver_interface */
+ protected $cache;
+
+ /** @var phpbb_user */
+ protected $user;
+
+ /** @var phpbb_auth */
+ protected $auth;
+
+ /** @var string */
+ protected $phpEx;
+
+ /**
+ * SQL Query to be executed to get feed items
+ */
+ var $sql = array();
+
+ /**
+ * Keys specified for retrieval of title, content, etc.
+ */
+ var $keys = array();
+
+ /**
+ * Number of items to fetch. Usually overwritten by $config['feed_something']
+ */
+ var $num_items = 15;
+
+ /**
+ * Separator for title elements to separate items (for example forum / topic)
+ */
+ var $separator = "\xE2\x80\xA2"; // &bull;
+
+ /**
+ * Separator for the statistics row (Posted by, post date, replies, etc.)
+ */
+ var $separator_stats = "\xE2\x80\x94"; // &mdash;
+
+ /**
+ * Constructor
+ *
+ * @param phpbb_feed_helper $helper Feed helper
+ * @param phpbb_config $config Config object
+ * @param phpbb_db_driver $db Database connection
+ * @param phpbb_cache_driver_interface $cache Cache object
+ * @param phpbb_user $user User object
+ * @param phpbb_auth $auth Auth object
+ * @param string $phpEx php file extension
+ * @return null
+ */
+ function __construct(phpbb_feed_helper $helper, phpbb_config $config, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, phpbb_user $user, phpbb_auth $auth, $phpEx)
+ {
+ $this->config = $config;
+ $this->helper = $helper;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->phpEx = $phpEx;
+
+ $this->set_keys();
+
+ // Allow num_items to be string
+ if (is_string($this->num_items))
+ {
+ $this->num_items = (int) $this->config[$this->num_items];
+
+ // A precaution
+ if (!$this->num_items)
+ {
+ $this->num_items = 10;
+ }
+ }
+ }
+
+ /**
+ * Set keys.
+ */
+ function set_keys()
+ {
+ }
+
+ /**
+ * Open feed
+ */
+ function open()
+ {
+ }
+
+ /**
+ * Close feed
+ */
+ function close()
+ {
+ if (!empty($this->result))
+ {
+ $this->db->sql_freeresult($this->result);
+ }
+ }
+
+ /**
+ * Set key
+ */
+ function set($key, $value)
+ {
+ $this->keys[$key] = $value;
+ }
+
+ /**
+ * Get key
+ */
+ function get($key)
+ {
+ return (isset($this->keys[$key])) ? $this->keys[$key] : NULL;
+ }
+
+ function get_readable_forums()
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_keys($this->auth->acl_getf('f_read', true));
+ }
+
+ return $forum_ids;
+ }
+
+ function get_moderator_approve_forums()
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_keys($this->auth->acl_getf('m_approve', true));
+ }
+
+ return $forum_ids;
+ }
+
+ function is_moderator_approve_forum($forum_id)
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_flip($this->get_moderator_approve_forums());
+ }
+
+ return (isset($forum_ids[$forum_id])) ? true : false;
+ }
+
+ function get_excluded_forums()
+ {
+ static $forum_ids;
+
+ // Matches acp/acp_board.php
+ $cache_name = 'feed_excluded_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids);
+ }
+
+ return $forum_ids;
+ }
+
+ function is_excluded_forum($forum_id)
+ {
+ $forum_ids = $this->get_excluded_forums();
+
+ return isset($forum_ids[$forum_id]) ? true : false;
+ }
+
+ function get_passworded_forums()
+ {
+ return $this->user->get_passworded_forums();
+ }
+
+ function get_item()
+ {
+ static $result;
+
+ if (!isset($result))
+ {
+ if (!$this->get_sql())
+ {
+ return false;
+ }
+
+ // Query database
+ $sql = $this->db->sql_build_query('SELECT', $this->sql);
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+ }
+
+ return $this->db->sql_fetchrow($result);
+ }
+
+ function user_viewprofile($row)
+ {
+ $author_id = (int) $row[$this->get('author_id')];
+
+ if ($author_id == ANONYMOUS)
+ {
+ // Since we cannot link to a profile, we just return GUEST
+ // instead of $row['username']
+ return $this->user->lang['GUEST'];
+ }
+
+ return '<a href="' . $this->helper->append_sid('memberlist.' . $this->phpEx, 'mode=viewprofile&amp;u=' . $author_id) . '">' . $row[$this->get('creator')] . '</a>';
+ }
+}
diff --git a/phpBB/includes/feed/factory.php b/phpBB/includes/feed/factory.php
new file mode 100644
index 0000000000..63a1eb8ef0
--- /dev/null
+++ b/phpBB/includes/feed/factory.php
@@ -0,0 +1,129 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Factory class to return correct object
+* @package phpBB3
+*/
+class phpbb_feed_factory
+{
+ /**
+ * Service container object
+ * @var object
+ */
+ protected $container;
+
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_db_driver */
+ protected $db;
+
+ /**
+ * Constructor
+ *
+ * @param objec $container Container object
+ * @param phpbb_config $config Config object
+ * @param phpbb_db_driver $db Database connection
+ * @return null
+ */
+ public function __construct($container, phpbb_config $config, phpbb_db_driver $db)
+ {
+ $this->container = $container;
+ $this->config = $config;
+ $this->db = $db;
+ }
+
+ /**
+ * Return correct object for specified mode
+ *
+ * @param string $mode The feeds mode.
+ * @param int $forum_id Forum id specified by the script if forum feed provided.
+ * @param int $topic_id Topic id specified by the script if topic feed provided.
+ *
+ * @return object Returns correct feeds object for specified mode.
+ */
+ function get_feed($mode, $forum_id, $topic_id)
+ {
+ switch ($mode)
+ {
+ case 'forums':
+ if (!$this->config['feed_overall_forums'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.forums');
+ break;
+
+ case 'topics':
+ case 'topics_new':
+ if (!$this->config['feed_topics_new'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.topics');
+ break;
+
+ case 'topics_active':
+ if (!$this->config['feed_topics_active'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.topics_active');
+ break;
+
+ case 'news':
+ // Get at least one news forum
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $this->db->sql_query_limit($sql, 1, 0, 600);
+ $s_feed_news = (int) $this->db->sql_fetchfield('forum_id');
+ $this->db->sql_freeresult($result);
+
+ if (!$s_feed_news)
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.news');
+ break;
+
+ default:
+ if ($topic_id && $this->config['feed_topic'])
+ {
+ return $this->container->get('feed.topic')
+ ->set_topic_id($topic_id);
+ }
+ else if ($forum_id && $this->config['feed_forum'])
+ {
+ return $this->container->get('feed.forum')
+ ->set_forum_id($forum_id);
+ }
+ else if ($this->config['feed_overall'])
+ {
+ return $this->container->get('feed.overall');
+ }
+
+ return false;
+ break;
+ }
+ }
+}
diff --git a/phpBB/includes/feed/forum.php b/phpBB/includes/feed/forum.php
new file mode 100644
index 0000000000..7670fbeaaa
--- /dev/null
+++ b/phpBB/includes/feed/forum.php
@@ -0,0 +1,147 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Forum feed
+*
+* This will give you the last {$this->num_items} posts made
+* within a specific forum.
+*
+* @package phpBB3
+*/
+class phpbb_feed_forum extends phpbb_feed_post_base
+{
+ var $forum_id = 0;
+ var $forum_data = array();
+
+ /**
+ * Set the Forum ID
+ *
+ * @param int $forum_id Forum ID
+ * @return phpbb_feed_forum
+ */
+ public function set_forum_id($topic_id)
+ {
+ $this->forum_id = (int) $forum_id;
+
+ return $this;
+ }
+
+ function open()
+ {
+ // Check if forum exists
+ $sql = 'SELECT forum_id, forum_name, forum_password, forum_type, forum_options
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $this->forum_id;
+ $result = $this->db->sql_query($sql);
+ $this->forum_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (empty($this->forum_data))
+ {
+ trigger_error('NO_FORUM');
+ }
+
+ // Forum needs to be postable
+ if ($this->forum_data['forum_type'] != FORUM_POST)
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure forum is not excluded from feed
+ if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options']))
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure we can read this forum
+ if (!$this->auth->acl_get('f_read', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not passworded or user is authed
+ if ($this->forum_data['forum_password'])
+ {
+ $forum_ids_passworded = $this->get_passworded_forums();
+
+ if (isset($forum_ids_passworded[$this->forum_id]))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ unset($forum_ids_passworded);
+ }
+ }
+
+ function get_sql()
+ {
+ $m_approve = ($this->auth->acl_get('m_approve', $this->forum_id)) ? true : false;
+
+ // Determine topics with recent activity
+ $sql = 'SELECT topic_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE forum_id = ' . $this->forum_id . '
+ AND topic_moved_id = 0
+ ' . ((!$m_approve) ? 'AND topic_approved = 1' : '') . '
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $topic_ids = array();
+ $min_post_time = 0;
+ while ($row = $this->db->sql_fetchrow())
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $min_post_time = (int) $row['topic_last_post_time'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($topic_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => $this->db->sql_in_set('p.topic_id', $topic_ids) . '
+ ' . ((!$m_approve) ? 'AND p.post_approved = 1' : '') . '
+ AND p.post_time >= ' . $min_post_time . '
+ AND p.poster_id = u.user_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+
+ function get_item()
+ {
+ return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row;
+ }
+}
diff --git a/phpBB/includes/feed/forums.php b/phpBB/includes/feed/forums.php
new file mode 100644
index 0000000000..72f786aa6a
--- /dev/null
+++ b/phpBB/includes/feed/forums.php
@@ -0,0 +1,72 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* 'All Forums' feed
+*
+* This will give you a list of all postable forums where feeds are enabled
+* including forum description, topic stats and post stats
+*
+* @package phpBB3
+*/
+class phpbb_feed_forums extends phpbb_feed_base
+{
+ var $num_items = 0;
+
+ function set_keys()
+ {
+ $this->set('title', 'forum_name');
+ $this->set('text', 'forum_desc');
+ $this->set('bitfield', 'forum_desc_bitfield');
+ $this->set('bbcode_uid','forum_desc_uid');
+ $this->set('updated', 'forum_last_post_time');
+ $this->set('options', 'forum_desc_options');
+ }
+
+ function get_sql()
+ {
+ $in_fid_ary = array_diff($this->get_readable_forums(), $this->get_excluded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // Build SQL Query
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.left_id, f.forum_name, f.forum_last_post_time,
+ f.forum_desc, f.forum_desc_bitfield, f.forum_desc_uid, f.forum_desc_options,
+ f.forum_topics, f.forum_posts',
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'WHERE' => 'f.forum_type = ' . FORUM_POST . '
+ AND ' . $this->db->sql_in_set('f.forum_id', $in_fid_ary),
+ 'ORDER_BY' => 'f.left_id ASC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewforum.' . $this->phpEx, 'f=' . $row['forum_id']);
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang('TOTAL_TOPICS', (int) $row['forum_topics'])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts']);
+ }
+ }
+}
diff --git a/phpBB/includes/feed/helper.php b/phpBB/includes/feed/helper.php
new file mode 100644
index 0000000000..93330aa2ad
--- /dev/null
+++ b/phpBB/includes/feed/helper.php
@@ -0,0 +1,159 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Class with some helpful functions used in feeds
+* @package phpBB3
+*/
+class phpbb_feed_helper
+{
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_user */
+ protected $user;
+
+ /** @var string */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param phpbb_config $config Config object
+ * @param phpbb_user $user User object
+ * @param string $phpbb_root_path Root path
+ * @return null
+ */
+ public function __construct(phpbb_config $config, phpbb_user $user, $phpbb_root_path)
+ {
+ $this->config = $config;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
+ public function get_board_url()
+ {
+ static $board_url;
+
+ if (empty($board_url))
+ {
+ $board_url = generate_board_url();
+ }
+
+ return $board_url;
+ }
+
+ /**
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
+ public function append_sid($url, $params)
+ {
+ return append_sid($this->get_board_url() . '/' . $url, $params, true, '');
+ }
+
+ /**
+ * 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 = phpbb_format_timezone_offset($zone_offset);
+ }
+
+ return gmdate("Y-m-d\TH:i:s", $time + $zone_offset) . $offset_string;
+ }
+
+ /**
+ * Generate text content
+ */
+ public function generate_content($content, $uid, $bitfield, $options)
+ {
+ if (empty($content))
+ {
+ return '';
+ }
+
+ // Prepare some bbcodes for better parsing
+ $content = preg_replace("#\[quote(=&quot;.*?&quot;)?:$uid\]\s*(.*?)\s*\[/quote:$uid\]#si", "[quote$1:$uid]<br />$2<br />[/quote:$uid]", $content);
+
+ $content = generate_text_for_display($content, $uid, $bitfield, $options);
+
+ // Add newlines
+ $content = str_replace('<br />', '<br />' . "\n", $content);
+
+ // Convert smiley Relative paths to Absolute path, Windows style
+ $content = str_replace($this->phpbb_root_path . $this->config['smilies_path'], $this->get_board_url() . '/' . $this->config['smilies_path'], $content);
+
+ // Remove "Select all" link and mouse events
+ $content = str_replace('<a href="#" onclick="selectCode(this); return false;">' . $this->user->lang['SELECT_ALL_CODE'] . '</a>', '', $content);
+ $content = preg_replace('#(onkeypress|onclick)="(.*?)"#si', '', $content);
+
+ // Firefox does not support CSS for feeds, though
+
+ // Remove font sizes
+ // $content = preg_replace('#<span style="font-size: [0-9]+%; line-height: [0-9]+%;">([^>]+)</span>#iU', '\1', $content);
+
+ // Make text strong :P
+ // $content = preg_replace('#<span style="font-weight: bold?">(.*?)</span>#iU', '<strong>\1</strong>', $content);
+
+ // Italic
+ // $content = preg_replace('#<span style="font-style: italic?">([^<]+)</span>#iU', '<em>\1</em>', $content);
+
+ // Underline
+ // $content = preg_replace('#<span style="text-decoration: underline?">([^<]+)</span>#iU', '<u>\1</u>', $content);
+
+ // Remove embed Windows Media Streams
+ $content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--<!\[endif\]-->#si', '', $content);
+
+ // Do not use &lt; and &gt;, because we want to retain code contained in [code][/code]
+
+ // Remove embed and objects
+ $content = preg_replace( '#<(object|embed)(.*?) (value|src)=(.*?) ([^[]+)(object|embed)>#si',' <a href=$4 target="_blank"><strong>$1</strong></a> ',$content);
+
+ // Remove some specials html tag, because somewhere there are a mod to allow html tags ;)
+ $content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', ' <strong>$1</strong> ', $content);
+
+ // Remove Comments from inline attachments [ia]
+ $content = preg_replace('#<div class="(inline-attachment|attachtitle)">(.*?)<!-- ia(.*?) -->(.*?)<!-- ia(.*?) -->(.*?)</div>#si','$4',$content);
+
+ // Replace some entities with their unicode counterpart
+ $entities = array(
+ '&nbsp;' => "\xC2\xA0",
+ '&bull;' => "\xE2\x80\xA2",
+ '&middot;' => "\xC2\xB7",
+ '&copy;' => "\xC2\xA9",
+ );
+
+ $content = str_replace(array_keys($entities), array_values($entities), $content);
+
+ // Remove CDATA blocks. ;)
+ $content = preg_replace('#\<\!\[CDATA\[(.*?)\]\]\>#s', '', $content);
+
+ // Other control characters
+ $content = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $content);
+
+ return $content;
+ }
+}
diff --git a/phpBB/includes/feed/news.php b/phpBB/includes/feed/news.php
new file mode 100644
index 0000000000..92cc18a3ab
--- /dev/null
+++ b/phpBB/includes/feed/news.php
@@ -0,0 +1,112 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* News feed
+*
+* This will give you {$this->num_items} first posts
+* of all topics in the selected news forums.
+*
+* @package phpBB3
+*/
+class phpbb_feed_news extends phpbb_feed_topic_base
+{
+ function get_news_forums()
+ {
+ static $forum_ids;
+
+ // Matches acp/acp_board.php
+ $cache_name = 'feed_news_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids);
+ }
+
+ return $forum_ids;
+ }
+
+ function get_sql()
+ {
+ // Determine forum ids
+ $in_fid_ary = array_intersect($this->get_news_forums(), $this->get_readable_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_first_post_id, topic_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ORDER BY topic_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_first_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+}
diff --git a/phpBB/includes/feed/overall.php b/phpBB/includes/feed/overall.php
new file mode 100644
index 0000000000..5fb922f6bb
--- /dev/null
+++ b/phpBB/includes/feed/overall.php
@@ -0,0 +1,97 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Board wide feed (aka overall feed)
+*
+* This will give you the newest {$this->num_items} posts
+* from the whole board.
+*
+* @package phpBB3
+*/
+class phpbb_feed_overall extends phpbb_feed_post_base
+{
+ function get_sql()
+ {
+ $forum_ids = array_diff($this->get_readable_forums(), $this->get_excluded_forums(), $this->get_passworded_forums());
+ if (empty($forum_ids))
+ {
+ return false;
+ }
+
+ // m_approve forums
+ $fid_m_approve = $this->get_moderator_approve_forums();
+ $sql_m_approve = (!empty($fid_m_approve)) ? 'OR ' . $this->db->sql_in_set('forum_id', $fid_m_approve) : '';
+
+ // Determine topics with recent activity
+ $sql = 'SELECT topic_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $forum_ids) . '
+ AND topic_moved_id = 0
+ AND (topic_approved = 1
+ ' . $sql_m_approve . ')
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $topic_ids = array();
+ $min_post_time = 0;
+ while ($row = $this->db->sql_fetchrow())
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $min_post_time = (int) $row['topic_last_post_time'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($topic_ids))
+ {
+ return false;
+ }
+
+ // Get the actual data
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name, ' .
+ 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ USERS_TABLE => 'u',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'f.forum_id = p.forum_id',
+ ),
+ ),
+ 'WHERE' => $this->db->sql_in_set('p.topic_id', $topic_ids) . '
+ AND (p.post_approved = 1
+ ' . str_replace('forum_id', 'p.forum_id', $sql_m_approve) . ')
+ AND p.post_time >= ' . $min_post_time . '
+ AND u.user_id = p.poster_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/feed/post_base.php b/phpBB/includes/feed/post_base.php
new file mode 100644
index 0000000000..a25ed50263
--- /dev/null
+++ b/phpBB/includes/feed/post_base.php
@@ -0,0 +1,57 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Abstract class for post based feeds
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_post_base extends phpbb_feed_base
+{
+ var $num_items = 'feed_limit_post';
+
+ function set_keys()
+ {
+ $this->set('title', 'post_subject');
+ $this->set('title2', 'topic_title');
+
+ $this->set('author_id', 'user_id');
+ $this->set('creator', 'username');
+ $this->set('published', 'post_time');
+ $this->set('updated', 'post_edit_time');
+ $this->set('text', 'post_text');
+
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, "t={$row['topic_id']}&amp;p={$row['post_id']}#p{$row['post_id']}");
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
+ . ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')])
+ . (($this->is_moderator_approve_forum($row['forum_id']) && !$row['post_approved']) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_UNAPPROVED'] : '');
+ }
+ }
+}
diff --git a/phpBB/includes/feed/topic.php b/phpBB/includes/feed/topic.php
new file mode 100644
index 0000000000..7d9a344982
--- /dev/null
+++ b/phpBB/includes/feed/topic.php
@@ -0,0 +1,116 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Topic feed for a specific topic
+*
+* This will give you the last {$this->num_items} posts made within this topic.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topic extends phpbb_feed_post_base
+{
+ var $topic_id = 0;
+ var $forum_id = 0;
+ var $topic_data = array();
+
+ /**
+ * Set the Topic ID
+ *
+ * @param int $topic_id Topic ID
+ * @return phpbb_feed_topic
+ */
+ public function set_topic_id($topic_id)
+ {
+ $this->topic_id = (int) $topic_id;
+
+ return $this;
+ }
+
+ function open()
+ {
+ $sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_approved, t.topic_title, t.topic_time, t.topic_views, t.topic_replies, t.topic_type
+ FROM ' . TOPICS_TABLE . ' t
+ LEFT JOIN ' . FORUMS_TABLE . ' f
+ ON (f.forum_id = t.forum_id)
+ WHERE t.topic_id = ' . $this->topic_id;
+ $result = $this->db->sql_query($sql);
+ $this->topic_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (empty($this->topic_data))
+ {
+ trigger_error('NO_TOPIC');
+ }
+
+ $this->forum_id = (int) $this->topic_data['forum_id'];
+
+ // Make sure topic is either approved or user authed
+ if (!$this->topic_data['topic_approved'] && !$this->auth->acl_get('m_approve', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not excluded from feed
+ if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options']))
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure we can read this forum
+ if (!$this->auth->acl_get('f_read', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not passworded or user is authed
+ if ($this->topic_data['forum_password'])
+ {
+ $forum_ids_passworded = $this->get_passworded_forums();
+
+ if (isset($forum_ids_passworded[$this->forum_id]))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ unset($forum_ids_passworded);
+ }
+ }
+
+ function get_sql()
+ {
+ $this->sql = array(
+ 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => 'p.topic_id = ' . $this->topic_id . '
+ ' . ($this->forum_id && !$this->auth->acl_get('m_approve', $this->forum_id) ? 'AND p.post_approved = 1' : '') . '
+ AND p.poster_id = u.user_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function get_item()
+ {
+ return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row;
+ }
+}
diff --git a/phpBB/includes/feed/topic_base.php b/phpBB/includes/feed/topic_base.php
new file mode 100644
index 0000000000..e6a47b4c86
--- /dev/null
+++ b/phpBB/includes/feed/topic_base.php
@@ -0,0 +1,59 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Abstract class for topic based feeds
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_topic_base extends phpbb_feed_base
+{
+ var $num_items = 'feed_limit_topic';
+
+ function set_keys()
+ {
+ $this->set('title', 'topic_title');
+ $this->set('title2', 'forum_name');
+
+ $this->set('author_id', 'topic_poster');
+ $this->set('creator', 'topic_first_poster_name');
+ $this->set('published', 'post_time');
+ $this->set('updated', 'post_edit_time');
+ $this->set('text', 'post_text');
+
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, 't=' . $row['topic_id'] . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']);
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
+ . ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang['REPLIES'] . ' ' . (($this->is_moderator_approve_forum($row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang['VIEWS'] . ' ' . $row['topic_views']
+ . (($this->is_moderator_approve_forum($row['forum_id']) && ($row['topic_replies_real'] != $row['topic_replies'])) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POSTS_UNAPPROVED'] : '');
+ }
+ }
+}
diff --git a/phpBB/includes/feed/topics.php b/phpBB/includes/feed/topics.php
new file mode 100644
index 0000000000..c8761d7176
--- /dev/null
+++ b/phpBB/includes/feed/topics.php
@@ -0,0 +1,91 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* New Topics feed
+*
+* This will give you the last {$this->num_items} created topics
+* including the first post.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topics extends phpbb_feed_topic_base
+{
+ function get_sql()
+ {
+ $forum_ids_read = $this->get_readable_forums();
+ if (empty($forum_ids_read))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_diff($forum_ids_read, $this->get_excluded_forums(), $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_first_post_id, topic_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ORDER BY topic_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_first_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/feed/topics_active.php b/phpBB/includes/feed/topics_active.php
new file mode 100644
index 0000000000..d1c920c136
--- /dev/null
+++ b/phpBB/includes/feed/topics_active.php
@@ -0,0 +1,136 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Active Topics feed
+*
+* This will give you the last {$this->num_items} topics
+* with replies made withing the last {$this->sort_days} days
+* including the last post.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topics_active extends phpbb_feed_topic_base
+{
+ var $sort_days = 7;
+
+ function set_keys()
+ {
+ parent::set_keys();
+
+ $this->set('author_id', 'topic_last_poster_id');
+ $this->set('creator', 'topic_last_poster_name');
+ }
+
+ function get_sql()
+ {
+ $forum_ids_read = $this->get_readable_forums();
+ if (empty($forum_ids_read))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_intersect($forum_ids_read, $this->get_forum_ids());
+ $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // Search for topics in last X days
+ $last_post_time_sql = ($this->sort_days) ? ' AND topic_last_post_time > ' . (time() - ($this->sort_days * 24 * 3600)) : '';
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_last_post_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ' . $last_post_time_sql . '
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_last_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_replies, t.topic_replies_real, t.topic_views,
+ t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function get_forum_ids()
+ {
+ static $forum_ids;
+
+ $cache_name = 'feed_topic_active_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_type = ' . FORUM_POST . '
+ AND ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '= 0') . '
+ AND ' . $this->db->sql_bit_and('forum_flags', log(FORUM_FLAG_ACTIVE_TOPICS, 2), '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids, 180);
+ }
+
+ return $forum_ids;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php
index ee4e2f5135..0a8000ea3d 100644
--- a/phpBB/includes/functions_download.php
+++ b/phpBB/includes/functions_download.php
@@ -46,7 +46,7 @@ function send_avatar_to_browser($file, $browser)
$image_data = @getimagesize($file_path);
header('Content-Type: ' . image_type_to_mime_type($image_data[2]));
- if (strpos(strtolower($browser), 'msie') !== false && strpos(strtolower($browser), 'msie 8.0') === false)
+ if ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
{
header('Content-Disposition: attachment; ' . header_filename($file));
@@ -174,10 +174,9 @@ function send_file_to_browser($attachment, $upload_dir, $category)
header('Pragma: public');
// Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
- $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false);
header('Content-Type: ' . $attachment['mimetype']);
- if ($is_ie8)
+ if (phpbb_is_greater_ie_version($user->browser, 7))
{
header('X-Content-Type-Options: nosniff');
}
@@ -189,7 +188,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
}
else
{
- if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false)))
+ if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
{
header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
@@ -200,7 +199,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
else
{
header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
- if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0))
+ if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
{
header('X-Download-Options: noopen');
}
@@ -410,7 +409,8 @@ function set_modified_headers($stamp, $browser)
// let's see if we have to send the file at all
$last_load = $request->header('Modified-Since') ? strtotime(trim($request->header('Modified-Since'))) : false;
- if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false))
+
+ if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
{
if ($last_load !== false && $last_load >= $stamp)
{
@@ -721,3 +721,24 @@ function phpbb_download_clean_filename($filename)
return $filename;
}
+
+/**
+* Check if the browser is internet explorer version 7+
+*
+* @param string $user_agent User agent HTTP header
+* @param int $version IE version to check against
+*
+* @return bool true if internet explorer version is greater than $version
+*/
+function phpbb_is_greater_ie_version($user_agent, $version)
+{
+ if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
+ {
+ $ie_version = (int) $matches[1];
+ return ($ie_version > $version);
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 7b11e4f01b..1b598f7bf7 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -1653,7 +1653,7 @@ function validate_username($username, $allowed_username = false)
*/
function validate_password($password)
{
- global $config, $db, $user;
+ global $config;
if ($password === '' || $config['pass_complex'] === 'PASS_TYPE_ANY')
{
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index adaf025730..aa493c3281 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -163,9 +163,16 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$engine = $info['Type'];
}
- if ($engine != 'MyISAM')
+ $fulltext_supported =
+ $engine === 'MyISAM' ||
+ // FULLTEXT is supported on InnoDB since MySQL 5.6.4 according to
+ // http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html
+ $engine === 'InnoDB' &&
+ phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
+
+ if (!$fulltext_supported)
{
- return $this->user->lang['FULLTEXT_MYSQL_NOT_MYISAM'];
+ return $this->user->lang['FULLTEXT_MYSQL_NOT_SUPPORTED'];
}
$sql = 'SHOW VARIABLES
diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php
index efc88e6e37..aada0525a8 100644
--- a/phpBB/includes/ucp/ucp_groups.php
+++ b/phpBB/includes/ucp/ucp_groups.php
@@ -416,9 +416,11 @@ class ucp_groups
if ($group_id)
{
- $sql = 'SELECT *
- FROM ' . GROUPS_TABLE . "
- WHERE group_id = $group_id";
+ $sql = 'SELECT g.*, t.teampage_position AS group_teampage
+ FROM ' . GROUPS_TABLE . ' g
+ LEFT JOIN ' . TEAMPAGE_TABLE . ' t
+ ON (t.group_id = g.group_id)
+ WHERE g.group_id = ' . $group_id;
$result = $db->sql_query($sql);
$group_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -514,6 +516,8 @@ class ucp_groups
'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0,
'message_limit' => request_var('group_message_limit', 0),
'max_recipients'=> request_var('group_max_recipients', 0),
+ 'legend' => $group_row['group_legend'],
+ 'teampage' => $group_row['group_teampage'],
);
if ($config['allow_avatar'])
@@ -569,6 +573,9 @@ class ucp_groups
// Only set the rank, colour, etc. if it's changed or if we're adding a new
// group. This prevents existing group members being updated if no changes
// were made.
+ // However there are some attributes that need to be set everytime,
+ // otherwise the group gets removed from the feature.
+ $set_attributes = array('legend', 'teampage');
$group_attributes = array();
$test_variables = array(
@@ -580,13 +587,14 @@ class ucp_groups
'avatar_height' => 'int',
'receive_pm' => 'int',
'legend' => 'int',
+ 'teampage' => 'int',
'message_limit' => 'int',
'max_recipients'=> 'int',
);
foreach ($test_variables as $test => $type)
{
- if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0))
+ if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes)))
{
settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
@@ -596,6 +604,7 @@ class ucp_groups
if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies)))
{
$cache->destroy('sql', GROUPS_TABLE);
+ $cache->destroy('sql', TEAMPAGE_TABLE);
$message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED';
trigger_error($user->lang[$message] . $return_page);
@@ -682,7 +691,7 @@ class ucp_groups
}
}
- if (!$update)
+ if (isset($phpbb_avatar_manager) && !$update)
{
// Merge any avatars errors into the primary error array
$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php
index aa1bd0fa35..df9b6c1c7e 100644
--- a/phpBB/install/install_update.php
+++ b/phpBB/install/install_update.php
@@ -1618,7 +1618,9 @@ class install_update extends module
{
case 'version_info':
global $phpbb_root_path, $phpEx;
- $info = get_remote_file('www.phpbb.com', '/updatecheck', ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
+
+ $info = get_remote_file('version.phpbb.com', '/phpbb',
+ ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
if ($info !== false)
{
diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php
index 9f947dc816..8d9443b481 100644
--- a/phpBB/language/en/acp/search.php
+++ b/phpBB/language/en/acp/search.php
@@ -52,7 +52,7 @@ $lang = array_merge($lang, array(
'DELETING_INDEX_IN_PROGRESS_EXPLAIN' => 'The search backend is currently cleaning its index. This can take a few minutes.',
'FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE' => 'The MySQL fulltext backend can only be used with MySQL4 and above.',
- 'FULLTEXT_MYSQL_NOT_MYISAM' => 'MySQL fulltext indexes can only be used with MyISAM tables.',
+ 'FULLTEXT_MYSQL_NOT_SUPPORTED' => 'MySQL fulltext indexes can only be used with MyISAM or InnoDB tables. MySQL 5.6.4 or later is required for fulltext indexes on InnoDB tables.',
'FULLTEXT_MYSQL_TOTAL_POSTS' => 'Total number of indexed posts',
'FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
'FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
diff --git a/phpBB/styles/prosilver/template/editor.js b/phpBB/styles/prosilver/template/editor.js
index fd4c68adfe..235cc0025b 100644
--- a/phpBB/styles/prosilver/template/editor.js
+++ b/phpBB/styles/prosilver/template/editor.js
@@ -401,7 +401,7 @@ function getCaretPosition(txtarea) {
*/
(function($) {
$(document).ready(function() {
- var doc, textarea, startTags, endTags;
+ var doc, textarea;
// find textarea, make sure browser supports necessary functions
if (document.forms[form_name]) {
@@ -415,81 +415,8 @@ function getCaretPosition(txtarea) {
}
textarea = doc.forms[form_name].elements[text_name];
- if (!textarea || typeof textarea.selectionStart !== 'number') {
- return;
- }
-
- // list of allowed start and end bbcode code tags, in lower case
- startTags = ['[code]', '[code='];
- endTags = ['[/code]'];
-
- function inTag() {
- var start = textarea.selectionStart,
- lastEnd = -1,
- lastStart = -1,
- i, index, value;
-
- value = textarea.value.toLowerCase();
-
- for (i = 0; i < startTags.length; i++) {
- var tagLength = startTags[i].length;
- if (start >= tagLength) {
- index = value.lastIndexOf(startTags[i], start - tagLength);
- lastStart = Math.max(lastStart, index);
- }
- }
- if (lastStart == -1) return false;
-
- if (start > 0) {
- for (i = 0; i < endTags.length; i++) {
- index = value.lastIndexOf(endTags[i], start - 1);
- lastEnd = Math.max(lastEnd, index);
- }
- }
-
- return (lastEnd < lastStart);
- }
-
- function getLastLine() {
- var start = textarea.selectionStart,
- value = textarea.value,
- index = value.lastIndexOf("\n", start - 1);
- return value.substring(index + 1, start);
- }
-
- function appendCode(code) {
- var start = textarea.selectionStart,
- end = textarea.selectionEnd,
- value = textarea.value;
- textarea.value = value.substr(0, start) + code + value.substr(end);
- textarea.selectionStart = textarea.selectionEnd = start + code.length;
- }
-
- $(textarea).on('keydown', function(event) {
- var key = event.keyCode || event.which;
- // intercept tabs
- if (key == 9) {
- if (inTag()) {
- appendCode("\t");
- event.preventDefault();
- return;
- }
- }
-
- // intercept new line characters
- if (key == 13) {
- if (inTag()) {
- var lastLine = getLastLine(),
- code = '' + /^\s*/g.exec(lastLine);
- if (code.length > 0) {
- appendCode("\n" + code);
- event.preventDefault();
- return;
- }
- }
- }
- });
+ phpbb.applyCodeEditor(textarea);
});
})(jQuery);
diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css
index 26ec23b2e6..89b3ab7ada 100644
--- a/phpBB/styles/prosilver/theme/common.css
+++ b/phpBB/styles/prosilver/theme/common.css
@@ -306,8 +306,12 @@ a#logo:hover {
ul.linklist {
display: block;
margin: 0;
- height: 4%;
- overflow: hidden;
+}
+
+ul.linklist:after {
+ content: '';
+ display: block;
+ clear: both;
}
#cp-main .panel {
@@ -689,28 +693,33 @@ p.rules a {
vertical-align: text-bottom;
}
+.icon-notification {
+ position: relative;
+}
+
#notification_list {
display: none;
position: absolute;
+ left: 0;
width: 330px;
z-index: 1;
border: 1px solid;
box-shadow: 3px 3px 5px darkgray;
border-radius: 5px;
- margin-top: 8px;
+ top: 32px;
}
#notification_list ul {
max-height: 350px;
overflow-y: auto;
overflow-x: hidden;
+ clear: both;
}
#notification_list ul li {
- width: 310px;
padding: 10px;
margin: 0;
- float: left;
+ float: none;
border-bottom: 1px solid;
list-style-type: none;
font-size: 0.95em;
diff --git a/phpBB/styles/prosilver/theme/tweaks.css b/phpBB/styles/prosilver/theme/tweaks.css
index 89510aa32f..ca4e9a23b6 100644
--- a/phpBB/styles/prosilver/theme/tweaks.css
+++ b/phpBB/styles/prosilver/theme/tweaks.css
@@ -9,6 +9,10 @@ tweaks required due to its poor CSS support.
zoom: 1;
}
+ul.linklist {
+ zoom: 1;
+}
+
/* Align checkboxes/radio buttons nicely */
dd label input {
vertical-align: text-bottom;
@@ -47,3 +51,18 @@ dd.lastpost, dd.redirect, dd.moderation, dd.time, dd.info {
dd.option {
*width: 124px;
}
+
+/* Notifications list for IE7 */
+#notification_list {
+ *left: 0;
+}
+
+#notification_list .header_settings {
+ *position: absolute;
+ *right: 10px;
+ *top: 0;
+}
+
+.icon-notification {
+ *z-index: 2;
+}
diff --git a/phpBB/styles/subsilver2/template/editor.js b/phpBB/styles/subsilver2/template/editor.js
index 93506b8d4a..6cf616e180 100644
--- a/phpBB/styles/subsilver2/template/editor.js
+++ b/phpBB/styles/subsilver2/template/editor.js
@@ -38,6 +38,7 @@ function initInsertions() {
}
var textarea = doc.forms[form_name].elements[text_name];
+ phpbb.applyCodeEditor(textarea);
if (is_ie && typeof(baseHeight) !== 'number') {
textarea.focus();