You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1040 lines
35 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
class RSSLib extends TikiDb_Bridge
{
private $items;
private $feeds;
private $modules;
private bool $updateArticles = true;
public function __construct()
{
$this->items = $this->table('tiki_rss_items');
$this->feeds = $this->table('tiki_rss_feeds');
$this->modules = $this->table('tiki_rss_modules');
}
public function enableUpdateArticles() {
$this->updateArticles = true;
}
public function disableUpdateArticles() {
$this->updateArticles = false;
}
// ------------------------------------
// functions for rss feeds we syndicate
// ------------------------------------
/**
* Return the feed format name
*
* @return string feed format name
*/
public function get_current_feed_format_name()
{
$ver = $this->get_current_feed_format();
if ($ver == '2') {
$name = 'rss';
} elseif ($ver == '5') {
$name = 'atom';
}
return $name;
}
/**
* Return the feed format code (2 for rss and 5 for atom)
* we currently use (user param or default value)
*
* @return int $ver
*/
public function get_current_feed_format()
{
global $prefs;
if (isset($_REQUEST['ver'])) {
$ver = $_REQUEST['ver'];
} else {
$ver = $prefs['feed_default_version'];
}
return $ver;
}
/* check for cached rss feed data */
public function get_from_cache($uniqueid, $rss_version = "9")
{
global $tikilib, $user, $prefs;
$rss_version = $this->get_current_feed_format();
$output = [];
$output["content-type"] = "application/xml";
$output["encoding"] = "UTF-8";
$output["data"] = "EMPTY";
// caching rss data for anonymous users only
if (isset($user) && $user <> "") {
return $output;
}
$res = $this->feeds->fetchFullRow(['name' => $uniqueid, 'rssVer' => $rss_version]);
if (! $res) {
// nothing found, then insert empty row for this feed+rss_ver
$this->feeds->insert(
[
'name' => $uniqueid,
'rssVer' => $rss_version,
'refresh' => (int) $prefs['feed_cache_time'],
'lastUpdated' => 1,
'cache' => '-',
]
);
} else {
// entry found in db:
$output["data"] = $res["cache"];
// $refresh = $res["refresh"]; // global cache time currently
$refresh = $prefs['feed_cache_time']; // global cache time currently
$lastUpdated = $res["lastUpdated"];
// up to date? if not, then set trigger to reload data:
if ($tikilib->now - $lastUpdated >= $refresh) {
$output["data"] = "EMPTY";
}
}
$output['content-type'] = 'application/xml';
return $output;
}
/* put to cache */
public function put_to_cache($uniqueid, $rss_version, $output)
{
global $user, $tikilib;
// caching rss data for anonymous users only
if (isset($user) && $user <> "") {
return;
}
if ($output == "" || $output == "EMPTY") {
return;
}
$rss_version = $rss_version ?? $this->get_current_feed_format();
// update cache with new generated data if data not empty
$this->feeds->update(
[
'cache' => $output,
'lastUpdated' => $tikilib->now,
],
[
'name' => $uniqueid,
'rssVer' => $rss_version,
]
);
}
/**
* Generate a feed (ATOM 1.0 or RSS 2.0 using Laminas\Feed\Writer\Feed
*
* @param string $section Tiki feature the feed is related to
* @param string $uniqueid
* @param string $feed_version DEPRECATED
* @param array $changes the content that will be used to generate the feed
* @param string $itemurl base url for items (e.g. "tiki-view_blog_post.php?postId=%s")
* @param string $urlparam
* @param string $id name of the id field used to identify each feed item (e.g. "postId")
* @param string $title title for the feed
* @param string $titleId name of the key in the $changes array with the title of each item
* @param string $desc description for the feed
* @param string $descId name of the key in the $changes array with the description of each item
* @param string $dateId name of the key in the $changes array with the date of each item
* @param string $authorId name of the key in the $changes array with the author of each item
* @param bool $fromcache if true recover the feed from cache
*
* @return array the generated feed
*/
public function generate_feed($section, $uniqueid, $feed_version, $changes, $itemurl, $urlparam, $id, $title, $titleId, $desc, $descId, $dateId, $authorId, $fromcache = false)
{
global $tiki_p_admin, $prefs;
$userlib = TikiLib::lib('user');
$tikilib = TikiLib::lib('tiki');
$smarty = TikiLib::lib('smarty');
// both title and description fields cannot be null
if (empty($title) || empty($desc)) {
$msg = tra('The title and description must be entered, to generate a feed.');
if ($tiki_p_admin) {
$msg .= ' ' . tra('To fix this error go to Admin -> Feeds.');
} else {
$msg .= ' ' . tra('Please contact the site administrator and request this error to be corrected');
}
$smarty->assign('msg', $msg);
$smarty->display('error.tpl');
die;
}
$feed_format = $this->get_current_feed_format();
$feed_format_name = $this->get_current_feed_format_name();
if ($prefs['feed_cache_time'] < 1) {
$fromcache = false;
}
// only get cache data if rss cache is enabled
if ($fromcache) {
$output = $this->get_from_cache($uniqueid, $feed_format);
if ($output['data'] != 'EMPTY') {
return $output;
}
}
$urlarray = parse_url($_SERVER["REQUEST_URI"]);
$rawPath = str_replace('\\', '/', dirname($urlarray["path"]));
$URLPrefix = $tikilib->httpPrefix() . $rawPath;
if ($rawPath != "/") {
$URLPrefix .= "/"; // Append a slash unless Tiki is in the document root. dirname() removes a slash except in that case.
}
if (isset($prefs['feed_' . $section . '_index']) && $prefs['feed_' . $section . '_index'] != '') {
$feedLink = $prefs['feed_' . $section . '_index'];
} else {
$feedLink = htmlspecialchars($tikilib->httpPrefix() . $_SERVER["REQUEST_URI"]);
}
$img = htmlspecialchars($URLPrefix . $prefs['feed_img']);
$title = htmlspecialchars($title);
$desc = htmlspecialchars($desc);
$read = $URLPrefix . $itemurl;
$feed = new Laminas\Feed\Writer\Feed();
$feed->setTitle($title);
$feed->setDescription($desc);
if (! empty($prefs['feed_language'])) {
$feed->setLanguage($prefs['feed_language']);
}
$feed->setLink($tikilib->tikiUrl(''));
$feed->setFeedLink($feedLink, $feed_format_name);
$feed->setDateModified($tikilib->now);
if ($feed_format_name == 'atom') {
$author = [];
if (! empty($prefs['feed_atom_author_name'])) {
$author['name'] = $prefs['feed_atom_author_name'];
}
if (! empty($prefs['feed_atom_author_email'])) {
$author['email'] = $prefs['feed_atom_author_email'];
}
if (! empty($prefs['feed_atom_author_url'])) {
$author['url'] = $prefs['feed_atom_author_url'];
}
if (! empty($author)) {
if (empty($author['name'])) {
$msg = tra('If you set feed author email or URL, you must set feed author name.');
$smarty->assign('msg', $msg);
$smarty->display('error.tpl');
die;
}
$feed->addAuthor($author);
}
} else {
$authors = [];
if (! empty($prefs['feed_rss_editor_email'])) {
$authors['name'] = $prefs['feed_rss_editor_email'];
}
if (! empty($prefs['feed_rss_webmaster_email'])) {
$authors['name'] = $prefs['feed_rss_webmaster_email'];
}
if (! empty($authors)) {
$feed->addAuthors([$authors]);
}
}
if (! empty($prefs['feed_img'])) {
$image = [];
$image['uri'] = $tikilib->tikiUrl($prefs['feed_img']);
$image['title'] = tra('Feed logo');
$image['link'] = $tikilib->tikiUrl('');
$feed->setImage($image);
}
foreach ($changes["data"] as $data) {
$item = $feed->createEntry();
if (empty($data[$titleId]) || ! is_string($data[$titleId])) {
$data[$titleId] = tra('No title specified');
}
$item->setTitle($data[$titleId]);
if (isset($data['sefurl'])) {
$item->setLink($URLPrefix . urlencode($data['sefurl']));
} elseif ($urlparam != '') { // 2 parameters to replace
$item->setlink(sprintf($read, urlencode($data["$id"]), urlencode($data["$urlparam"])));
} else {
$item->setLink(sprintf($read, urlencode($data["$id"])));
}
if (isset($data[$descId]) && $data[$descId] != '') {
$item->setDescription($data[$descId]);
}
$item->setDateCreated((int) $data[$dateId]);
$item->setDateModified((int) $data[$dateId]);
if ($authorId != '' && $prefs['feed_' . $section . '_showAuthor'] == 'y') {
$author = $this->process_item_author($data[$authorId]);
if (array_key_exists('name', $author) && ! empty($author['name']) && is_string($author['name'])) {
$item->addAuthor($author);
}
}
$feed->addEntry($item);
}
$data = $feed->export($feed_format_name);
$this->put_to_cache($uniqueid, $feed_format, $data);
$output = [];
$output["data"] = $data;
$output["content-type"] = 'application/xml';
return $output;
}
/**
* Return information about the user acording to its preferences
*
* @param string $login
* @return array author data (can be the login name or the realName if set and email if public)
*/
public function process_item_author($login)
{
$userlib = TikiLib::lib('user');
$tikilib = TikiLib::lib('tiki');
$author = [];
if ($userlib->user_exists($login) && $tikilib->get_user_preference($login, 'user_information', 'private') == 'public') {
// if realName is not set use $login
$author['name'] = $tikilib->get_user_preference($login, 'realName', $login);
if ($tikilib->get_user_preference($login, 'email is public', 'n') != 'n') {
$res = $userlib->get_user_info($login, false);
$author['email'] = TikiMail::scrambleEmail($res['email']);
}
} else {
$author['name'] = $login;
}
return $author;
}
// --------------------------------------------
// functions for rss feeds syndicated by others
// --------------------------------------------
/* get (a part of) the list of existing rss feeds from db */
public function list_rss_modules($offset = 0, $maxRecords = null, $sort_mode = 'name_asc', $find = '')
{
global $prefs;
$conditions = [];
if ($maxRecords === null) {
$maxRecords = $prefs['maxRecords'];
}
if ($find) {
$conditions['search'] = $this->modules->expr('(`name` LIKE ? OR `description` LIKE ?)', ["%$find%", "%$find%"]);
}
$ret = $this->modules->fetchAll($this->modules->all(), $conditions, $maxRecords, $offset, $this->modules->sortMode($sort_mode));
foreach ($ret as & $res) {
$res["minutes"] = $res["refresh"] / 60;
}
return [
'data' => $ret,
'cant' => $this->modules->fetchCount($conditions),
];
}
/* replace rss feed in db */
public function replace_rss_module($rssId, $name, $description, $url, $refresh, $showTitle, $showPubDate, $noUpdate = false)
{
//if ($this->rss_module_name_exists($name)) return false; // TODO: Check the name
$refresh = 60 * $refresh;
$data = [
'name' => $name,
'description' => $description,
'refresh' => $refresh,
'url' => $url,
'showTitle' => $showTitle,
'showPubDate' => $showPubDate,
];
if ($rssId) {
$this->modules->update($data, ['rssId' => (int) $rssId,]);
} else {
$data['lastUpdated'] = 1;
$rssId = $this->modules->insert($data);
}
if (! $noUpdate) {
// Updating is normally required, except for cases where we know it will be updated later (e.g. after article generation is set, so that articles are created immediately)
$this->refresh_rss_module($rssId);
}
return $rssId;
}
/* remove rss feed from db */
public function remove_rss_module($rssId)
{
$resultModule = $this->modules->delete(['rssId' => $rssId,]);
$resultItems = $this->items->deleteMultiple(['rssId' => $rssId,]);
return ['feed' => $resultModule, 'items' => $resultItems];
}
/* read rss feed data from db */
public function get_rss_module($rssId)
{
return $this->modules->fetchFullRow(['rssId' => $rssId]);
}
/**
* @param $rssId
*
* @return mixed
*/
public function refresh_rss_module($rssId)
{
return $this->update_feeds([ $rssId ], true);
}
/**
* @return array
* @throws Exception
*/
public function refresh_all_rss_modules()
{
$mods = $this->list_rss_modules(0, -1);
$feeds = [];
foreach ($mods['data'] as $mod) {
$feeds[] = $mod['rssId'];
}
return $this->update_feeds($feeds, true);
}
/**
* @param int $rssId feed id
* @param int $olderThan publication date more than than this number of seconds ago
*
* @return TikiDb_Adodb_Result|TikiDb_Pdo_Result
*/
public function clear_rss_cache($rssId, $olderThan = 0)
{
$conditions = ['rssId' => (int)$rssId];
if ($olderThan) {
$conditions['publication_date'] = $this->items->lesserThan(time() - $olderThan);
}
return $this->items->deleteMultiple($conditions);
}
/* check if an rss feed name already exists */
public function rss_module_name_exists($name)
{
return $this->modules->fetchCount(['name' => $name]);
}
/* get rss feed id by name */
public function get_rss_module_id($name)
{
return $this->modules->fetchOne('rssId', ['name' => $name]);
}
/* check if 'showTitle' for an rss feed is enabled */
public function get_rss_showTitle($rssId)
{
return $this->modules->fetchOne('showTitle', ['rssId' => $rssId]);
}
/* check if 'showPubdate' for an rss feed is enabled */
public function get_rss_showPubDate($rssId)
{
return $this->modules->fetchOne('showPubDate', ['rssId' => $rssId]);
}
public function get_feed_items($feeds, $count = 10)
{
$feeds = (array) $feeds;
$this->update_feeds($feeds);
return $this->items->fetchAll(
$this->items->all(),
['rssId' => $this->items->in($feeds),],
$count,
0,
['publication_date' => 'DESC']
);
}
/**
* @param $feeds
* @param bool $force
* @param bool $updateArticles
*
* @return array
* @throws Exception
*/
private function update_feeds($feeds, $force = false)
{
global $tikilib;
$conditions = ['rssId' => $this->modules->in($feeds),];
if (! $force) {
$conditions['date'] = $this->modules->expr('`lastUpdated` < ? - `refresh`', [$tikilib->now]);
}
$result = $this->modules->fetchAll(['rssId', 'url', 'actions'], $conditions);
$feedResult['feeds'] = count($result);
$entryReturn = ['feed' => 0, 'articles' => 0, 'feedData' => []];
foreach ($result as $row) {
$entryResult = $this->update_feed($row['rssId'], $row['url'], $row['actions']);
if (! empty($entryResult['feed'])) {
$entryReturn['feed'] += $entryResult['feed'];
}
if ($this->updateArticles && ! empty($entryResult['articles'])) {
$entryReturn['articles'] += $entryResult['articles'];
}
if (! empty($entryResult['feedData'])) {
$entryReturn['feedData'] = array_merge($entryReturn['feedData'], $entryResult['feedData']);
}
}
$feedResult['entries'] = $entryReturn;
return $feedResult;
}
/**
* @param $rssId
* @param $url
* @param $actions
*
* @return array
* @throws Exception
*/
private function update_feed($rssId, $url, $actions)
{
global $tikilib;
$filter = new DeclFilter();
$filter->addStaticKeyFilters(
[
'url' => 'url',
'title' => 'striptags',
'author' => 'striptags',
'description' => 'striptags',
'content' => 'purifier',
]
);
$guidFilter = TikiFilter::get('url');
$success = ['feed' => 0, 'articles' => 0, 'feedData' => []];
try {
$content = $tikilib->httprequest($url);
$feed = Laminas\Feed\Reader\Reader::importString($content);
} catch (Laminas\Feed\Exception\ExceptionInterface $e) {
$this->modules->update(
[
'lastUpdated' => $tikilib->now,
'sitetitle' => 'N/A',
'siteurl' => '#',
],
['rssId' => $rssId,]
);
return $success;
}
$siteTitle = TikiFilter::get('striptags')->filter($feed->getTitle());
$siteUrl = TikiFilter::get('url')->filter($feed->getLink());
$this->modules->update(
[
'lastUpdated' => $tikilib->now,
'sitetitle' => $siteTitle,
'siteurl' => $siteUrl,
],
['rssId' => $rssId,]
);
$DOM = new DOMDocument();
foreach ($feed as $entry) { // TODO: optimize. Atom entries have an 'updated' element which can be used to only update updated entries
$guid = $guidFilter->filter($entry->getId());
$authors = $entry->getAuthors();
$categories = $entry->getCategories();
$link = $entry->getLink();
if (! $link) {
$link = '';
}
$description = $entry->getDescription();
if (! $description) {
$description = '';
}
$data = $filter->filter(
[
'title' => $entry->getTitle(),
'url' => $link,
'description' => $description,
'content' => $entry->getContent(),
'author' => $authors ? implode(', ', $authors->getValues()) : '',
'categories' => $categories ? json_encode($categories->getValues()) : json_encode([]),
'language' => TikiFilter::get('striptags')->filter($feed->getLanguage()),
]
);
$data['guid'] = $guid;
if (method_exists($entry, 'getDateCreated') && $createdDate = $entry->getDateCreated()) {
$data['publication_date'] = $createdDate->getTimestamp();
} else {
global $tikilib;
$data['publication_date'] = $tikilib->now;
}
$htmlContent = $entry->getContent();
@$DOM->loadHTML($htmlContent);
$rows = $DOM->getElementsByTagName('tr');
foreach ($rows as $row) {
$cols = $row->getElementsByTagName('td');
if (isset($cols[0]) && $cols[1]) {
$data[str_replace(' ', '', $cols[0]->textContent)] = $cols[1]->textContent;
}
}
array_push($success['feedData'], $data);
if (! $this->updateArticles) {
continue;
}
$count = $this->items->fetchCount(['rssId' => $rssId, 'guid' => $guid]);
if (0 == $count) {
$result = $this->insert_item($rssId, $data, $actions);
if (! empty($result['feed'])) {
$success['feed']++;
}
if (! empty($result['articles'])) {
$success['articles']++;
}
} else {
$result = $this->update_item($rssId, $data['guid'], $data);
if ($result && $result->numrows()) {
$success['feed']++;
}
}
}
return $success;
}
public function get_feed_source_categories($rssId)
{
$feeds = $this->items->fetchAll(['categories'], ['rssId' => $rssId]);
$categories = [];
foreach ($feeds as $feed) {
if (isset($feed['categories'])) {
foreach (json_decode($feed['categories']) as $sourcecat) {
$categories[$sourcecat] = [];
}
}
}
$custom_info = $this->get_article_custom_info($rssId);
$categories = array_merge($categories, $custom_info);
ksort($categories, SORT_NATURAL);
return $categories;
}
public function get_article_custom_info($rssId)
{
$result = $this->modules->fetchOne('actions', ['rssId' => $rssId]);
$actions = json_decode($result);
$categories = [];
foreach ($actions as $action) {
if (isset($action->custom_atype)) {
foreach ($action->custom_atype as $source_category => $atype) {
$categories[$source_category]['atype'] = $atype;
}
}
if (isset($action->custom_topic)) {
foreach ($action->custom_topic as $source_category => $topic) {
$categories[$source_category]['topic'] = $topic;
}
}
if (isset($action->custom_rating)) {
foreach ($action->custom_rating as $source_category => $rating) {
$categories[$source_category]['rating'] = $rating;
}
}
if (isset($action->custom_priority)) {
foreach ($action->custom_priority as $source_category => $priority) {
$categories[$source_category]['priority'] = $priority;
}
}
}
return $categories;
}
/**
* @param $rssId
* @param $data
* @param $actions
*
* @return array|bool|mixed
* @throws Exception
*/
private function insert_item($rssId, $data, $actions)
{
$result = $this->items->insert(
[
'rssId' => $rssId,
'guid' => $data['guid'],
'url' => $data['url'],
'publication_date' => $data['publication_date'],
'title' => $data['title'],
'author' => $data['author'],
'description' => $data['description'],
'content' => $data['content'],
'categories' => $data['categories'],
]
);
$actions = json_decode($actions, true);
//currently handles creation of articles through process_action_article()
if (! empty($actions)) {
$pagecontentlib = TikiLib::lib('pagecontent');
$data = $pagecontentlib->augmentInformation($data);
$actionCount = 0;
foreach ($actions as $action) {
$method = 'process_action_' . $action['type'];
unset($action['type']);
if ($action['active']) {
$actionId = $this->$method($action, $data, $rssId);
if (! empty($actionId) && is_numeric($actionId)) {
$actionCount++;
}
}
}
}
return ['feed' => $result, 'articles' => $actionCount];
}
private function update_item($rssId, $guid, $data)
{
// A feed may contain several entries with the same GUID... see http://framework.zend.com/issues/browse/ZF-10954. Assuming a single record would actually cause issues, see r37318.
return $this->items->updateMultiple(
['rssId' => $rssId, 'guid' => $guid,],
[
'url' => $data['url'],
'publication_date' => $data['publication_date'],
'title' => $data['title'],
'author' => $data['author'],
'description' => $data['description'],
'content' => $data['content'],
]
);
}
private function process_action_article($configuration, $data, $rssId)
{
$tikilib = TikiLib::lib('tiki');
$artlib = TikiLib::lib('art');
$publication = $data['publication_date'];
// First override with custom settings for source categories if any
if (isset($data['categories'])) {
$source_categories = json_decode($data['categories'], true);
}
if (! empty($source_categories)) {
$custominfo = $this->get_article_custom_info($rssId);
$oldcats = array_keys($custominfo);
if ($newcats = array_diff($source_categories, $oldcats)) {
// send a notification if there are new categories
$nots = $tikilib->get_event_watches('article_submitted', '*');
if (count($nots)) {
$title = $this->modules->fetchOne('name', ['rssId' => $rssId]);
include_once('lib/notifications/notificationemaillib.php');
$smarty = TikiLib::lib('smarty');
$smarty->assign('mail_site', $_SERVER['SERVER_NAME']);
$smarty->assign('rssId', $rssId);
$smarty->assign('title', $title);
$smarty->assign('newcats', $newcats);
sendEmailNotification($nots, 'watch', 'rss_new_source_category_subject.tpl', $_SERVER['SERVER_NAME'], 'rss_new_source_category.tpl');
}
}
$current_priority = 0;
foreach ($custominfo as $source_category => $settings) {
if (in_array($source_category, $source_categories)) {
if (isset($settings['priority']) && $settings['priority'] < $current_priority) {
continue;
}
if (! empty($settings['atype'])) {
$configuration['atype'] = $settings['atype'];
}
if (isset($settings['topic']) && $settings['topic'] > '') {
// need to match 0
$configuration['topic'] = $settings['topic'];
}
if (isset($settings['rating']) && $settings['rating'] > '') {
// need to match 0
$configuration['rating'] = $settings['rating'];
}
$current_priority = isset($settings['priority']) ? $settings['priority'] : 0;
}
}
}
if ($configuration['future_publish'] > 0) {
$publication = $tikilib->now + $configuration['future_publish'] * 60;
}
$expire = $publication + 3600 * 24 * $configuration['expiry'];
if (strpos($data['content'], trim($data['description'])) === 0 && strlen($data['description']) < 1024) {
$data['content'] = substr($data['content'], strlen(trim($data['description'])));
}
$data['content'] = trim($data['content']) == '' ? $data['content'] : '~np~' . $data['content'] . '~/np~';
if ($configuration['submission'] == true) {
$subid = $this->table('tiki_submissions')->fetchOne('subId', [
'linkto' => $data['url'],
'topicId' => $configuration['topic'],
]);
if (! $subid) {
$subid = 0;
}
$subid = $artlib->replace_submission(
$data['title'],
$data['author'],
$configuration['topic'],
'n',
'',
0,
'',
'',
$data['description'],
$data['content'],
$publication,
$expire,
'admin',
$subid,
0,
0,
$configuration['atype'],
'',
'',
$data['url'],
'',
$configuration['a_lang'],
$configuration['rating']
);
if (count($configuration['categories'])) {
$categlib = TikiLib::lib('categ');
$objectId = $categlib->add_categorized_object('submission', $subid, $data['title'], $data['title'], 'tiki-edit_submission.php?subId=' . $subid);
foreach ($configuration['categories'] as $categId) {
$categlib->categorize($objectId, $categId);
}
}
return $subid;
} else {
$id = $this->table('tiki_articles')->fetchOne('articleId', [
'linkto' => $data['url'],
'topicId' => $configuration['topic'],
]);
if (! $id) {
$id = 0;
}
$id = $artlib->replace_article(
$data['title'],
$data['author'],
$configuration['topic'],
'n',
'',
0,
'',
'',
$data['description'],
$data['content'],
$publication,
$expire,
'admin',
$id,
0,
0,
$configuration['atype'],
'',
'',
$data['url'],
'',
$configuration['a_lang'],
$configuration['rating']
);
if (count($configuration['categories'])) {
$categlib = TikiLib::lib('categ');
$objectId = $categlib->add_categorized_object('article', $id, $data['title'], $data['title'], 'tiki-read_article.php?articleId=' . $id);
foreach ($configuration['categories'] as $categId) {
$categlib->categorize($objectId, $categId);
}
}
TikiLib::lib('relation')->add_relation('tiki.rss.source', 'article', $id, 'rss', $rssId);
require_once('lib/search/refresh-functions.php');
refresh_index('articles', $id);
$related_items = TikiLib::lib('relation')->get_relations_to('article', $id, 'tiki.article.attach');
foreach ($related_items as $item) {
refresh_index($item['type'], $item['itemId']);
}
return $id;
}
}
/**
* @param $rssId
* @param $configuration
*
* @return TikiDb_Adodb_Result|TikiDb_Pdo_Result
*/
public function set_article_generator($rssId, $configuration)
{
$configuration['type'] = 'article';
$module = $this->get_rss_module($rssId);
if ($module['actions']) {
$actions = json_decode($module['actions'], true);
} else {
$actions = [];
}
$out = [];
foreach ($actions as $action) {
if ($action['type'] != 'article') {
$out[] = $action;
}
}
$out[] = $configuration;
return $this->modules->update(
['actions' => json_encode($out),],
['rssId' => $rssId,]
);
}
public function get_article_generator($rssId)
{
$module = $this->get_rss_module($rssId);
if ($module['actions']) {
$actions = json_decode($module['actions'], true);
} else {
$actions = [];
}
$default = [
'active' => false,
'expiry' => 365,
'atype' => 'Article',
'topic' => 0,
'future_publish' => -1,
'categories' => [],
'rating' => 5,
'feed_name' => $module['name'],
];
foreach ($actions as $action) {
if ($action['type'] == 'article') {
unset($action['type']);
return array_merge($default, $action);
}
}
return $default;
}
public function generate_feed_from_data($data, $feed_descriptor)
{
require_once 'lib/smarty_tiki/modifier.sefurl.php';
$tikilib = TikiLib::lib('tiki');
$writer = new Laminas\Feed\Writer\Feed();
$writer->setTitle($feed_descriptor['feedTitle']);
$writer->setDescription($feed_descriptor['feedDescription']);
$writer->setLink($tikilib->tikiUrl(''));
$writer->setDateModified(time());
foreach ($data as $row) {
$titleKey = $feed_descriptor['entryTitleKey'];
$url = $row[$feed_descriptor['entryUrlKey']];
$title = $row[$titleKey];
if (isset($feed_descriptor['entryObjectDescriptors'])) {
list($typeKey, $objectKey) = $feed_descriptor['entryObjectDescriptors'];
$object = $row[$objectKey];
$type = $row[$typeKey];
if (empty($url)) {
$url = smarty_modifier_sefurl($object, $type);
}
if (empty($title)) {
$title = TikiLib::lib('object')->get_title($type, $object);
}
}
$entry = $writer->createEntry();
$entry->setTitle($title ? $title : tra('Unspecified'));
$entry->setLink($tikilib->tikiUrl($url));
if (! empty($row[$feed_descriptor['entryModificationKey']])) {
$date = $row[$feed_descriptor['entryModificationKey']];
if (! is_int($date)) {
$date = strtotime($date);
}
$entry->setDateModified($date);
}
$writer->addEntry($entry);
}
return $writer;
}
}