Commit df2d50e9 authored by Tino Goratsch's avatar Tino Goratsch

Squashed 'ACP3/Modules/ACP3/News/' content from commit f84dd52

git-subtree-dir: ACP3/Modules/ACP3/News
git-subtree-split: f84dd52fffbc70ec7c8e7a35c8eda6a71403c7c0
parents
.idea
vendor/
<?php
namespace ACP3\Modules\ACP3\News;
use ACP3\Core;
/**
* Class Cache
* @package ACP3\Modules\ACP3\News
*/
class Cache extends Core\Modules\AbstractCacheStorage
{
const CACHE_ID = 'details_id_';
/**
* @var Model
*/
protected $newsModel;
/**
* @param Core\Cache $cache
* @param Model $newsModel
*/
public function __construct(
Core\Cache $cache,
Model $newsModel
) {
parent::__construct($cache);
$this->newsModel = $newsModel;
}
/**
* Bindet die gecachete News ein
*
* @param integer $id
* Die ID der News
*
* @return array
*/
public function getCache($id)
{
if ($this->cache->contains(self::CACHE_ID . $id) === false) {
$this->setCache($id);
}
return $this->cache->fetch(self::CACHE_ID . $id);
}
/**
* Erstellt den Cache einer News anhand der angegebenen ID
*
* @param integer $id
* Die ID der News
*
* @return boolean
*/
public function setCache($id)
{
return $this->cache->save(self::CACHE_ID . $id, $this->newsModel->getOneById($id));
}
}
This diff is collapsed.
<?php
namespace ACP3\Modules\ACP3\News\Controller;
use ACP3\Core;
use ACP3\Modules\ACP3\Categories;
use ACP3\Modules\ACP3\News;
/**
* Class Index
* @package ACP3\Modules\ACP3\News\Controller
*/
class Index extends Core\Modules\Controller\Frontend
{
/**
* @var Core\Date
*/
protected $date;
/**
* @var \Doctrine\DBAL\Connection
*/
protected $db;
/**
* @var Core\Pagination
*/
protected $pagination;
/**
* @var News\Model
*/
protected $newsModel;
/**
* @var News\Cache
*/
protected $newsCache;
/**
* @var array
*/
protected $newsSettings;
/**
* @var \ACP3\Modules\ACP3\Categories\Helpers
*/
protected $categoriesHelpers;
/**
* @var Categories\Model
*/
protected $categoriesModel;
/**
* @var bool
*/
protected $commentsActive;
/**
* @param \ACP3\Core\Context\Frontend $context
* @param \ACP3\Core\Date $date
* @param \ACP3\Core\Pagination $pagination
* @param \ACP3\Modules\ACP3\News\Model $newsModel
* @param \ACP3\Modules\ACP3\News\Cache $newsCache
* @param \ACP3\Modules\ACP3\Categories\Helpers $categoriesHelpers
* @param \ACP3\Modules\ACP3\Categories\Model $categoriesModel
*/
public function __construct(
Core\Context\Frontend $context,
Core\Date $date,
Core\Pagination $pagination,
News\Model $newsModel,
News\Cache $newsCache,
Categories\Helpers $categoriesHelpers,
Categories\Model $categoriesModel)
{
parent::__construct($context);
$this->date = $date;
$this->pagination = $pagination;
$this->newsModel = $newsModel;
$this->newsCache = $newsCache;
$this->categoriesHelpers = $categoriesHelpers;
$this->categoriesModel = $categoriesModel;
}
public function preDispatch()
{
parent::preDispatch();
$this->newsSettings = $this->config->getSettings('news');
$this->commentsActive = ($this->newsSettings['comments'] == 1 && $this->acl->hasPermission('frontend/comments') === true);
}
public function actionDetails()
{
if ($this->get('core.validator.rules.misc')->isNumber($this->request->id) === true &&
$this->newsModel->resultExists($this->request->id, $this->date->getCurrentDateTime()) == 1
) {
$news = $this->newsCache->getCache($this->request->id);
$this->breadcrumb->append($this->lang->t('news', 'news'), 'news');
if ($this->newsSettings['category_in_breadcrumb'] == 1) {
$this->breadcrumb->append($news['category_title'], 'news/index/index/cat_' . $news['category_id']);
}
$this->breadcrumb->append($news['title']);
if (!empty($news['uri']) && (bool)preg_match('=^http(s)?://=', $news['uri']) === false) {
$news['uri'] = 'http://' . $news['uri'];
}
$news['target'] = $news['target'] == 2 ? ' target="_blank"' : '';
$this->view->assign('news', $news);
$this->view->assign('dateformat', $this->newsSettings['dateformat']);
if ($this->commentsActive === true && $news['comments'] == 1) {
/** @var \ACP3\Modules\ACP3\Comments\Controller\Index $comments */
$comments = $this->get('comments.controller.frontend.index');
$comments
->setModule('news')
->setEntryId($this->request->id);
$this->view->assign('comments', $comments->actionIndex());
}
} else {
throw new Core\Exceptions\ResultNotExists();
}
}
public function actionIndex()
{
if (isset($_POST['cat']) && $this->get('core.validator.rules.misc')->isNumber($_POST['cat']) === true) {
$cat = (int)$_POST['cat'];
} elseif ($this->get('core.validator.rules.misc')->isNumber($this->request->cat) === true) {
$cat = (int)$this->request->cat;
} else {
$cat = 0;
}
$this->view->assign('categories', $this->categoriesHelpers->categoriesList('news', $cat));
// Kategorie in Brotkrümelspur anzeigen
if ($cat !== 0 && $this->newsSettings['category_in_breadcrumb'] == 1) {
$this->seo->setCanonicalUri($this->router->route('news'));
$this->breadcrumb->append($this->lang->t('news', 'news'), 'news');
$category = $this->categoriesModel->getTitleById($cat);
if (!empty($category)) {
$this->breadcrumb->append($category);
}
}
$time = $this->date->getCurrentDateTime();
// Falls Kategorie angegeben, News nur aus eben dieser selektieren
if (!empty($cat)) {
$news = $this->newsModel->getAllByCategoryId($cat, $time, POS, $this->auth->entries);
} else {
$news = $this->newsModel->getAll($time, POS, $this->auth->entries);
}
$c_news = count($news);
if ($c_news > 0) {
$this->pagination->setTotalResults($this->newsModel->countAll($time, $cat));
$this->pagination->display();
$formatter = $this->get('core.helpers.stringFormatter');
for ($i = 0; $i < $c_news; ++$i) {
if ($this->commentsActive === true && $news[$i]['comments'] == 1) {
$news[$i]['comments_count'] = $this->get('comments.helpers')->commentsCount('news', $news[$i]['id']);
}
if ($this->newsSettings['readmore'] == 1 && $news[$i]['readmore'] == 1) {
$news[$i]['text'] = $formatter->shortenEntry($news[$i]['text'], $this->newsSettings['readmore_chars'], 50, '...<a href="' . $this->router->route('news/details/id_' . $news[$i]['id']) . '">[' . $this->lang->t('news', 'readmore') . "]</a>\n");
}
}
$this->view->assign('news', $news);
$this->view->assign('dateformat', $this->newsSettings['dateformat']);
}
}
}
<?php
namespace ACP3\Modules\ACP3\News\Controller\Sidebar;
use ACP3\Core;
use ACP3\Modules\ACP3\News;
/**
* Class Index
* @package ACP3\Modules\ACP3\News\Controller\Sidebar
*/
class Index extends Core\Modules\Controller
{
/**
* @var Core\Date
*/
protected $date;
/**
* @var News\Model
*/
protected $newsModel;
/**
* @param \ACP3\Core\Context $context
* @param \ACP3\Core\Date $date
* @param \ACP3\Modules\ACP3\News\Model $newsModel
*/
public function __construct(
Core\Context $context,
Core\Date $date,
News\Model $newsModel)
{
parent::__construct($context);
$this->date = $date;
$this->newsModel = $newsModel;
}
/**
* @param int $categoryId
* @param string $template
*/
public function actionIndex($categoryId = 0, $template = '')
{
$settings = $this->config->getSettings('news');
if (!empty($categoryId)) {
$news = $this->newsModel->getAllByCategoryId((int)$categoryId, $this->date->getCurrentDateTime(), $settings['sidebar']);
} else {
$news = $this->newsModel->getAll($this->date->getCurrentDateTime(), $settings['sidebar']);
}
$this->view->assign('sidebar_news', $news);
$this->view->assign('dateformat', $settings['dateformat']);
$this->setTemplate($template !== '' ? $template : 'News/Sidebar/index.index.tpl');
}
/**
* @param int $categoryId
*/
public function actionLatest($categoryId = 0)
{
$settings = $this->config->getSettings('news');
if (!empty($categoryId)) {
$news = $this->newsModel->getLatestByCategoryId((int)$categoryId, $this->date->getCurrentDateTime());
} else {
$news = $this->newsModel->getLatest($this->date->getCurrentDateTime());
}
$this->view->assign('sidebar_news_latest', $news);
$this->view->assign('dateformat', $settings['dateformat']);
$this->setTemplate('News/Sidebar/index.latest.tpl');
}
}
<?php
namespace ACP3\Modules\ACP3\News;
use ACP3\Core;
/**
* Class Helpers
* @package ACP3\Modules\ACP3\News
*/
class Helpers
{
const URL_KEY_PATTERN = 'news/index/details/id_%s/';
}
<?php
namespace ACP3\Modules\ACP3\News;
use ACP3\Core\Modules;
/**
* Class Installer
* @package ACP3\Modules\ACP3\News
*/
class Installer extends Modules\AbstractInstaller
{
const MODULE_NAME = 'news';
const SCHEMA_VERSION = 35;
/**
* @inheritdoc
*/
public function createTables()
{
return [
"CREATE TABLE `{pre}news` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`start` DATETIME NOT NULL,
`end` DATETIME NOT NULL,
`title` VARCHAR(120) NOT NULL,
`text` TEXT NOT NULL,
`readmore` TINYINT(1) UNSIGNED NOT NULL,
`comments` TINYINT(1) UNSIGNED NOT NULL,
`category_id` INT(10) UNSIGNED NOT NULL,
`uri` VARCHAR(120) NOT NULL,
`target` TINYINT(1) UNSIGNED NOT NULL,
`link_title` VARCHAR(120) NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`), FULLTEXT KEY `index` (`title`,`text`), INDEX `foreign_category_id` (`category_id`)
) {engine} {charset};"
];
}
/**
* @inheritdoc
*/
public function removeTables()
{
return [
"DROP TABLE `{pre}news`;",
"DELETE FROM `{pre}categories` WHERE `module_id` = " . $this->getModuleId() . ";"
];
}
/**
* @inheritdoc
*/
public function settings()
{
return [
'comments' => 1,
'dateformat' => 'long',
'readmore' => 1,
'readmore_chars' => 350,
'sidebar' => 5,
'category_in_breadcrumb' => 1
];
}
/**
* @inheritdoc
*/
public function schemaUpdates()
{
return [
31 => [
"ALTER TABLE `{pre}news` CHANGE `headline` `title` VARCHAR(120) {charset} NOT NULL",
],
32 => [
"DELETE FROM `{pre}acl_resources` WHERE `module_id` = " . $this->getModuleId() . " AND `page` = \"extensions/search\";",
"DELETE FROM `{pre}acl_resources` WHERE `module_id` = " . $this->getModuleId() . " AND `page` = \"extensions/feeds\";",
"DELETE FROM `{pre}acl_resources` WHERE `module_id` = " . $this->getModuleId() . " AND `page` = \"functions\";",
],
33 => [
'UPDATE `{pre}seo` SET `uri`=REPLACE(`uri`, "news/", "news/index/") WHERE `uri` LIKE "news/%";',
],
34 => [
$this->moduleIsInstalled('menus') || $this->moduleIsInstalled('menu_items') ? 'UPDATE `{pre}menu_items` SET `uri`=REPLACE(`uri`, "news/list/", "news/index/index/") WHERE `uri` LIKE "news/list/%";' : '',
$this->moduleIsInstalled('menus') || $this->moduleIsInstalled('menu_items') ? 'UPDATE `{pre}menu_items` SET `uri`=REPLACE(`uri`, "news/details/", "news/index/details/") WHERE `uri` LIKE "news/details/%";' : '',
],
35 => [
"INSERT INTO `{pre}acl_resources` (`id`, `module_id`, `area`, `controller`, `page`, `params`, `privilege_id`) VALUES('', " . $this->getModuleId() . ", 'sidebar', 'index', 'latest', '', 1);",
]
];
}
}
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<language>
<info>
<name>Deutsch (Deutschland)</name>
<direction>ltr</direction>
</info>
<keys>
<item key="activate_readmore">&quot;Weiterlesen...&quot; aktivieren</item>
<item key="admin_index_create">Neue News erstellen</item>
<item key="admin_index_delete">News löschen</item>
<item key="admin_index_edit">News bearbeiten</item>
<item key="admin_index_settings">Einstellungen</item>
<item key="hyperlink">Link</item>
<item key="complete_hyperlink_statements">Bitte vervollständigen Sie die Angaben zum Hyperlink</item>
<item key="details">News</item>
<item key="display_category_in_breadcrumb">Kategorie in Brotkrümelspur anzeigen</item>
<item key="latest_news">Aktuelle News</item>
<item key="link_title">Linkbezeichnung</item>
<item key="mod_description">Mit diesem Modul können die News verwaltet werden.</item>
<item key="news">News</item>
<item key="read_newsfeed">Newsfeed ansehen</item>
<item key="readmore">weiterlesen</item>
<item key="readmore_chars"><![CDATA[Benötigte Anzahl an Zeichen für &quot;weiterlesen...&quot;-Funktion]]></item>
<item key="select_activate_readmore">
<![CDATA[Bitte wählen Sie aus, ob die &quot;weiterlesen...&quot;-Funktion aktiviert werden soll oder nicht]]></item>
<item key="select_allow_comments">Bitte wählen Sie aus, ob Kommentare unter News zugelassen werden sollen oder
nicht
</item>
<item key="select_category">Bitte wählen Sie die Kategorie aus, in der sich die News befinden soll</item>
<item key="select_display_category_in_breadcrumb">Bitte wählen Sie aus, ob der Kategoriename einer News in der
Brotkrümelspur angezeigt werden soll.
</item>
<item key="target_page">Zielseite</item>
<item key="text">Text</item>
<item key="text_to_short">Der Text sollte mindestens 3 Zeichen lang sein</item>
<item key="title">Titel</item>
<item key="title_to_short">Der Titel sollte mindestens 3 Zeichen lang sein</item>
<item key="type_in_readmore_chars">
<![CDATA[Bitte geben Sie ein, wie viele Zeichen die News mindestens haben muss, um die &quot;weiterlesen...&quot;-Funktion zu aktivieren]]></item>
<item key="uri">URI</item>
</keys>
</language>
<?xml version="1.0" encoding="UTF-8"?>
<language>
<info>
<name>English (United States)</name>
<direction>ltr</direction>
</info>
<keys>
<item key="admin_index_create">Create new news</item>
<item key="admin_index_delete">Delete news</item>
<item key="admin_index_edit">Edit news</item>
<item key="admin_index_settings">Settings</item>
<item key="activate_readmore">Activate &quot;read more...&quot;</item>
<item key="hyperlink">Link</item>
<item key="complete_hyperlink_statements">Please complete the information of the hyperlink.</item>
<item key="details">News</item>
<item key="display_category_in_breadcrumb">Display category in breadcrumb</item>
<item key="latest_news">Latest news</item>
<item key="link_title">Link title</item>
<item key="mod_description">With this module you can administer the news.</item>
<item key="news">News</item>
<item key="read_newsfeed">Read newsfeed</item>
<item key="readmore">read more</item>
<item key="readmore_chars"><![CDATA[Characters required, to enable the &quot;read more...&quot;-function]]></item>
<item key="select_activate_readmore">
<![CDATA[Please select whether you want to enable or disable the &quot;read more...&quot;-function.]]></item>
<item key="select_allow_comments">Please select whether you want to allow comments under news or not.</item>
<item key="select_category">Please select the category where do you want to find the news.</item>
<item key="select_display_category_in_breadcrumb">Please select whether you want to display the category name of a
news in the breadcrumb or not.
</item>
<item key="target_page">Target page</item>
<item key="text">Text</item>
<item key="text_to_short">The news text should be at least 3 characters long.</item>
<item key="title">Title</item>
<item key="title_to_short">The title should be at least 3 characters long.</item>
<item key="type_in_readmore_chars">
<![CDATA[Please specify how many characters a news needs to have to enable the &quot;read more...&quot;-function.]]></item>
<item key="uri">URI</item>
</keys>
</language>
<?php
namespace ACP3\Modules\ACP3\News;
use ACP3\Core;
/**
* Class Model
* @package ACP3\Modules\ACP3\News
*/
class Model extends Core\Model
{
const TABLE_NAME = 'news';
/**
* @return string
*/
protected function _getPeriod()
{
return '(start = end AND start <= :time OR start != end AND :time BETWEEN start AND end)';
}
/**
* @param $id
* @param string $time
* @return bool
*/
public function resultExists($id, $time = '')
{
$period = empty($time) === false ? ' AND ' . $this->_getPeriod() : '';
return ((int)$this->db->fetchColumn('SELECT COUNT(*) FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE id = :id' . $period, ['id' => $id, 'time' => $time]) > 0);
}
/**
* @param $id
* @return array
*/
public function getOneById($id)
{
return $this->db->fetchAssoc('SELECT n.*, c.title AS category_title FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' AS n LEFT JOIN ' . $this->db->getPrefix() . \ACP3\Modules\ACP3\Categories\Model::TABLE_NAME . ' AS c ON(n.category_id = c.id) WHERE n.id = ?', [$id]);
}
/**
* @param string $time
* @param string $categoryId
* @return int
*/
public function countAll($time = '', $categoryId = '')
{
if (!empty($categoryId)) {
$where = empty($time) === false ? ' AND ' . $this->_getPeriod() : '';
return $this->db->fetchColumn('SELECT COUNT(*) FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE category_id = :categoryId' . $where . ' ORDER BY start DESC, end DESC, id DESC', ['time' => $time, 'categoryId' => $categoryId]);
} else {
$where = empty($time) === false ? ' WHERE ' . $this->_getPeriod() : '';
return $this->db->fetchColumn('SELECT COUNT(*) FROM ' . $this->db->getPrefix() . static::TABLE_NAME . $where . ' ORDER BY start DESC, end DESC, id DESC', ['time' => $time]);
}
}
/**
* @param $categoryId
* @param string $time
* @param string $limitStart
* @param string $resultsPerPage
* @return array
*/
public function getAllByCategoryId($categoryId, $time = '', $limitStart = '', $resultsPerPage = '')
{
$where = empty($time) === false ? ' AND ' . $this->_getPeriod() : '';
$limitStmt = $this->_buildLimitStmt($limitStart, $resultsPerPage);
return $this->db->fetchAll('SELECT * FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE category_id = :categoryId' . $where . ' ORDER BY start DESC, end DESC, id DESC' . $limitStmt, ['time' => $time, 'categoryId' => $categoryId]);
}
/**
* @param string $time
* @param string $limitStart
* @param string $resultsPerPage
* @return array
*/
public function getAll($time = '', $limitStart = '', $resultsPerPage = '')
{
$where = empty($time) === false ? ' WHERE ' . $this->_getPeriod() : '';
$limitStmt = $this->_buildLimitStmt($limitStart, $resultsPerPage);
return $this->db->fetchAll('SELECT * FROM ' . $this->db->getPrefix() . static::TABLE_NAME . $where . ' ORDER BY start DESC, end DESC, id DESC' . $limitStmt, ['time' => $time]);
}
/**
* @return array
*/
public function getAllInAcp()
{
return $this->db->fetchAll('SELECT n.*, c.title AS cat FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' AS n, ' . $this->db->getPrefix() . \ACP3\Modules\ACP3\Categories\Model::TABLE_NAME . ' AS c WHERE n.category_id = c.id ORDER BY n.start DESC, n.end DESC, n.id DESC');
}
/**
* @param $fields
* @param $searchTerm
* @param $sort
* @param $time
* @return array
*/
public function getAllSearchResults($fields, $searchTerm, $sort, $time)
{
$period = ' AND ' . $this->_getPeriod();
return $this->db->fetchAll('SELECT id, title, text FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE MATCH (' . $fields . ') AGAINST (' . $this->db->getConnection()->quote($searchTerm) . ' IN BOOLEAN MODE)' . $period . ' ORDER BY start ' . $sort . ', end ' . $sort . ', id ' . $sort, ['time' => $time]);
}
/**
* @param $categoryId
* @param $time
*
* @return mixed
*/
public function getLatestByCategoryId($categoryId, $time)
{
$period = ' AND ' . $this->_getPeriod();
return $this->db->fetchAssoc('SELECT * FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE category_id = :category_id ' . $period . ' ORDER BY start DESC LIMIT 1', ['category_id' => $categoryId, 'time' => $time]);
}
/**
* @param $time
*
* @return mixed
*/
public function getLatest($time)
{
return $this->db->fetchAssoc('SELECT * FROM ' . $this->db->getPrefix() . static::TABLE_NAME . ' WHERE ' . $this->_getPeriod() . ' ORDER BY start DESC LIMIT 1', ['time' => $time]);
}
}
jQuery(document).ready(function ($) {
$('input[name="readmore"]').on('click',function () {
var $elem = $('#readmore-container');
if ($(this).val() == 1) {
$elem.show();
} else {
$elem.hide();
}
}).filter(':checked').click();
});
{extends file="asset:layout.tpl"}
{block CONTENT}
{if isset($error_msg)}
{$error_msg}
{/if}
<form action="{$REQUEST_URI}" method="post" accept-charset="UTF-8" class="form-horizontal" data-ajax-form="true" data-ajax-form-loading-text="{lang t="system|loading_please_wait"}">
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active"><a href="#tab-1" data-toggle="tab">{lang t="system|publication_period"}</a></li>
<li><a href="#tab-2" data-toggle="tab">{lang t="news|news"}</a></li>
<li><a href="#tab-3" data-toggle="tab">{lang t="news|hyperlink"}</a></li>
<li><a href="#tab-4" data-toggle="tab">{lang t="seo|seo"}</a></li>
</ul>
<div class="tab-content">
<div id="tab-1" class="tab-pane fade in active">
{include file="asset:system/datepicker.tpl" datepicker=$publication_period}
</div>
<div id="tab-2" class="tab-pane fade">
<div class="form-group">
<label for="title" class="col-sm-2 control-label">{lang t="news|title"}</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="title" id="title" value="{$form.title}" maxlength="120">
</div>
</div>
<div class="form-group">
<label for="text" class="col-sm-2 control-label">{lang t="news|text"}</label>
<div class="col-sm-10">{wysiwyg name="text" value="`$form.text`" height="250"}</div>
</div>
<div class="form-group">
<label for="cat" class="col-sm-2 control-label">{lang t="categories|category"}</label>
<div class="col-sm-10">{$categories}</div>
</div>
{if isset($options)}
<div class="form-group">
<label for="{$options.0.name}" class="col-sm-2 control-label">{lang t="system|options"}</label>
<div class="col-sm-10">
{foreach $options as $row}
<div class="checkbox">
<label for="{$row.name}">
<input type="checkbox" name="{$row.name}" id="{$row.name}" value="1"{$row.checked}>
{$row.lang}
</label>
</div>
{/foreach}
</div>
</div>
{/if}
</div>
<div id="tab-3" class="tab-pane fade">
<div class="form-group">
<label for="link-title" class="col-sm-2 control-label">{lang t="news|link_title"}</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="link_title" id="link-title" value="{$form.link_title}" maxlength="120">
</div>
</div>
<div class="form-group">
<label for="link-uri" class="col-sm-2 control-label">{lang t="news|uri"}</label>
<div class="col-sm-10">
<input class="form-control" type="url" name="uri" id="link-uri" value="{$form.uri}" maxlength="120">
</div>
</div>