/** * Get a instance for a unique id and feed * * @param RDR_Feed $feed * @param mixed $uniqueId * @return self */ static function get(RDR_Feed $feed, $uniqueId) { $uniqueId = $feed->getId() . "-" . md5($uniqueId); $object = RDR_Entry::getByCondition("uniqueId = {1}", array($feed, $uniqueId)); if ($object) { return reset($object); } $object = new self(db()); $object->feed = $feed; $object->uniqueId = $uniqueId; return $object; }
/** * Old entries will be deleted automatically with this cleanup */ static function cleanupEntries() { $time = RDR_Setting::get("maxentrylifetime")->value; if (!$time) { return; } $updated = false; while (true) { $tmp = RDR_Entry::getByCondition("datetime < {0}", array(dt("now {$time}")), null, 1000); if (!$tmp) { break; } db()->deleteMultiple($tmp); $updated = true; } # after deleting some entries update readed/saved flags if ($updated) { self::cleanupFlags(); } }
/** * Delete the feed */ public function delete() { if (!$this->getId()) { return; } db()->deleteMultiple(RDR_Entry::getByCondition("feed = {0}", array($this))); $cats = RDR_Category::getByQuery("\n SELECT o FROM RDR_Category_feeds\n WHERE k = " . $this->getId() . "\n "); foreach ($cats as $category) { $feeds = $category->feeds; if ($feeds) { foreach ($feeds as $key => $feed) { if (compare($this, $feed)) { unset($feeds[$key]); } if (count($feeds) != count($category->feeds)) { $category->store(); } } } } parent::delete(); RDR_Cleanup::cleanupFlags(); }
/** * Create a entry for given item * * @param SimpleXMLElement $item * @param RDR_Feed $feed * @return RDR_Entry | null */ private static function createEntryForItem($item, RDR_Feed $feed) { $guid = self::xmlValue($item->guid); if (!$guid) { $guid = self::xmlValue($item->id); } if (!$guid) { $guid = self::xmlValue($item->link); } $entry = RDR_Entry::get($feed, $guid); $now = dt("now"); $entry->title = null; $entry->title = cut(self::xmlValue($item->title), 252, "..."); $entry->text = null; $entry->text = self::xmlValue($item->description); if (!$entry->text) { $entry->text = self::xmlValue($item->content); } if (!$entry->text) { $entry->text = self::xmlValue($item->summary); } $entry->datetime = null; $entry->datetime = dt(self::xmlValue($item->pubDate)); if (!$entry->datetime->valid) { $entry->datetime = dt(self::xmlValue($item->published)); } if (!$entry->datetime->valid) { $entry->datetime = dt(self::xmlValue($item->updated)); } if ($entry->datetime->valid && $entry->datetime->getUnixtime() > $now->getUnixtime()) { $entry->datetime = $now; } $count = count($item->link); foreach ($item->link as $link) { if ($count > 1) { if (self::xmlAttr($link, "type") == "text/html") { $entry->link = self::xmlAttr($link, "href"); } } else { $entry->link = self::xmlValue($link); } } if (!$entry->link) { $entry->link = self::xmlValue($item->link); } if (!$entry->link) { $entry->link = self::xmlAttr($item->link, "href"); } $entry->image = null; $enclosures = $item->xpath("enclosure"); if ($enclosures) { foreach ($enclosures as $encl) { if ($entry->image) { break; } if (self::xmlAttr($encl, "type")) { if (strpos(self::xmlAttr($encl, "type"), "image") !== false) { $entry->image = self::xmlAttr($encl, "url"); } } elseif (self::xmlAttr($encl, "url")) { if (preg_match("~jpg|jpeg|gif|png~i", self::xmlAttr($encl, "url"))) { $entry->image = self::xmlAttr($encl, "url"); } } } } $namespaces = $item->getNameSpaces(true); if ($namespaces) { foreach ($namespaces as $ns) { $tmp = $item->children($ns); foreach ($tmp as $key => $value) { if (!$entry->datetime->valid && strpos($key, "date") !== false) { $entry->datetime = dt(self::xmlValue($value)); } if (!$entry->title && strpos($key, "title") !== false) { $entry->title = cut(self::xmlValue($value), 252, "..."); } if (strpos($key, "description") !== false || strpos($key, "content") !== false || strpos($key, "encoded") !== false) { $text = self::xmlValue($value); if ($text && (!$entry->text || mb_strlen($text) > $entry->text)) { $entry->text = $text; } if (!$entry->image) { $attr = $value->attributes(); $url = isset($attr->url) ? self::xmlValue($attr->url) : null; $type = isset($attr->type) ? self::xmlValue($attr->type) : null; if ($url && (preg_match("~\\.(jpg|jpeg|png|gif)~i", $url) || preg_match("~image\\/~i", $type))) { $entry->image = $url; } } } } } } # if datetime is older than maxlifetime than don't store if (!$entry->datetime->valid) { $entry->datetime = $now; } $time = RDR_Setting::get("maxentrylifetime")->value; if ($time && $entry->datetime->getUnixtime() < dt("now {$time}")->getUnixtime()) { return; } $entry->store(); return $entry; }
/** * Load the View */ public function onLoad() { if (!needRole()) { return; } $jsonData = null; switch (post("action")) { case "delete-feed-user": $feed = RDR_Feed::getById(post("data[fid]")); if ($feed) { $cats = user()->getCategories(); foreach ($cats as $category) { $feeds = $category->feeds; if ($feeds) { foreach ($feeds as $key => $catFeed) { if (compare($catFeed, $feed)) { unset($feeds[$key]); } } if (count($feeds) != count($category->feeds)) { $category->feeds = $feeds; $category->store(); } } } } break; case "delete-feed-admin": if (needRole(RDR_User::ROLE_ADMIN)) { $feed = RDR_Feed::getById(post("data[fid]")); if ($feed) { $feed->delete(); } } break; case "add-feed": $event = RDR_Import::addFeed(post("data[url]"), RDR_Category::get(post("data[category]"))); if ($event->feed) { RDR_Import::importFeedEntries($event->feed); } break; case "mark-all-as-readed": $cache = session("entry.ids.original"); if ($cache) { $ids = array_keys($cache); user()->loadReadedFlags(array_keys($ids)); $insertIds = array(); foreach ($ids as $id) { if (!isset(user()->_cacheReaded[$id])) { $insertIds[$id] = $id; } } if ($insertIds) { $query = "INSERT IGNORE INTO RDR_User_readed (o,k,v) VALUES "; foreach ($insertIds as $id) { $query .= " (" . user()->getId() . ", {$id}, 1), "; } $query = substr($query, 0, -2); db()->query($query); user()->updateReadedCount(); } } break; case "update-setting-user": user()->setting(post("data[key]"), post("data[value]")); user()->store(); break; case "update-newscache": user()->updateNewsCache(); $jsonData = user()->getAjaxData(); break; case "set-entries-readed": if (post("data[ids]")) { $entries = RDR_Entry::getByIds(post("data[ids]")); if ($entries) { user()->loadReadedFlags(array_keys($entries)); $insertIds = $deleteIds = array(); foreach ($entries as $entry) { $id = $entry->getId(); if ($id < user()->setting("init.entry")) { continue; } if (isset(user()->_cacheReaded[$id])) { $deleteIds[$id] = $id; } else { $insertIds[$id] = $id; } } if ($insertIds) { $query = "INSERT IGNORE INTO RDR_User_readed (o,k,v) VALUES "; foreach ($insertIds as $id) { $query .= " (" . user()->getId() . ", {$id}, 1), "; } $query = substr($query, 0, -2); db()->query($query); } if ($deleteIds) { $query = "DELETE FROM RDR_User_readed WHERE o = " . user()->getId() . " && k IN " . db()->toDb($deleteIds); } user()->updateReadedCount(); } } break; case "set-entries-saved": if (post("data[ids]")) { $entry = RDR_Entry::getById(post("data[ids][0]")); if ($entry) { if (user()->getByKey("saved", $entry->getId())) { user()->remove("saved", $entry->getId()); } else { user()->add("saved", 1, $entry->getId()); } user()->store(); } } break; case "set-feed-property": if (needRole(RDR_User::ROLE_ADMIN)) { $feed = RDR_Feed::getById(post("data[feed]")); if ($feed) { $feed->{post("data[field]")} = post("data[value]"); $feed->store(); } } break; } echo json_encode($jsonData, JSON_FORCE_OBJECT); }
/** * Load the View */ public function onLoad() { if (!needRole()) { return; } # some ajax actions switch (post("action")) { case "admin-feed": if (needRole(RDR_User::ROLE_ADMIN)) { $entry = RDR_Entry::getById(post("eid")); $feed = RDR_Feed::getById(post("fid")); ?> <b><?php echo t("feedadmin.raw.1"); ?> </b> <div class="small"> <?php echo t("feedadmin.raw.2"); ?> </div> <code class="raw"><?php echo s('<div>' . $entry->text . '</div>'); ?> </code><br/><br/> <b><?php echo t("feedadmin.format.1"); ?> </b> <div class="small"> <?php echo t("feedadmin.format.2"); ?> </div> <code class="formated"></code><br/><br/> <b><?php echo sprintf(t("feedadmin.js.1"), s(cut($feed->name, 30))); ?> </b> <div class="small"> <?php echo nl2br(sprintf(t("feedadmin.js.2"), s('<p>'), 'html = $(html); html.find("p").remove()')); ?> <br/> <textarea data-field="contentJS" style="width:90%" cols="45" rows="3"><?php echo s($feed->contentJS); ?> </textarea> </div> <?php } return; break; case "readed": if (post("ids")) { $entries = RDR_Entry::getByIds(post("ids")); if ($entries) { user()->loadReadedFlags(array_keys($entries)); $insertIds = $deleteIds = array(); foreach ($entries as $entry) { $id = $entry->getId(); if ($id < user()->setting("init.entry")) { continue; } if (isset(user()->_cacheReaded[$id])) { $deleteIds[$id] = $id; } else { $insertIds[$id] = $id; } } if ($insertIds) { $query = "INSERT IGNORE INTO RDR_User_readed (o,k,v) VALUES "; foreach ($insertIds as $id) { $query .= " (" . user()->getId() . ", {$id}, 1), "; } $query = substr($query, 0, -2); db()->query($query); } if ($deleteIds) { $query = "DELETE FROM RDR_User_readed WHERE o = " . user()->getId() . " && k IN " . db()->toDb($deleteIds); } user()->updateReadedCount(); } } break; case "saved": if (post("ids")) { $entry = RDR_Entry::getById(post("ids[0]")); if ($entry) { if (user()->getByKey("saved", $entry->getId())) { user()->remove("saved", $entry->getId()); } else { user()->add("saved", 1, $entry->getId()); } user()->store(); } } break; } $jsonData = user()->getAjaxData(); echo json_encode($jsonData, JSON_FORCE_OBJECT); }
/** * Load the View */ public function onLoad() { needRole(null, true); if (get("token")) { $token = explode(".", get("token")); if (count($token) == 2 && saltedHash("sha256", $token[0]) == $token[1]) { session("user.id", $token[0]); if (user()) { $max = min(array(200, (int) get("max"))); $catmax = get("catmax") ? min(array($max, (int) get("catmax"))) : $max; $feedmax = get("feedmax") ? min(array($max, (int) get("feedmax"))) : $max; $feedIds = explode(",", get("f")); $rss = new SimpleXMLElement('<' . '?xml version="1.0" encoding="utf-8"?><rss></rss>'); $rss->addAttribute("version", "2.0"); $channel = $rss->addChild("channel"); $channel->addChild("title", get("title")); $channel->addChild("description", get("desc")); $channel->addChild("pubDate", dt("now")->format("r")); $feeds = user()->getFeeds(); $catCount = $feedCount = array(); $count = 0; $allEntries = array(); $offset = 0; $limit = 50; while (true) { if (!$feeds) { break; } $entries = RDR_Entry::getByCondition("feed IN {0} && id > {1}", array($feeds, (int) user()->setting("init.entry")), array("-datetime", "-id"), $limit, $offset); $offset += $limit; if (!$entries) { break; } user()->loadReadedFlags(array_keys($entries)); foreach ($entries as $entry) { if (isset(user()->_cacheReaded[$entry->getId()])) { continue; } if ($count >= $max) { break 2; } $feed = $entry->feed; $category = user()->getCategoryToFeed($feed); $feedId = $feed->getId(); $catId = $category->getId(); if (!isset($catCount[$catId])) { $catCount[$catId] = 0; } if (!isset($feedCount[$feedId])) { $feedCount[$feedId] = 0; } if ($feedCount[$feedId] >= $feedmax) { if (isset($feeds[$feedId])) { unset($feeds[$feedId]); } continue; } if ($catCount[$catId] >= $catmax) { continue; } $entry->category = $category; $entry->time = $entry->datetime->getUnixtime(); $allEntries[] = $entry; $feedCount[$feedId]++; $catCount[$catId]++; $count++; } } foreach ($allEntries as $entry) { $feed = $entry->feed; $category = $entry->category; $item = $channel->addChild("item"); $this->addCData($item->addChild("title"), $entry->title); $this->addCData($item->addChild("link"), $entry->link); $this->addCData($item->addChild("description"), $entry->text); $this->addCData($item->addChild("category"), $category->name); $item->addChild("guid", $entry->getId()); $item->addChild("pubDate", $entry->datetime->format("r")); } $data = $rss->asXML(); CHOQ_OutputManager::cleanAllBuffers(); header("Content-type: application/rss+xml"); echo $data; die; } } } view("RDR_BasicFrame", array("view" => $this)); }
/** * Display contents for a entry * * @param RDR_Entry $entry */ private function displayEntry(RDR_Entry $entry) { $jsonData = $entry->_dbValues; $jsonData["id"] = $entry->getId(); $readed = isset(user()->_cacheReaded[$entry->getId()]) || user()->setting("init.entry") >= $entry->getId(); $saved = user()->getByKey("saved", $entry->getId()); $categories = user()->getCategories(); $feed = $entry->feed; $jsonData["contentJS"] = $feed->contentJS; $jsonData["feedId"] = $feed->getId(); $category = user()->getCategoryToFeed($feed); $layout = "default"; $favicon = $entry->feed->getFaviconUrl(); if (user()->setting("layout")) { $layout = user()->setting("layout"); } $smallTag = '<div class="feed-options small">'; if (!$readed) { $smallTag .= '<span><a href="#" class="readed">' . t("mark.read") . '</a> · </span>'; } $smallTag .= '<span><a href="#" class="saved">' . (!$saved ? t("saveit") : t("remove.save")) . '</a> · </span>'; $smallTag .= '<time datetime="' . $entry->datetime->getUnixtime() . '"></time> · '; $smallTag .= t("feed") . ': '; if ($favicon) { $smallTag .= '<span class="favicon" style="background-image:url(' . $favicon . ')"></span>'; } $smallTag .= sprintf(t("feeds.2"), '<a href="' . $entry->feed->getLink() . '">' . s(cut($entry->feed->name, 30)) . '</a>', '<a href="' . $category->getLink() . '">' . s(cut($category->name, 30)) . '</a>') . " · "; $smallTag .= t("url") . ': <a href="' . $entry->link . '" target="_blank">' . s(cut($entry->link, 30)) . '</a>'; if (needRole(RDR_User::ROLE_ADMIN)) { $smallTag .= ' · <a href="#" class="adminview">' . t("adminview") . '</a>'; } $smallTag .= '</div>'; $titleTag = '<h2><a href="' . $entry->link . '" target="_blank" onclick="return false;" rel="noreferrer">' . s($entry->title) . '</a></h2>'; $imageTag = '<div class="image"></div>'; ?> <div class="<?php echo user()->setting("hideimages") ? 'no-feed-images' : null; ?> entry <?php echo $readed && $this->readedLayoutEnabled ? 'readed' : null; ?> layout-<?php echo s($layout); ?> " id="entry-<?php echo $entry->getId(); ?> " data-id="<?php echo $entry->getId(); ?> " data-feed="<?php echo $feed->getId(); ?> "> <div class="feed-start"></div> <?php switch ($layout) { case "big": ?> <?php echo $titleTag; ?> <div class="clear"></div> <div class="float-one"> <div class="inner"><?php echo $imageTag; ?> </div> </div> <div class="float-two"> <div class="inner"> <?php echo $smallTag; ?> <div class="text"></div> </div> </div> <div class="clear"></div> <?php break; case "headline": echo $titleTag; echo $smallTag; break; default: ?> <div class="float-one"> <div class="inner"><?php echo $imageTag; ?> </div> </div> <div class="float-two"> <div class="inner"> <?php echo $titleTag; ?> <?php echo $smallTag; ?> <div class="text"></div> </div> </div> <div class="clear"></div> <?php break; } ?> <div class="feed-end"></div> <?php if (!user()->setting("noautoread") && !$readed) { ?> <div class="entry-readed" data-id="<?php echo $entry->getId(); ?> "></div> <?php } ?> <?php if (needRole(RDR_User::ROLE_ADMIN)) { ?> <div class="adminview"></div> <?php } ?> </div> <script type="text/javascript"> (function(){ var d = <?php echo json_encode($jsonData, JSON_FORCE_OBJECT); ?> ; Feeds.feedInit(d); })(); </script> <?php }