PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,97 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Abstract class for feeds displaying attachments
*/
abstract class attachments_base extends base
{
/**
* Attachments that may be displayed
*/
protected $attachments = array();
/**
* Retrieve the list of attachments that may be displayed
*
* @param array $post_ids Specify for which post IDs to fetch the attachments (optional)
* @param array $topic_ids Specify for which topic IDs to fetch the attachments (optional)
*/
protected function fetch_attachments($post_ids = array(), $topic_ids = array())
{
$sql_array = array(
'SELECT' => 'a.*',
'FROM' => array(
ATTACHMENTS_TABLE => 'a'
),
'WHERE' => 'a.in_message = 0 ',
'ORDER_BY' => 'a.filetime DESC, a.post_msg_id ASC',
);
if (!empty($post_ids))
{
$sql_array['WHERE'] .= 'AND ' . $this->db->sql_in_set('a.post_msg_id', $post_ids);
}
else if (!empty($topic_ids))
{
if (isset($this->topic_id))
{
$topic_ids[] = $this->topic_id;
}
$sql_array['WHERE'] .= 'AND ' . $this->db->sql_in_set('a.topic_id', $topic_ids);
}
else if (isset($this->topic_id))
{
$sql_array['WHERE'] .= 'AND a.topic_id = ' . (int) $this->topic_id;
}
else if (isset($this->forum_id))
{
$sql_array['LEFT_JOIN'] = array(
array(
'FROM' => array(TOPICS_TABLE => 't'),
'ON' => 'a.topic_id = t.topic_id',
)
);
$sql_array['WHERE'] .= 'AND t.forum_id = ' . (int) $this->forum_id;
}
else
{
// Do not allow querying the full attachments table
throw new \RuntimeException($this->user->lang('INVALID_FEED_ATTACHMENTS'));
}
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query($sql);
// Set attachments in feed items
while ($row = $this->db->sql_fetchrow($result))
{
$this->attachments[$row['post_msg_id']][] = $row;
}
$this->db->sql_freeresult($result);
}
/**
* Get attachments related to a given post
*
* @param $post_id int Post id
* @return mixed Attachments related to $post_id
*/
public function get_attachments($post_id)
{
return $this->attachments[$post_id];
}
}

View File

@ -0,0 +1,337 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Base class with some generic functions and settings.
*/
abstract class base implements feed_interface
{
/**
* Feed helper object
* @var \phpbb\feed\helper
*/
protected $helper;
/** @var \phpbb\config\config */
protected $config;
/** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\cache\driver\driver_interface */
protected $cache;
/** @var \phpbb\user */
protected $user;
/** @var \phpbb\auth\auth */
protected $auth;
/** @var \phpbb\content_visibility */
protected $content_visibility;
/** @var \phpbb\event\dispatcher_interface */
protected $phpbb_dispatcher;
/** @var string */
protected $phpEx;
/**
* SQL Query to be executed to get feed items
*/
protected $sql = array();
/**
* Keys specified for retrieval of title, content, etc.
*/
protected $keys = array();
/**
* Number of items to fetch. Usually overwritten by $config['feed_something']
*/
protected $num_items = 15;
/**
* Separator for title elements to separate items (for example forum / topic)
*/
protected $separator = "\xE2\x80\xA2"; // &bull;
/**
* Separator for the statistics row (Posted by, post date, replies, etc.)
*/
protected $separator_stats = "\xE2\x80\x94"; // &mdash;
/** @var mixed Query result handle */
protected $result;
/**
* Constructor
*
* @param \phpbb\feed\helper $helper Feed helper
* @param \phpbb\config\config $config Config object
* @param \phpbb\db\driver\driver_interface $db Database connection
* @param \phpbb\cache\driver\driver_interface $cache Cache object
* @param \phpbb\user $user User object
* @param \phpbb\auth\auth $auth Auth object
* @param \phpbb\content_visibility $content_visibility Auth object
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
* @param string $phpEx php file extension
*/
public function __construct(
\phpbb\feed\helper $helper,
\phpbb\config\config $config,
\phpbb\db\driver\driver_interface $db,
\phpbb\cache\driver\driver_interface $cache,
\phpbb\user $user,
\phpbb\auth\auth $auth,
\phpbb\content_visibility $content_visibility,
\phpbb\event\dispatcher_interface $phpbb_dispatcher,
$phpEx
)
{
$this->config = $config;
$this->helper = $helper;
$this->db = $db;
$this->cache = $cache;
$this->user = $user;
$this->auth = $auth;
$this->content_visibility = $content_visibility;
$this->phpbb_dispatcher = $phpbb_dispatcher;
$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;
}
}
}
/**
* {@inheritdoc}
*/
public function set_keys()
{
}
/**
* {@inheritdoc}
*/
public function open()
{
}
/**
* {@inheritdoc}
*/
public function close()
{
if (!empty($this->result))
{
$this->db->sql_freeresult($this->result);
}
}
/**
* {@inheritdoc}
*/
public function set($key, $value)
{
$this->keys[$key] = $value;
}
/**
* {@inheritdoc}
*/
public function get($key)
{
return (isset($this->keys[$key])) ? $this->keys[$key] : null;
}
/**
* {@inheritdoc}
*/
public function get_item()
{
if (!isset($this->result))
{
if (!$this->get_sql())
{
return false;
}
$sql_ary = $this->sql;
/**
* Event to modify the feed item sql
*
* @event core.feed_base_modify_item_sql
* @var array sql_ary The SQL array to get the feed item data
*
* @since 3.1.10-RC1
*/
$vars = array('sql_ary');
extract($this->phpbb_dispatcher->trigger_event('core.feed_base_modify_item_sql', compact($vars)));
$this->sql = $sql_ary;
unset($sql_ary);
// Query database
$sql = $this->db->sql_build_query('SELECT', $this->sql);
$this->result = $this->db->sql_query_limit($sql, $this->num_items);
}
return $this->db->sql_fetchrow($this->result);
}
/**
* Returns the ids of the forums readable by the current user.
*
* @return int[]
*/
protected 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;
}
/**
* Returns the ids of the forum for which the current user can approve the post in the moderation queue.
*
* @return int[]
*/
protected 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;
}
/**
* Returns true if the current user can approve the post of the given forum
*
* @param int $forum_id Forum id to check
* @return bool
*/
protected 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;
}
/**
* Returns the ids of the forum excluded from the feeds
*
* @return int[]
*/
protected 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;
}
/**
* Returns true if the given id is in the excluded forums list.
*
* @param int $forum_id Id to check
* @return bool
*/
protected function is_excluded_forum($forum_id)
{
$forum_ids = $this->get_excluded_forums();
return isset($forum_ids[$forum_id]) ? true : false;
}
/**
* Returns all password protected forum ids the current user is currently NOT authenticated for.
*
* @return array Array of forum ids
*/
protected function get_passworded_forums()
{
return $this->user->get_passworded_forums();
}
/**
* Returns the link to the user profile.
*
* @return string
*/
protected 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>';
}
/**
* Returns the SQL query used to retrieve the posts of the feed.
*
* @return string SQL SELECT query
*/
protected abstract function get_sql();
}

View File

@ -0,0 +1,411 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\controller;
use phpbb\auth\auth;
use phpbb\config\config;
use phpbb\db\driver\driver_interface;
use \phpbb\event\dispatcher_interface;
use phpbb\exception\http_exception;
use phpbb\feed\feed_interface;
use phpbb\feed\exception\feed_unavailable_exception;
use phpbb\feed\exception\unauthorized_exception;
use phpbb\feed\helper as feed_helper;
use phpbb\controller\helper as controller_helper;
use phpbb\symfony_request;
use phpbb\user;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class feed
{
/**
* @var \Twig_Environment
*/
protected $template;
/**
* @var symfony_request
*/
protected $request;
/**
* @var controller_helper
*/
protected $controller_helper;
/**
* @var config
*/
protected $config;
/**
* @var driver_interface
*/
protected $db;
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var feed_helper
*/
protected $feed_helper;
/**
* @var user
*/
protected $user;
/**
* @var auth
*/
protected $auth;
/**
* @var dispatcher_interface
*/
protected $phpbb_dispatcher;
/**
* @var string
*/
protected $php_ext;
/**
* Constructor
*
* @param \Twig_Environment $twig
* @param symfony_request $request
* @param controller_helper $controller_helper
* @param config $config
* @param driver_interface $db
* @param ContainerInterface $container
* @param feed_helper $feed_helper
* @param user $user
* @param auth $auth
* @param dispatcher_interface $phpbb_dispatcher
* @param string $php_ext
*/
public function __construct(\Twig_Environment $twig, symfony_request $request, controller_helper $controller_helper, config $config, driver_interface $db, ContainerInterface $container, feed_helper $feed_helper, user $user, auth $auth, dispatcher_interface $phpbb_dispatcher, $php_ext)
{
$this->request = $request;
$this->controller_helper = $controller_helper;
$this->config = $config;
$this->db = $db;
$this->container = $container;
$this->feed_helper = $feed_helper;
$this->user = $user;
$this->auth = $auth;
$this->php_ext = $php_ext;
$this->template = $twig;
$this->phpbb_dispatcher = $phpbb_dispatcher;
}
/**
* Controller for /feed/forums route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function forums()
{
if (!$this->config['feed_overall_forums'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.forums'));
}
/**
* Controller for /feed/news route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function 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)
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.news'));
}
/**
* Controller for /feed/topics route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function topics()
{
if (!$this->config['feed_topics_new'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.topics'));
}
/**
* Controller for /feed/topics_new route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function topics_new()
{
return $this->topics();
}
/**
* Controller for /feed/topics_active route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function topics_active()
{
if (!$this->config['feed_topics_active'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.topics_active'));
}
/**
* Controller for /feed/forum/{forum_id} route
*
* @param int $forum_id
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function forum($forum_id)
{
if (!$this->config['feed_forum'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.forum')->set_forum_id($forum_id));
}
/**
* Controller for /feed/topic/{topic_id} route
*
* @param int $topic_id
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function topic($topic_id)
{
if (!$this->config['feed_topic'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.topic')->set_topic_id($topic_id));
}
/**
* Controller for /feed/{mode] route
*
* @return Response
*
* @throws http_exception when the feed is disabled
*/
public function overall()
{
if (!$this->config['feed_overall'])
{
$this->send_unavailable();
}
return $this->send_feed($this->container->get('feed.overall'));
}
/**
* Display a given feed
*
* @param feed_interface $feed
*
* @return Response
*/
protected function send_feed(feed_interface $feed)
{
try
{
return $this->send_feed_do($feed);
}
catch (feed_unavailable_exception $e)
{
throw new http_exception(Response::HTTP_NOT_FOUND, $e->getMessage(), $e->get_parameters(), $e);
}
catch (unauthorized_exception $e)
{
throw new http_exception(Response::HTTP_FORBIDDEN, $e->getMessage(), $e->get_parameters(), $e);
}
}
/**
* Really send the feed
*
* @param feed_interface $feed
*
* @return Response
*
* @throw exception\feed_exception
*/
protected function send_feed_do(feed_interface $feed)
{
$feed_updated_time = 0;
$item_vars = array();
$board_url = $this->feed_helper->get_board_url();
// Open Feed
$feed->open();
// Iterate through items
while ($row = $feed->get_item())
{
/**
* Event to modify the feed row
*
* @event core.feed_modify_feed_row
* @var int forum_id Forum ID
* @var string mode Feeds mode (forums|topics|topics_new|topics_active|news)
* @var array row Array with feed data
* @var int topic_id Topic ID
*
* @since 3.1.10-RC1
*/
$vars = array('forum_id', 'mode', 'row', 'topic_id');
extract($this->phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars)));
// BBCode options to correctly disable urls, smilies, bbcode...
if ($feed->get('options') === null)
{
// Allow all combinations
$options = 7;
if ($feed->get('enable_bbcode') !== null && $feed->get('enable_smilies') !== null && $feed->get('enable_magic_url') !== null)
{
$options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0);
}
}
else
{
$options = $row[$feed->get('options')];
}
$title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : '');
$published = ($feed->get('published') !== null) ? (int) $row[$feed->get('published')] : 0;
$updated = ($feed->get('updated') !== null) ? (int) $row[$feed->get('updated')] : 0;
$display_attachments = ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false;
$item_row = array(
'author' => ($feed->get('creator') !== null) ? $row[$feed->get('creator')] : '',
'published' => ($published > 0) ? $this->feed_helper->format_date($published) : '',
'updated' => ($updated > 0) ? $this->feed_helper->format_date($updated) : '',
'link' => '',
'title' => censor_text($title),
'category' => ($this->config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $this->php_ext . '?f=' . $row['forum_id'] : '',
'category_name' => ($this->config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '',
'description' => censor_text($this->feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))),
'statistics' => '',
);
// Adjust items, fill link, etc.
$feed->adjust_item($item_row, $row);
$item_vars[] = $item_row;
$feed_updated_time = max($feed_updated_time, $published, $updated);
}
// If we do not have any items at all, sending the current time is better than sending no time.
if (!$feed_updated_time)
{
$feed_updated_time = time();
}
$feed->close();
$content = $this->template->render('feed.xml.twig', array(
// Some default assignments
// FEED_IMAGE is not used (atom)
'FEED_IMAGE' => '',
'SELF_LINK' => $this->controller_helper->route($this->request->attributes->get('_route'), $this->request->attributes->get('_route_params'), true, '', UrlGeneratorInterface::ABSOLUTE_URL),
'FEED_LINK' => $board_url . '/index.' . $this->php_ext,
'FEED_TITLE' => $this->config['sitename'],
'FEED_SUBTITLE' => $this->config['site_desc'],
'FEED_UPDATED' => $this->feed_helper->format_date($feed_updated_time),
'FEED_LANG' => $this->user->lang['USER_LANG'],
'FEED_AUTHOR' => $this->config['sitename'],
// Feed entries
'FEED_ROWS' => $item_vars,
));
$response = new Response($content);
$response->headers->set('Content-Type', 'application/atom+xml');
$response->setCharset('UTF-8');
$response->setLastModified(new \DateTime('@' . $feed_updated_time));
if (!empty($this->user->data['is_bot']))
{
// Let reverse proxies know we detected a bot.
$response->headers->set('X-PHPBB-IS-BOT', 'yes');
}
return $response;
}
/**
* Throw and exception saying that the feed isn't available
*
* @throw http_exception
*/
protected function send_unavailable()
{
throw new http_exception(404, 'FEATURE_NOT_AVAILABLE');
}
}

View File

@ -0,0 +1,21 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
use phpbb\exception\runtime_exception;
abstract class feed_exception extends runtime_exception
{
}

View File

@ -0,0 +1,19 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
abstract class feed_unavailable_exception extends feed_exception
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
class no_feed_exception extends feed_unavailable_exception
{
public function __construct(\Exception $previous = null, $code = 0)
{
parent::__construct('NO_FEED', array(), $previous, $code);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
class no_forum_exception extends feed_unavailable_exception
{
public function __construct($forum_id, \Exception $previous = null, $code = 0)
{
parent::__construct('NO_FORUM', array($forum_id), $previous, $code);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
class no_topic_exception extends feed_unavailable_exception
{
public function __construct($topic_id, \Exception $previous = null, $code = 0)
{
parent::__construct('NO_TOPIC', array($topic_id), $previous, $code);
}
}

View File

@ -0,0 +1,19 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
abstract class unauthorized_exception extends feed_exception
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
class unauthorized_forum_exception extends unauthorized_exception
{
public function __construct($forum_id, \Exception $previous = null, $code = 0)
{
parent::__construct('SORRY_AUTH_READ', array($forum_id), $previous, $code);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed\exception;
class unauthorized_topic_exception extends unauthorized_exception
{
public function __construct($topic_id, \Exception $previous = null, $code = 0)
{
parent::__construct('SORRY_AUTH_READ_TOPIC', array($topic_id), $previous, $code);
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Interface implemented by all feeds types
*/
interface feed_interface
{
/**
* Set keys.
*/
public function set_keys();
/**
* Open feed
*/
public function open();
/**
* Close feed
*/
public function close();
/**
* Set key
*
* @param string $key Key
* @param mixed $value Value
*/
public function set($key, $value);
/**
* Get key
*
* @param string $key Key
* @return mixed
*/
public function get($key);
/**
* Get the next post in the feed
*
* @return array
*/
public function get_item();
/**
* Adjust a feed entry
*
* @param $item_row
* @param $row
* @return array
*/
public function adjust_item(&$item_row, &$row);
}

View File

@ -0,0 +1,178 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
use phpbb\feed\exception\no_feed_exception;
use phpbb\feed\exception\no_forum_exception;
use phpbb\feed\exception\unauthorized_forum_exception;
/**
* Forum feed
*
* This will give you the last {$this->num_items} posts made
* within a specific forum.
*/
class forum extends post_base
{
protected $forum_id = 0;
protected $forum_data = array();
/**
* Set the Forum ID
*
* @param int $forum_id Forum ID
* @return \phpbb\feed\forum
*/
public function set_forum_id($forum_id)
{
$this->forum_id = (int) $forum_id;
return $this;
}
/**
* {@inheritdoc}
*/
public 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))
{
throw new no_forum_exception($this->forum_id);
}
// Forum needs to be postable
if ($this->forum_data['forum_type'] != FORUM_POST)
{
throw new no_feed_exception();
}
// Make sure forum is not excluded from feed
if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options']))
{
throw new no_feed_exception();
}
// Make sure we can read this forum
if (!$this->auth->acl_get('f_read', $this->forum_id))
{
if ($this->user->data['user_id'] != ANONYMOUS)
{
send_status_line(403, 'Forbidden');
}
else
{
send_status_line(401, 'Unauthorized');
}
throw new unauthorized_forum_exception($this->forum_id);
}
// 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]))
{
if ($this->user->data['user_id'] != ANONYMOUS)
{
send_status_line(403, 'Forbidden');
}
else
{
send_status_line(401, 'Unauthorized');
}
throw new unauthorized_forum_exception($this->forum_id);
}
unset($forum_ids_passworded);
}
parent::open();
}
/**
* {@inheritdoc}
*/
protected function get_sql()
{
// 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
AND ' . $this->content_visibility->get_visibility_sql('topic', $this->forum_id) . '
ORDER BY topic_last_post_time DESC, topic_last_post_id 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;
}
parent::fetch_attachments(array(), $topic_ids);
$this->sql = array(
'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
USERS_TABLE => 'u',
),
'WHERE' => $this->db->sql_in_set('p.topic_id', $topic_ids) . '
AND ' . $this->content_visibility->get_visibility_sql('post', $this->forum_id, 'p.') . '
AND p.post_time >= ' . $min_post_time . '
AND p.poster_id = u.user_id',
'ORDER_BY' => 'p.post_time DESC, p.post_id DESC',
);
return true;
}
/**
* {@inheritdoc}
*/
public 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'];
$item_row['forum_id'] = $this->forum_id;
}
/**
* {@inheritdoc}
*/
public function get_item()
{
return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* '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
*/
class forums extends base
{
protected $num_items = 0;
/**
* {@inheritdoc}
*/
public 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');
}
/**
* {@inheritdoc}
*/
public 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_approved, f.forum_posts_approved',
'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;
}
/**
* {@inheritdoc}
*/
public 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_approved'])
. ' ' . $this->separator_stats . ' ' . $this->user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts_approved']);
}
}
}

View File

@ -0,0 +1,186 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
use phpbb\config\config;
use phpbb\path_helper;
use phpbb\textformatter\s9e\renderer;
use phpbb\user;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class with some helpful functions used in feeds
*/
class helper
{
/** @var config */
protected $config;
/** @var ContainerInterface */
protected $container;
/** @var path_helper */
protected $path_helper;
/** @var renderer */
protected $renderer;
/** @var user */
protected $user;
/**
* Constructor
*
* @param config $config Config object
* @param ContainerInterface $container Service container object
* @param path_helper $path_helper Path helper object
* @param renderer $renderer TextFormatter renderer object
* @param user $user User object
*/
public function __construct(config $config, ContainerInterface $container, path_helper $path_helper, renderer $renderer, user $user)
{
$this->config = $config;
$this->container = $container;
$this->path_helper = $path_helper;
$this->renderer = $renderer;
$this->user = $user;
}
/**
* Returns the board url (and caches it in the function)
*/
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
*
* @param string $content is feed text content
* @param string $uid is bbcode_uid
* @param string $bitfield is bbcode bitfield
* @param int $options bbcode flag options
* @param int $forum_id is the forum id
* @param array $post_attachments is an array containing the attachments and their respective info
* @return string the html content to be printed for the feed
*/
public function generate_content($content, $uid, $bitfield, $options, $forum_id, $post_attachments)
{
if (empty($content))
{
return '';
}
// Setup our own quote_helper to remove all attributes from quotes
$this->renderer->configure_quote_helper($this->container->get('feed.quote_helper'));
$this->renderer->set_smilies_path($this->get_board_url() . '/' . $this->config['smilies_path']);
$content = generate_text_for_display($content, $uid, $bitfield, $options);
// 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);
// Parse inline images to display with the feed
if (!empty($post_attachments))
{
$update_count = array();
parse_attachments($forum_id, $content, $post_attachments, $update_count);
$content .= implode('<br />', $post_attachments);
// Convert attachments' relative path to absolute path
$content = str_replace($this->path_helper->get_web_root_path() . 'download/file.' . $this->path_helper->get_php_ext(), $this->get_board_url() . '/download/file.' . $this->path_helper->get_php_ext(), $content);
}
// Remove Comments from inline attachments [ia]
$content = preg_replace('#<dd>(.*?)</dd>#','',$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;
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* News feed
*
* This will give you {$this->num_items} first posts
* of all topics in the selected news forums.
*/
class news extends topic_base
{
/**
* Returns the ids of the 'news forums'
* @return int[]
*/
private 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;
}
/**
* {@inheritdoc}
*/
protected 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 topic_moved_id = 0
AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $in_fid_ary) . '
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;
}
parent::fetch_attachments($post_ids);
$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_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, 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, p.post_attachment, t.topic_visibility',
'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, p.post_id DESC',
);
return true;
}
}

View File

@ -0,0 +1,94 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Board wide feed (aka overall feed)
*
* This will give you the newest {$this->num_items} posts
* from the whole board.
*/
class overall extends post_base
{
/**
* {@inheritdoc}
*/
protected 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;
}
// Determine topics with recent activity
$sql = 'SELECT topic_id, topic_last_post_time
FROM ' . TOPICS_TABLE . '
WHERE topic_moved_id = 0
AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $forum_ids) . '
ORDER BY topic_last_post_time DESC, topic_last_post_id 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;
}
parent::fetch_attachments(array(), $topic_ids);
// 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_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'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 ' . $this->content_visibility->get_forums_visibility_sql('post', $forum_ids, 'p.') . '
AND p.post_time >= ' . $min_post_time . '
AND u.user_id = p.poster_id',
'ORDER_BY' => 'p.post_time DESC, p.post_id DESC',
);
return true;
}
/**
* {@inheritdoc}
*/
public 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'];
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Abstract class for post based feeds
*/
abstract class post_base extends attachments_base
{
protected $num_items = 'feed_limit_post';
/**
* {@inheritdoc}
*/
public 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');
}
/**
* {@inheritdoc}
*/
public 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']) && (int) $row['post_visibility'] === ITEM_UNAPPROVED) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_UNAPPROVED'] : '')
. (($this->is_moderator_approve_forum($row['forum_id']) && (int) $row['post_visibility'] === ITEM_DELETED) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_DELETED'] : '');
}
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Modified quote_helper for feeds (basically just removing all attributes)
*/
class quote_helper extends \phpbb\textformatter\s9e\quote_helper
{
/**
* {@inheritdoc}
*/
public function inject_metadata($xml)
{
// In feeds we don't want any attributes, so delete all of them
return \s9e\TextFormatter\Utils::replaceAttributes(
$xml,
'QUOTE',
function ()
{
return [];
}
);
}
}

View File

@ -0,0 +1,164 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
use phpbb\feed\exception\no_feed_exception;
use phpbb\feed\exception\no_topic_exception;
use phpbb\feed\exception\unauthorized_forum_exception;
use phpbb\feed\exception\unauthorized_topic_exception;
/**
* Topic feed for a specific topic
*
* This will give you the last {$this->num_items} posts made within this topic.
*/
class topic extends post_base
{
protected $topic_id = 0;
protected $forum_id = 0;
protected $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;
}
/**
* {@inheritdoc}
*/
public function open()
{
$sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_visibility, t.topic_title, t.topic_time, t.topic_views, t.topic_posts_approved, 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))
{
throw new no_topic_exception($this->topic_id);
}
$this->forum_id = (int) $this->topic_data['forum_id'];
// Make sure topic is either approved or user authed
if ($this->topic_data['topic_visibility'] != ITEM_APPROVED && !$this->auth->acl_get('m_approve', $this->forum_id))
{
if ($this->user->data['user_id'] != ANONYMOUS)
{
send_status_line(403, 'Forbidden');
}
else
{
send_status_line(401, 'Unauthorized');
}
throw new unauthorized_topic_exception($this->topic_id);
}
// Make sure forum is not excluded from feed
if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options']))
{
throw new no_feed_exception();
}
// Make sure we can read this forum
if (!$this->auth->acl_get('f_read', $this->forum_id))
{
if ($this->user->data['user_id'] != ANONYMOUS)
{
send_status_line(403, 'Forbidden');
}
else
{
send_status_line(401, 'Unauthorized');
}
throw new unauthorized_forum_exception($this->forum_id);
}
// 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]))
{
if ($this->user->data['user_id'] != ANONYMOUS)
{
send_status_line(403, 'Forbidden');
}
else
{
send_status_line(401, 'Unauthorized');
}
throw new unauthorized_forum_exception($this->forum_id);
}
unset($forum_ids_passworded);
}
parent::open();
}
/**
* {@inheritdoc}
*/
protected function get_sql()
{
parent::fetch_attachments();
$this->sql = array(
'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
USERS_TABLE => 'u',
),
'WHERE' => 'p.topic_id = ' . $this->topic_id . '
AND ' . $this->content_visibility->get_visibility_sql('post', $this->forum_id, 'p.') . '
AND p.poster_id = u.user_id',
'ORDER_BY' => 'p.post_time DESC, p.post_id DESC',
);
return true;
}
/**
* {@inheritdoc}
*/
public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
$item_row['forum_id'] = $this->forum_id;
}
/**
* {@inheritdoc}
*/
public function get_item()
{
return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row;
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* Abstract class for topic based feeds
*/
abstract class topic_base extends attachments_base
{
protected $num_items = 'feed_limit_topic';
/**
* {@inheritdoc}
*/
public 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');
}
/**
* {@inheritdoc}
*/
public 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->content_visibility->get_count('topic_posts', $row, $row['forum_id']) - 1)
. ' ' . $this->separator_stats . ' ' . $this->user->lang['VIEWS'] . ' ' . $row['topic_views'];
if ($this->is_moderator_approve_forum($row['forum_id']))
{
if ((int) $row['topic_visibility'] === ITEM_DELETED)
{
$item_row['statistics'] .= ' ' . $this->separator_stats . ' ' . $this->user->lang['TOPIC_DELETED'];
}
else if ((int) $row['topic_visibility'] === ITEM_UNAPPROVED)
{
$item_row['statistics'] .= ' ' . $this->separator_stats . ' ' . $this->user->lang['TOPIC_UNAPPROVED'];
}
else if ($row['topic_posts_unapproved'])
{
$item_row['statistics'] .= ' ' . $this->separator_stats . ' ' . $this->user->lang['POSTS_UNAPPROVED'];
}
}
}
}
}

View File

@ -0,0 +1,94 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* New Topics feed
*
* This will give you the last {$this->num_items} created topics
* including the first post.
*/
class topics extends topic_base
{
/**
* {@inheritdoc}
*/
protected 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 topic_moved_id = 0
AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $in_fid_ary) . '
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;
}
parent::fetch_attachments($post_ids);
$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_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, 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, p.post_attachment, t.topic_visibility',
'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, p.post_id DESC',
);
return true;
}
/**
* {@inheritdoc}
*/
public 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'];
}
}

View File

@ -0,0 +1,147 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\feed;
/**
* 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.
*/
class topics_active extends topic_base
{
protected $sort_days = 7;
/**
* {@inheritdoc}
*/
public function set_keys()
{
parent::set_keys();
$this->set('author_id', 'topic_last_poster_id');
$this->set('creator', 'topic_last_poster_name');
}
/**
* {@inheritdoc}
*/
protected 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 topic_moved_id = 0
AND ' . $this->content_visibility->get_forums_visibility_sql('topic', $in_fid_ary) . '
' . $last_post_time_sql . '
ORDER BY topic_last_post_time DESC, topic_last_post_id 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;
}
parent::fetch_attachments($post_ids);
$this->sql = array(
'SELECT' => 'f.forum_id, f.forum_name,
t.topic_id, t.topic_title, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, 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, p.post_attachment, t.topic_visibility',
'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, p.post_id DESC',
);
return true;
}
/**
* Returns the ids of the forums not excluded from the active list
*
* @return int[]
*/
private 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', round(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;
}
/**
* {@inheritdoc}
*/
public 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'];
}
}