primo commit

This commit is contained in:
2024-12-17 17:34:10 +01:00
commit e650f8df99
16435 changed files with 2451012 additions and 0 deletions

View File

@ -0,0 +1,60 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Controller;
use Joomla\CMS\MVC\Controller\BaseController;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeeds Component Controller
*
* @since 1.5
*/
class DisplayController extends BaseController
{
/**
* Method to show a newsfeeds view
*
* @param boolean $cachable If true, the view output will be cached
* @param array $urlparams An array of safe URL parameters and their variable types.
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
*
* @return static This object to support chaining.
*
* @since 1.5
*/
public function display($cachable = false, $urlparams = false)
{
$cachable = true;
// Set the default view name and format from the Request.
$vName = $this->input->get('view', 'categories');
$this->input->set('view', $vName);
if ($this->app->getIdentity()->get('id') || ($this->input->getMethod() === 'POST' && $vName === 'category')) {
$cachable = false;
}
$safeurlparams = [
'id' => 'INT',
'limit' => 'UINT',
'limitstart' => 'UINT',
'filter_order' => 'CMD',
'filter_order_Dir' => 'CMD',
'lang' => 'CMD',
];
return parent::display($cachable, $safeurlparams);
}
}

View File

@ -0,0 +1,64 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Helper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Associations;
use Joomla\Component\Categories\Administrator\Helper\CategoryAssociationHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeeds Component Association Helper
*
* @since 3.0
*/
abstract class AssociationHelper extends CategoryAssociationHelper
{
/**
* Method to get the associations for a given item
*
* @param integer $id Id of the item
* @param string $view Name of the view
*
* @return array Array of associations for the item
*
* @since 3.0
*/
public static function getAssociations($id = 0, $view = null)
{
$jinput = Factory::getApplication()->getInput();
$view = $view ?? $jinput->get('view');
$id = empty($id) ? $jinput->getInt('id') : $id;
if ($view === 'newsfeed') {
if ($id) {
$associations = Associations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $id);
$return = [];
foreach ($associations as $tag => $item) {
$return[$tag] = RouteHelper::getNewsfeedRoute($item->id, (int) $item->catid, $item->language);
}
return $return;
}
}
if ($view === 'category' || $view === 'categories') {
return self::getCategoryAssociations($id, 'com_newsfeeds');
}
return [];
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Helper;
use Joomla\CMS\Categories\CategoryNode;
use Joomla\CMS\Language\Multilanguage;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeeds Component Route Helper
*
* @since 1.5
*/
abstract class RouteHelper
{
/**
* getNewsfeedRoute
*
* @param int $id menu itemid
* @param int $catid category id
* @param int $language language
*
* @return string
*/
public static function getNewsfeedRoute($id, $catid, $language = 0)
{
// Create the link
$link = 'index.php?option=com_newsfeeds&view=newsfeed&id=' . $id;
if ((int) $catid > 1) {
$link .= '&catid=' . $catid;
}
if ($language && $language !== '*' && Multilanguage::isEnabled()) {
$link .= '&lang=' . $language;
}
return $link;
}
/**
* getCategoryRoute
*
* @param int $catid category id
* @param int $language language
*
* @return string
*/
public static function getCategoryRoute($catid, $language = 0)
{
if ($catid instanceof CategoryNode) {
$id = $catid->id;
} else {
$id = (int) $catid;
}
if ($id < 1) {
$link = '';
} else {
// Create the link
$link = 'index.php?option=com_newsfeeds&view=category&id=' . $id;
if ($language && $language !== '*' && Multilanguage::isEnabled()) {
$link .= '&lang=' . $language;
}
}
return $link;
}
}

View File

@ -0,0 +1,156 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Model;
use Joomla\CMS\Categories\Categories;
use Joomla\CMS\Categories\CategoryNode;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Registry\Registry;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* This models supports retrieving lists of newsfeed categories.
*
* @since 1.6
*/
class CategoriesModel extends ListModel
{
/**
* Model context string.
*
* @var string
*/
public $_context = 'com_newsfeeds.categories';
/**
* The category context (allows other extensions to derived from this model).
*
* @var string
*/
protected $_extension = 'com_newsfeeds';
/**
* Parent category of the current one
*
* @var CategoryNode|null
*/
private $_parent = null;
/**
* Array of child-categories
*
* @var CategoryNode[]|null
*/
private $_items = null;
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field
* @param string $direction An optional direction [asc|desc]
*
* @return void
*
* @throws \Exception
*
* @since 1.6
*/
protected function populateState($ordering = null, $direction = null)
{
$app = Factory::getApplication();
$this->setState('filter.extension', $this->_extension);
// Get the parent id if defined.
$parentId = $app->getInput()->getInt('id');
$this->setState('filter.parentId', $parentId);
$params = $app->getParams();
$this->setState('params', $params);
$this->setState('filter.published', 1);
$this->setState('filter.access', true);
}
/**
* Method to get a store id based on model configuration state.
*
* This is necessary because the model is used by the component and
* different modules that might need different sets of data or different
* ordering requirements.
*
* @param string $id A prefix for the store id.
*
* @return string A store id.
*/
protected function getStoreId($id = '')
{
// Compile the store id.
$id .= ':' . $this->getState('filter.extension');
$id .= ':' . $this->getState('filter.published');
$id .= ':' . $this->getState('filter.access');
$id .= ':' . $this->getState('filter.parentId');
return parent::getStoreId($id);
}
/**
* redefine the function and add some properties to make the styling easier
*
* @return mixed An array of data items on success, false on failure.
*/
public function getItems()
{
if ($this->_items === null) {
$app = Factory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
if ($active) {
$params = $active->getParams();
} else {
$params = new Registry();
}
$options = [];
$options['countItems'] = $params->get('show_cat_items_cat', 1) || !$params->get('show_empty_categories_cat', 0);
$categories = Categories::getInstance('Newsfeeds', $options);
$this->_parent = $categories->get($this->getState('filter.parentId', 'root'));
if (\is_object($this->_parent)) {
$this->_items = $this->_parent->getChildren();
} else {
$this->_items = false;
}
}
return $this->_items;
}
/**
* get the Parent
*
* @return null
*/
public function getParent()
{
if (!\is_object($this->_parent)) {
$this->getItems();
}
return $this->_parent;
}
}

View File

@ -0,0 +1,413 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Model;
use Joomla\CMS\Categories\Categories;
use Joomla\CMS\Categories\CategoryNode;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\TagsHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\CMS\Table\Table;
use Joomla\Database\ParameterType;
use Joomla\Database\QueryInterface;
use Joomla\Registry\Registry;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeeds Component Category Model
*
* @since 1.5
*/
class CategoryModel extends ListModel
{
/**
* Category items data
*
* @var array
*/
protected $_item;
/**
* Array of newsfeeds in the category
*
* @var \stdClass[]
*/
protected $_articles;
/**
* Category left and right of this one
*
* @var CategoryNode[]|null
*/
protected $_siblings;
/**
* Array of child-categories
*
* @var CategoryNode[]|null
*/
protected $_children;
/**
* Parent category of the current one
*
* @var CategoryNode|null
*/
protected $_parent;
/**
* The category that applies.
*
* @var object
*/
protected $_category;
/**
* The list of other newsfeed categories.
*
* @var array
*/
protected $_categories;
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
* @param ?MVCFactoryInterface $factory The factory.
*
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
* @since 3.2
*/
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
{
if (empty($config['filter_fields'])) {
$config['filter_fields'] = [
'id', 'a.id',
'name', 'a.name',
'numarticles', 'a.numarticles',
'link', 'a.link',
'ordering', 'a.ordering',
];
}
parent::__construct($config, $factory);
}
/**
* Method to get a list of items.
*
* @return mixed An array of objects on success, false on failure.
*/
public function getItems()
{
// Invoke the parent getItems method to get the main list
$items = parent::getItems();
$taggedItems = [];
// Convert the params field into an object, saving original in _params
foreach ($items as $item) {
if (!isset($this->_params)) {
$item->params = new Registry($item->params);
}
// Some contexts may not use tags data at all, so we allow callers to disable loading tag data
if ($this->getState('load_tags', true)) {
$item->tags = new TagsHelper();
$taggedItems[$item->id] = $item;
}
}
// Load tags of all items.
if ($taggedItems) {
$tagsHelper = new TagsHelper();
$itemIds = array_keys($taggedItems);
foreach ($tagsHelper->getMultipleItemTags('com_newsfeeds.newsfeed', $itemIds) as $id => $tags) {
$taggedItems[$id]->tags->itemTags = $tags;
}
}
return $items;
}
/**
* Method to build an SQL query to load the list data.
*
* @return QueryInterface An SQL query
*
* @since 1.6
*/
protected function getListQuery()
{
$user = $this->getCurrentUser();
$groups = $user->getAuthorisedViewLevels();
// Create a new query object.
$db = $this->getDatabase();
$query = $db->getQuery(true);
// Select required fields from the categories.
$query->select($this->getState('list.select', $db->quoteName('a') . '.*'))
->from($db->quoteName('#__newsfeeds', 'a'))
->whereIn($db->quoteName('a.access'), $groups);
// Filter by category.
if ($categoryId = (int) $this->getState('category.id')) {
$query->where($db->quoteName('a.catid') . ' = :categoryId')
->join('LEFT', $db->quoteName('#__categories', 'c'), $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid'))
->whereIn($db->quoteName('c.access'), $groups)
->bind(':categoryId', $categoryId, ParameterType::INTEGER);
}
// Filter by state
$state = $this->getState('filter.published');
if (is_numeric($state)) {
$state = (int) $state;
$query->where($db->quoteName('a.published') . ' = :state')
->bind(':state', $state, ParameterType::INTEGER);
} else {
$query->where($db->quoteName('a.published') . ' IN (0,1,2)');
}
// Filter by start and end dates.
if ($this->getState('filter.publish_date')) {
$nowDate = Factory::getDate()->toSql();
$query->extendWhere(
'AND',
[
$db->quoteName('a.publish_up') . ' IS NULL',
$db->quoteName('a.publish_up') . ' <= :nowDate1',
],
'OR'
)
->extendWhere(
'AND',
[
$db->quoteName('a.publish_down') . ' IS NULL',
$db->quoteName('a.publish_down') . ' >= :nowDate2',
],
'OR'
)
->bind([':nowDate1', ':nowDate2'], $nowDate);
}
// Filter by search in title
if ($search = $this->getState('list.filter')) {
$search = '%' . $search . '%';
$query->where($db->quoteName('a.name') . ' LIKE :search')
->bind(':search', $search);
}
// Filter by language
if ($this->getState('filter.language')) {
$query->whereIn($db->quoteName('a.language'), [Factory::getApplication()->getLanguage()->getTag(), '*'], ParameterType::STRING);
}
// Add the list ordering clause.
$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
return $query;
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field
* @param string $direction An optional direction [asc|desc]
*
* @return void
*
* @since 1.6
*
* @throws \Exception
*/
protected function populateState($ordering = null, $direction = null)
{
$app = Factory::getApplication();
$input = $app->getInput();
$params = $app->getParams();
$this->setState('params', $params);
// List state information
$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
$this->setState('list.limit', $limit);
$limitstart = $input->get('limitstart', 0, 'uint');
$this->setState('list.start', $limitstart);
// Optional filter text
$this->setState('list.filter', $input->getString('filter-search'));
$orderCol = $input->get('filter_order', 'ordering');
if (!\in_array($orderCol, $this->filter_fields)) {
$orderCol = 'ordering';
}
$this->setState('list.ordering', $orderCol);
$listOrder = $input->get('filter_order_Dir', 'ASC');
if (!\in_array(strtoupper($listOrder), ['ASC', 'DESC', ''])) {
$listOrder = 'ASC';
}
$this->setState('list.direction', $listOrder);
$id = $input->get('id', 0, 'int');
$this->setState('category.id', $id);
$user = $this->getCurrentUser();
if ((!$user->authorise('core.edit.state', 'com_newsfeeds')) && (!$user->authorise('core.edit', 'com_newsfeeds'))) {
// Limit to published for people who can't edit or edit.state.
$this->setState('filter.published', 1);
// Filter by start and end dates.
$this->setState('filter.publish_date', true);
}
$this->setState('filter.language', Multilanguage::isEnabled());
}
/**
* Method to get category data for the current category
*
* @return object
*
* @since 1.5
*/
public function getCategory()
{
if (!\is_object($this->_item)) {
$app = Factory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
if ($active) {
$params = $active->getParams();
} else {
$params = new Registry();
}
$options = [];
$options['countItems'] = $params->get('show_cat_items', 1) || $params->get('show_empty_categories', 0);
$categories = Categories::getInstance('Newsfeeds', $options);
$this->_item = $categories->get($this->getState('category.id', 'root'));
if (\is_object($this->_item)) {
$this->_children = $this->_item->getChildren();
$this->_parent = false;
if ($this->_item->getParent()) {
$this->_parent = $this->_item->getParent();
}
$this->_rightsibling = $this->_item->getSibling();
$this->_leftsibling = $this->_item->getSibling(false);
} else {
$this->_children = false;
$this->_parent = false;
}
}
return $this->_item;
}
/**
* Get the parent category.
*
* @return mixed An array of categories or false if an error occurs.
*/
public function getParent()
{
if (!\is_object($this->_item)) {
$this->getCategory();
}
return $this->_parent;
}
/**
* Get the sibling (adjacent) categories.
*
* @return mixed An array of categories or false if an error occurs.
*/
public function &getLeftSibling()
{
if (!\is_object($this->_item)) {
$this->getCategory();
}
return $this->_leftsibling;
}
/**
* Get the sibling (adjacent) categories.
*
* @return mixed An array of categories or false if an error occurs.
*/
public function &getRightSibling()
{
if (!\is_object($this->_item)) {
$this->getCategory();
}
return $this->_rightsibling;
}
/**
* Get the child categories.
*
* @return mixed An array of categories or false if an error occurs.
*/
public function &getChildren()
{
if (!\is_object($this->_item)) {
$this->getCategory();
}
return $this->_children;
}
/**
* Increment the hit counter for the category.
*
* @param int $pk Optional primary key of the category to increment.
*
* @return boolean True if successful; false otherwise and internal error set.
*/
public function hit($pk = 0)
{
$input = Factory::getApplication()->getInput();
$hitcount = $input->getInt('hitcount', 1);
if ($hitcount) {
$pk = (!empty($pk)) ? $pk : (int) $this->getState('category.id');
$table = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\');
$table->hit($pk);
}
return true;
}
}

View File

@ -0,0 +1,225 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Model;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\ItemModel;
use Joomla\Database\ParameterType;
use Joomla\Registry\Registry;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeeds Component Newsfeed Model
*
* @since 1.5
*/
class NewsfeedModel extends ItemModel
{
/**
* Model context string.
*
* @var string
* @since 1.6
*/
protected $_context = 'com_newsfeeds.newsfeed';
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return void
*
* @since 1.6
*/
protected function populateState()
{
$app = Factory::getApplication();
// Load state from the request.
$pk = $app->getInput()->getInt('id');
$this->setState('newsfeed.id', $pk);
$offset = $app->getInput()->get('limitstart', 0, 'uint');
$this->setState('list.offset', $offset);
// Load the parameters.
$params = $app->getParams();
$this->setState('params', $params);
$user = $this->getCurrentUser();
if ((!$user->authorise('core.edit.state', 'com_newsfeeds')) && (!$user->authorise('core.edit', 'com_newsfeeds'))) {
$this->setState('filter.published', 1);
$this->setState('filter.archived', 2);
}
}
/**
* Method to get newsfeed data.
*
* @param integer $pk The id of the newsfeed.
*
* @return mixed Menu item data object on success, false on failure.
*
* @since 1.6
*/
public function &getItem($pk = null)
{
$pk = (int) $pk ?: (int) $this->getState('newsfeed.id');
if ($this->_item === null) {
$this->_item = [];
}
if (!isset($this->_item[$pk])) {
try {
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select(
[
$this->getState('item.select', $db->quoteName('a') . '.*'),
$db->quoteName('c.title', 'category_title'),
$db->quoteName('c.alias', 'category_alias'),
$db->quoteName('c.access', 'category_access'),
$db->quoteName('u.name', 'author'),
$db->quoteName('parent.title', 'parent_title'),
$db->quoteName('parent.id', 'parent_id'),
$db->quoteName('parent.path', 'parent_route'),
$db->quoteName('parent.alias', 'parent_alias'),
]
)
->from($db->quoteName('#__newsfeeds', 'a'))
->join('LEFT', $db->quoteName('#__categories', 'c'), $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid'))
->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('a.created_by'))
->join('LEFT', $db->quoteName('#__categories', 'parent'), $db->quoteName('parent.id') . ' = ' . $db->quoteName('c.parent_id'))
->where($db->quoteName('a.id') . ' = :id')
->bind(':id', $pk, ParameterType::INTEGER);
// Filter by published state.
$published = $this->getState('filter.published');
$archived = $this->getState('filter.archived');
if (is_numeric($published)) {
// Filter by start and end dates.
$nowDate = Factory::getDate()->toSql();
$published = (int) $published;
$archived = (int) $archived;
$query->extendWhere(
'AND',
[
$db->quoteName('a.published') . ' = :published1',
$db->quoteName('a.published') . ' = :archived1',
],
'OR'
)
->extendWhere(
'AND',
[
$db->quoteName('a.publish_up') . ' IS NULL',
$db->quoteName('a.publish_up') . ' <= :nowDate1',
],
'OR'
)
->extendWhere(
'AND',
[
$db->quoteName('a.publish_down') . ' IS NULL',
$db->quoteName('a.publish_down') . ' >= :nowDate2',
],
'OR'
)
->extendWhere(
'AND',
[
$db->quoteName('c.published') . ' = :published2',
$db->quoteName('c.published') . ' = :archived2',
],
'OR'
)
->bind([':published1', ':published2'], $published, ParameterType::INTEGER)
->bind([':archived1', ':archived2'], $archived, ParameterType::INTEGER)
->bind([':nowDate1', ':nowDate2'], $nowDate);
}
$db->setQuery($query);
$data = $db->loadObject();
if ($data === null) {
throw new \Exception(Text::_('COM_NEWSFEEDS_ERROR_FEED_NOT_FOUND'), 404);
}
// Check for published state if filter set.
if ((is_numeric($published) || is_numeric($archived)) && $data->published != $published && $data->published != $archived) {
throw new \Exception(Text::_('COM_NEWSFEEDS_ERROR_FEED_NOT_FOUND'), 404);
}
// Convert parameter fields to objects.
$registry = new Registry($data->params);
$data->params = clone $this->getState('params');
$data->params->merge($registry);
$data->metadata = new Registry($data->metadata);
// Compute access permissions.
if ($access = $this->getState('filter.access')) {
// If the access filter has been set, we already know this user can view.
$data->params->set('access-view', true);
} else {
// If no access filter is set, the layout takes some responsibility for display of limited information.
$user = $this->getCurrentUser();
$groups = $user->getAuthorisedViewLevels();
$data->params->set('access-view', \in_array($data->access, $groups) && \in_array($data->category_access, $groups));
}
$this->_item[$pk] = $data;
} catch (\Exception $e) {
$this->setError($e);
$this->_item[$pk] = false;
}
}
return $this->_item[$pk];
}
/**
* Increment the hit counter for the newsfeed.
*
* @param int $pk Optional primary key of the item to increment.
*
* @return boolean True if successful; false otherwise and internal error set.
*
* @since 3.0
*/
public function hit($pk = 0)
{
$input = Factory::getApplication()->getInput();
$hitcount = $input->getInt('hitcount', 1);
if ($hitcount) {
$pk = (!empty($pk)) ? $pk : (int) $this->getState('newsfeed.id');
$table = $this->getTable('Newsfeed', 'Administrator');
$table->hit($pk);
}
return true;
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Service;
use Joomla\CMS\Categories\Categories;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeed Component Category Tree
*
* @since 1.6
*/
class Category extends Categories
{
/**
* Constructor
*
* @param array $options options
*/
public function __construct($options = [])
{
$options['table'] = '#__newsfeeds';
$options['extension'] = 'com_newsfeeds';
$options['statefield'] = 'published';
parent::__construct($options);
}
}

View File

@ -0,0 +1,268 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\Service;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Categories\CategoryFactoryInterface;
use Joomla\CMS\Categories\CategoryInterface;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Component\Router\RouterView;
use Joomla\CMS\Component\Router\RouterViewConfiguration;
use Joomla\CMS\Component\Router\Rules\MenuRules;
use Joomla\CMS\Component\Router\Rules\NomenuRules;
use Joomla\CMS\Component\Router\Rules\StandardRules;
use Joomla\CMS\Menu\AbstractMenu;
use Joomla\Database\DatabaseInterface;
use Joomla\Database\ParameterType;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Routing class from com_newsfeeds
*
* @since 3.3
*/
class Router extends RouterView
{
/**
* Flag to remove IDs
*
* @var boolean
*/
protected $noIDs = false;
/**
* The category factory
*
* @var CategoryFactoryInterface
*
* @since 4.0.0
*/
private $categoryFactory;
/**
* The category cache
*
* @var array
*
* @since 4.0.0
*/
private $categoryCache = [];
/**
* The db
*
* @var DatabaseInterface
*
* @since 4.0.0
*/
private $db;
/**
* Newsfeeds Component router constructor
*
* @param SiteApplication $app The application object
* @param AbstractMenu $menu The menu object to work with
* @param CategoryFactoryInterface $categoryFactory The category object
* @param DatabaseInterface $db The database object
*/
public function __construct(SiteApplication $app, AbstractMenu $menu, CategoryFactoryInterface $categoryFactory, DatabaseInterface $db)
{
$this->categoryFactory = $categoryFactory;
$this->db = $db;
$params = ComponentHelper::getParams('com_newsfeeds');
$this->noIDs = (bool) $params->get('sef_ids');
$categories = new RouterViewConfiguration('categories');
$categories->setKey('id');
$this->registerView($categories);
$category = new RouterViewConfiguration('category');
$category->setKey('id')->setParent($categories, 'catid')->setNestable();
$this->registerView($category);
$newsfeed = new RouterViewConfiguration('newsfeed');
$newsfeed->setKey('id')->setParent($category, 'catid');
$this->registerView($newsfeed);
parent::__construct($app, $menu);
$this->attachRule(new MenuRules($this));
$this->attachRule(new StandardRules($this));
$this->attachRule(new NomenuRules($this));
}
/**
* Method to get the segment(s) for a category
*
* @param string $id ID of the category to retrieve the segments for
* @param array $query The request that is built right now
*
* @return array|string The segments of this item
*/
public function getCategorySegment($id, $query)
{
$category = $this->getCategories()->get($id);
if ($category) {
$path = array_reverse($category->getPath(), true);
$path[0] = '1:root';
if ($this->noIDs) {
foreach ($path as &$segment) {
list($id, $segment) = explode(':', $segment, 2);
}
}
return $path;
}
return [];
}
/**
* Method to get the segment(s) for a category
*
* @param string $id ID of the category to retrieve the segments for
* @param array $query The request that is built right now
*
* @return array|string The segments of this item
*/
public function getCategoriesSegment($id, $query)
{
return $this->getCategorySegment($id, $query);
}
/**
* Method to get the segment(s) for a newsfeed
*
* @param string $id ID of the newsfeed to retrieve the segments for
* @param array $query The request that is built right now
*
* @return array|string The segments of this item
*/
public function getNewsfeedSegment($id, $query)
{
if (!strpos($id, ':')) {
$id = (int) $id;
$dbquery = $this->db->getQuery(true);
$dbquery->select($this->db->quoteName('alias'))
->from($this->db->quoteName('#__newsfeeds'))
->where($this->db->quoteName('id') . ' = :id')
->bind(':id', $id, ParameterType::INTEGER);
$this->db->setQuery($dbquery);
$id .= ':' . $this->db->loadResult();
}
if ($this->noIDs) {
list($void, $segment) = explode(':', $id, 2);
return [$void => $segment];
}
return [(int) $id => $id];
}
/**
* Method to get the id for a category
*
* @param string $segment Segment to retrieve the ID for
* @param array $query The request that is parsed right now
*
* @return mixed The id of this item or false
*/
public function getCategoryId($segment, $query)
{
if (isset($query['id'])) {
$category = $this->getCategories(['access' => false])->get($query['id']);
if ($category) {
foreach ($category->getChildren() as $child) {
if ($this->noIDs) {
if ($child->alias === $segment) {
return $child->id;
}
} else {
if ($child->id == (int) $segment) {
return $child->id;
}
}
}
}
}
return false;
}
/**
* Method to get the segment(s) for a category
*
* @param string $segment Segment to retrieve the ID for
* @param array $query The request that is parsed right now
*
* @return mixed The id of this item or false
*/
public function getCategoriesId($segment, $query)
{
return $this->getCategoryId($segment, $query);
}
/**
* Method to get the segment(s) for a newsfeed
*
* @param string $segment Segment of the newsfeed to retrieve the ID for
* @param array $query The request that is parsed right now
*
* @return mixed The id of this item or false
*/
public function getNewsfeedId($segment, $query)
{
if ($this->noIDs) {
$dbquery = $this->db->getQuery(true);
$dbquery->select($this->db->quoteName('id'))
->from($this->db->quoteName('#__newsfeeds'))
->where($this->db->quoteName('alias') . ' = :segment')
->bind(':segment', $segment);
if (isset($query['id']) && $query['id']) {
$dbquery->where($this->db->quoteName('catid') . ' = :id')
->bind(':id', $query['id'], ParameterType::INTEGER);
}
$this->db->setQuery($dbquery);
return (int) $this->db->loadResult();
}
return (int) $segment;
}
/**
* Method to get categories from cache
*
* @param array $options The options for retrieving categories
*
* @return CategoryInterface The object containing categories
*
* @since 4.0.0
*/
private function getCategories(array $options = []): CategoryInterface
{
$key = serialize($options);
if (!isset($this->categoryCache[$key])) {
$this->categoryCache[$key] = $this->categoryFactory->createCategory($options);
}
return $this->categoryCache[$key];
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\View\Categories;
use Joomla\CMS\MVC\View\CategoriesView;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Newsfeed categories view.
*
* @since 1.5
*/
class HtmlView extends CategoriesView
{
/**
* Language key for default page heading
*
* @var string
* @since 3.2
*/
protected $pageHeading = 'COM_NEWSFEEDS_DEFAULT_PAGE_TITLE';
/**
* @var string The name of the extension for the category
* @since 3.2
*/
protected $extension = 'com_newsfeeds';
}

View File

@ -0,0 +1,106 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\View\Category;
use Joomla\CMS\MVC\View\CategoryView;
use Joomla\Component\Newsfeeds\Site\Helper\RouteHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* HTML View class for the Newsfeeds component
*
* @since 1.0
*/
class HtmlView extends CategoryView
{
/**
* @var string Default title to use for page title
* @since 3.2
*/
protected $defaultPageTitle = 'COM_NEWSFEEDS_DEFAULT_PAGE_TITLE';
/**
* @var string The name of the extension for the category
* @since 3.2
*/
protected $extension = 'com_newsfeeds';
/**
* @var string The name of the view to link individual items to
* @since 3.2
*/
protected $viewName = 'newsfeed';
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
*
* @return void
*/
public function display($tpl = null)
{
$this->commonCategoryDisplay();
// Flag indicates to not add limitstart=0 to URL
$this->pagination->hideEmptyLimitstart = true;
// Prepare the data.
// Compute the newsfeed slug.
foreach ($this->items as $item) {
$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
$temp = $item->params;
$item->params = clone $this->params;
$item->params->merge($temp);
}
parent::display($tpl);
}
/**
* Prepares the document
*
* @return void
*/
protected function prepareDocument()
{
parent::prepareDocument();
$menu = $this->menu;
$id = (int) @$menu->query['id'];
if (
$menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] === 'newsfeed'
|| $id != $this->category->id)
) {
$path = [['title' => $this->category->title, 'link' => '']];
$category = $this->category->getParent();
while (
isset($category->id) && $category->id > 1
&& (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] === 'newsfeed'
|| $id != $category->id)
) {
$path[] = ['title' => $category->title, 'link' => RouteHelper::getCategoryRoute($category->id, $category->language)];
$category = $category->getParent();
}
$path = array_reverse($path);
foreach ($path as $item) {
$this->pathway->addItem($item['title'], $item['link']);
}
}
}
}

View File

@ -0,0 +1,308 @@
<?php
/**
* @package Joomla.Site
* @subpackage com_newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Component\Newsfeeds\Site\View\Newsfeed;
use Joomla\CMS\Categories\Categories;
use Joomla\CMS\Factory;
use Joomla\CMS\Feed\FeedFactory;
use Joomla\CMS\Helper\TagsHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\GenericDataException;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\Component\Newsfeeds\Site\Helper\RouteHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* HTML View class for the Newsfeeds component
*
* @since 1.0
*/
class HtmlView extends BaseHtmlView
{
/**
* The model state
*
* @var object
*
* @since 1.6
*/
protected $state;
/**
* The newsfeed item
*
* @var object
*
* @since 1.6
*/
protected $item;
/**
* UNUSED?
*
* @var boolean
*
* @since 1.6
*/
protected $print;
/**
* The current user instance
*
* @var \Joomla\CMS\User\User|null
*
* @since 4.0.0
*/
protected $user = null;
/**
* The page class suffix
*
* @var string
*
* @since 4.0.0
*/
protected $pageclass_sfx = '';
/**
* The page parameters
*
* @var \Joomla\Registry\Registry|null
*
* @since 4.0.0
*/
protected $params;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
*
* @return void
*
* @since 1.6
*/
public function display($tpl = null)
{
$app = Factory::getApplication();
$user = $this->getCurrentUser();
// Get view related request variables.
$print = $app->getInput()->getBool('print');
// Get model data.
$state = $this->get('State');
$item = $this->get('Item');
// Check for errors.
// @TODO: Maybe this could go into ComponentHelper::raiseErrors($this->get('Errors'))
if (\count($errors = $this->get('Errors'))) {
throw new GenericDataException(implode("\n", $errors), 500);
}
// Add router helpers.
$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
$item->catslug = $item->category_alias ? ($item->catid . ':' . $item->category_alias) : $item->catid;
$item->parent_slug = $item->category_alias ? ($item->parent_id . ':' . $item->parent_alias) : $item->parent_id;
// Merge newsfeed params. If this is single-newsfeed view, menu params override newsfeed params
// Otherwise, newsfeed params override menu item params
$params = $state->get('params');
$newsfeed_params = clone $item->params;
$active = $app->getMenu()->getActive();
$temp = clone $params;
// Check to see which parameters should take priority
if ($active) {
$currentLink = $active->link;
// If the current view is the active item and a newsfeed view for this feed, then the menu item params take priority
if (strpos($currentLink, 'view=newsfeed') && strpos($currentLink, '&id=' . (string) $item->id)) {
// $item->params are the newsfeed params, $temp are the menu item params
// Merge so that the menu item params take priority
$newsfeed_params->merge($temp);
$item->params = $newsfeed_params;
// Load layout from active query (in case it is an alternative menu item)
if (isset($active->query['layout'])) {
$this->setLayout($active->query['layout']);
}
} else {
// Current view is not a single newsfeed, so the newsfeed params take priority here
// Merge the menu item params with the newsfeed params so that the newsfeed params take priority
$temp->merge($newsfeed_params);
$item->params = $temp;
// Check for alternative layouts (since we are not in a single-newsfeed menu item)
if ($layout = $item->params->get('newsfeed_layout')) {
$this->setLayout($layout);
}
}
} else {
// Merge so that newsfeed params take priority
$temp->merge($newsfeed_params);
$item->params = $temp;
// Check for alternative layouts (since we are not in a single-newsfeed menu item)
if ($layout = $item->params->get('newsfeed_layout')) {
$this->setLayout($layout);
}
}
// Check the access to the newsfeed
$levels = $user->getAuthorisedViewLevels();
if (!\in_array($item->access, $levels) || (\in_array($item->access, $levels) && (!\in_array($item->category_access, $levels)))) {
$app->enqueueMessage(Text::_('JERROR_ALERTNOAUTHOR'), 'error');
$app->setHeader('status', 403, true);
return;
}
// Get the current menu item
$params = $app->getParams();
$params->merge($item->params);
try {
$feed = new FeedFactory();
$this->rssDoc = $feed->getFeed($item->link);
} catch (\InvalidArgumentException $e) {
$msg = Text::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
} catch (\RuntimeException $e) {
$msg = Text::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
}
if (empty($this->rssDoc)) {
$msg = Text::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
}
$feed_display_order = $params->get('feed_display_order', 'des');
if ($feed_display_order === 'asc') {
$this->rssDoc->reverseItems();
}
// Escape strings for HTML output
$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));
$this->params = $params;
$this->state = $state;
$this->item = $item;
$this->user = $user;
if (!empty($msg)) {
$this->msg = $msg;
}
$this->print = $print;
$item->tags = new TagsHelper();
$item->tags->getItemTags('com_newsfeeds.newsfeed', $item->id);
// Increment the hit counter of the newsfeed.
if (\in_array($app->getInput()->getMethod(), ['GET', 'POST'])) {
$model = $this->getModel();
$model->hit();
}
$this->_prepareDocument();
parent::display($tpl);
}
/**
* Prepares the document
*
* @return void
*
* @since 1.6
*/
protected function _prepareDocument()
{
$app = Factory::getApplication();
$pathway = $app->getPathway();
// Because the application sets a default page title,
// we need to get it from the menu item itself
$menu = $app->getMenu()->getActive();
if ($menu) {
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
} else {
$this->params->def('page_heading', Text::_('COM_NEWSFEEDS_DEFAULT_PAGE_TITLE'));
}
$title = $this->params->get('page_title', '');
$id = (int) @$menu->query['id'];
// If the menu item does not concern this newsfeed
if (
$menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] !== 'newsfeed'
|| $id != $this->item->id)
) {
// If this is not a single newsfeed menu item, set the page title to the newsfeed title
if ($this->item->name) {
$title = $this->item->name;
}
$path = [['title' => $this->item->name, 'link' => '']];
$category = Categories::getInstance('Newsfeeds')->get($this->item->catid);
while (
isset($category->id) && $category->id > 1
&& (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] === 'newsfeed'
|| $id != $category->id)
) {
$path[] = ['title' => $category->title, 'link' => RouteHelper::getCategoryRoute($category->id)];
$category = $category->getParent();
}
$path = array_reverse($path);
foreach ($path as $item) {
$pathway->addItem($item['title'], $item['link']);
}
}
if (empty($title)) {
$title = $this->item->name;
}
$this->setDocumentTitle($title);
if ($this->item->metadesc) {
$this->getDocument()->setDescription($this->item->metadesc);
} elseif ($this->params->get('menu-meta_description')) {
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
}
if ($this->params->get('robots')) {
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
}
if ($app->get('MetaAuthor') == '1') {
$this->getDocument()->setMetaData('author', $this->item->author);
}
$mdata = $this->item->metadata->toArray();
foreach ($mdata as $k => $v) {
if ($v) {
$this->getDocument()->setMetaData($k, $v);
}
}
}
}