summaryrefslogtreecommitdiffstats
path: root/app/classes
diff options
context:
space:
mode:
authornashe <thomas@chauchefoin.fr>2017-10-21 13:30:15 +0200
committernashe <thomas@chauchefoin.fr>2017-10-21 13:30:15 +0200
commit351009241bbe0864670c79fd78b5e95271cc6c2f (patch)
tree1fe11d960daa3da772971386b87480a9854962bc /app/classes
parent1b341502ba68092b444a7870d601537eec68b344 (diff)
downloadplanet-351009241bbe0864670c79fd78b5e95271cc6c2f.tar
planet-351009241bbe0864670c79fd78b5e95271cc6c2f.tar.gz
planet-351009241bbe0864670c79fd78b5e95271cc6c2f.tar.bz2
planet-351009241bbe0864670c79fd78b5e95271cc6c2f.tar.xz
planet-351009241bbe0864670c79fd78b5e95271cc6c2f.zip
Improve project structure
Diffstat (limited to 'app/classes')
-rw-r--r--app/classes/Cache.php254
-rw-r--r--app/classes/Opml.php70
-rw-r--r--app/classes/OpmlManager.php50
-rw-r--r--app/classes/Planet.php67
4 files changed, 410 insertions, 31 deletions
diff --git a/app/classes/Cache.php b/app/classes/Cache.php
new file mode 100644
index 0000000..b73182e
--- /dev/null
+++ b/app/classes/Cache.php
@@ -0,0 +1,254 @@
+<?php
+/**
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this software; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* © Copyright 2005 Richard Heyes
+*/
+
+/**
+* Caching Libraries for PHP5
+*
+* Handles data and output caching. Defaults to /dev/shm
+* (shared memory). All methods are static.
+*
+* Eg: (output caching)
+*
+* if (!OutputCache::Start('group', 'unique id', 600)) {
+*
+* // ... Output
+*
+* OutputCache::End();
+* }
+*
+* Eg: (data caching)
+*
+* if (!$data = DataCache::Get('group', 'unique id')) {
+*
+* $data = time();
+*
+* DataCache::Put('group', 'unique id', 10, $data);
+* }
+*
+* echo $data;
+*/
+ class Cache
+ {
+ /**
+ * Whether caching is enabled
+ * @var bool
+ */
+ public static $enabled = true;
+
+ /**
+ * Place to store the cache files
+ * @var string
+ */
+ protected static $store = '/dev/shm/';
+
+ /**
+ * Prefix to use on cache files
+ * @var string
+ */
+ protected static $prefix = 'cache_';
+
+ /**
+ * Stores data
+ *
+ * @param string $group Group to store data under
+ * @param string $id Unique ID of this data
+ * @param int $ttl How long to cache for (in seconds)
+ */
+ protected static function write($group, $id, $ttl, $data)
+ {
+ $filename = self::getFilename($group, $id);
+
+ if (self::$enabled && $fp = fopen($filename, 'xb')) {
+
+ if (flock($fp, LOCK_EX)) {
+ fwrite($fp, $data);
+ }
+ fclose($fp);
+
+ // Set filemtime
+ touch($filename, time() + $ttl);
+ }
+ }
+
+ /**
+ * Reads data
+ *
+ * @param string $group Group to store data under
+ * @param string $id Unique ID of this data
+ */
+ protected static function read($group, $id)
+ {
+ $filename = self::getFilename($group, $id);
+
+ return file_get_contents($filename);
+ }
+
+ /**
+ * Determines if an entry is cached
+ *
+ * @param string $group Group to store data under
+ * @param string $id Unique ID of this data
+ */
+ protected static function isCached($group, $id)
+ {
+ $filename = self::getFilename($group, $id);
+
+ if (self::$enabled && file_exists($filename) && filemtime($filename) > time()) {
+ return true;
+ }
+
+ @unlink($filename);
+
+ return false;
+ }
+
+ /**
+ * Builds a filename/path from group, id and
+ * store.
+ *
+ * @param string $group Group to store data under
+ * @param string $id Unique ID of this data
+ */
+ protected static function getFilename($group, $id)
+ {
+ $id = md5($id);
+
+ return self::$store . self::$prefix . "{$group}_{$id}";
+ }
+
+ /**
+ * Sets the filename prefix to use
+ *
+ * @param string $prefix Filename Prefix to use
+ */
+ public static function setPrefix($prefix)
+ {
+ self::$prefix = $prefix;
+ }
+
+ /**
+ * Sets the store for cache files. Defaults to
+ * /dev/shm. Must have trailing slash.
+ *
+ * @param string $store The dir to store the cache data in
+ */
+ public static function setStore($store)
+ {
+ self::$store = $store;
+ }
+ }
+
+ /**
+ * Output Cache extension of base caching class
+ */
+ class OutputCache extends Cache
+ {
+ /**
+ * Group of currently being recorded data
+ * @var string
+ */
+ private static $group;
+
+ /**
+ * ID of currently being recorded data
+ * @var string
+ */
+ private static $id;
+
+ /**
+ * Ttl of currently being recorded data
+ * @var int
+ */
+ private static $ttl;
+
+ /**
+ * Starts caching off. Returns true if cached, and dumps
+ * the output. False if not cached and start output buffering.
+ *
+ * @param string $group Group to store data under
+ * @param string $id Unique ID of this data
+ * @param int $ttl How long to cache for (in seconds)
+ * @return bool True if cached, false if not
+ */
+ public static function Start($group, $id, $ttl)
+ {
+ if (self::isCached($group, $id)) {
+ echo self::read($group, $id);
+ return true;
+
+ } else {
+
+ ob_start();
+
+ self::$group = $group;
+ self::$id = $id;
+ self::$ttl = $ttl;
+
+ return false;
+ }
+ }
+
+ /**
+ * Ends caching. Writes data to disk.
+ */
+ public static function End()
+ {
+ $data = ob_get_contents();
+ ob_end_flush();
+
+ self::write(self::$group, self::$id, self::$ttl, $data);
+ }
+ }
+
+ /**
+ * Data cache extension of base caching class
+ */
+ class DataCache extends Cache
+ {
+
+ /**
+ * Retrieves data from the cache
+ *
+ * @param string $group Group this data belongs to
+ * @param string $id Unique ID of the data
+ * @return mixed Either the resulting data, or null
+ */
+ public static function Get($group, $id)
+ {
+ if (self::isCached($group, $id)) {
+ return unserialize(self::read($group, $id));
+ }
+
+ return null;
+ }
+
+ /**
+ * Stores data in the cache
+ *
+ * @param string $group Group this data belongs to
+ * @param string $id Unique ID of the data
+ * @param int $ttl How long to cache for (in seconds)
+ * @param mixed $data The data to store
+ */
+ public static function Put($group, $id, $ttl, $data)
+ {
+ self::write($group, $id, $ttl, serialize($data));
+ }
+ }
+?> \ No newline at end of file
diff --git a/app/classes/Opml.php b/app/classes/Opml.php
index e69de29..ae9e8b1 100644
--- a/app/classes/Opml.php
+++ b/app/classes/Opml.php
@@ -0,0 +1,70 @@
+<?php
+
+class Opml
+{
+ var $_xml = null;
+ var $_currentTag = '';
+
+ var $title = '';
+ var $entries = array();
+ var $map =
+ array(
+ 'URL' => 'website',
+ 'HTMLURL' => 'website',
+ 'TEXT' => 'name',
+ 'TITLE' => 'name',
+ 'XMLURL' => 'feed',
+ 'DESCRIPTION' => 'description',
+ 'ISDOWN' => 'isDown'
+ );
+
+
+ function parse($data)
+ {
+ $this->_xml = xml_parser_create('UTF-8');
+ //xml_parser_set_option($this->_xml, XML_OPTION_CASE_FOLDING, false);
+ //xml_parser_set_option($this->_xml, XML_OPTION_SKIP_WHITE, true);
+ xml_set_object($this->_xml, $this);
+ xml_set_element_handler($this->_xml,'_openTag','_closeTag');
+ xml_set_character_data_handler ($this->_xml, '_cData');
+
+ xml_parse($this->_xml,$data);
+ xml_parser_free($this->_xml);
+ return $this->entries;
+ }
+
+
+ function _openTag($p,$tag,$attrs)
+ {
+ $this->_currentTag = $tag;
+
+ if ($tag == 'OUTLINE')
+ {
+ $i = count($this->entries);
+ foreach (array_keys($this->map) as $key)
+ {
+ if (isset($attrs[$key])) {
+ $this->entries[$i][$this->map[$key]] = $attrs[$key];
+ }
+ }
+ }
+ }
+
+ function _closeTag($p, $tag){
+ $this->_currentTag = '';
+ }
+
+ function _cData($p, $cdata){
+ if ($this->_currentTag == 'TITLE'){
+ $this->title = $cdata;
+ }
+ }
+
+ function getTitle(){
+ return $this->title;
+ }
+
+ function getPeople(){
+ return $this->entries;
+ }
+} \ No newline at end of file
diff --git a/app/classes/OpmlManager.php b/app/classes/OpmlManager.php
new file mode 100644
index 0000000..02491a2
--- /dev/null
+++ b/app/classes/OpmlManager.php
@@ -0,0 +1,50 @@
+<?php
+
+
+class OpmlManager
+{
+ public static function load($file)
+ {
+ if (!file_exists($file)) {
+ throw new Exception('OPML file not found!');
+ }
+
+ $opml = new opml();
+
+ //Remove BOM if needed
+ $BOM = '/^/';
+ $fileContent = file_get_contents($file);
+ $fileContent = preg_replace($BOM, '', $fileContent, 1);
+
+ //Parse
+ $opml->parse($fileContent);
+
+ return $opml;
+ }
+
+ /**
+ * @param Opml $opml
+ * @param string $file
+ */
+ public static function save($opml, $file){
+ $out = '<?xml version="1.0"?>'."\n";
+ $out.= '<opml version="1.1">'."\n";
+ $out.= '<head>'."\n";
+ $out.= '<title>'.htmlspecialchars($opml->getTitle()).'</title>'."\n";
+ $out.= '<dateCreated>'.date('c').'</dateCreated>'."\n";
+ $out.= '<dateModified>'.date('c').'</dateModified>'."\n";
+ $out.= '</head>'."\n";
+ $out.= '<body>'."\n";
+ foreach ($opml->entries as $person) {
+ $out.= '<outline text="' . htmlspecialchars($person['name'], ENT_QUOTES) . '" htmlUrl="' . htmlspecialchars($person['website'], ENT_QUOTES) . '" xmlUrl="' . htmlspecialchars($person['feed'], ENT_QUOTES) . '" isDown="' . htmlspecialchars($person['isDown'], ENT_QUOTES) . '"/>'."\n";
+ }
+ $out.= '</body>'."\n";
+ $out.= '</opml>';
+
+ file_put_contents($file, $out);
+ }
+
+ public static function backup($file){
+ copy($file, $file.'.bak');
+ }
+}
diff --git a/app/classes/Planet.php b/app/classes/Planet.php
index 39b55f6..c287843 100644
--- a/app/classes/Planet.php
+++ b/app/classes/Planet.php
@@ -34,23 +34,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
class Planet
{
+ /** @var PlanetConfig */
public $config;
+
+ /** @var PlanetItem[] */
public $items;
+
+ /** @var PlanetFeed[] */
public $people;
+
+ /** @var PlanetError[] */
public $errors;
+ /**
+ * Planet constructor.
+ *
+ * @param PlanetConfig $config
+ */
public function __construct($config=null)
{
+ $this->config = $config === null ? new PlanetConfig() : $config;
- if ($config == null) {
- $this->config = new PlanetConfig(array());
- } else {
- $this->config = $config;
- }
-
- $this->items = array();
- $this->people = array();
- $this->errors = array();
+ $this->items = [];
+ $this->people = [];
+ $this->errors = [];
}
/**
@@ -111,8 +118,9 @@ class Planet
}
/**
- * Adds a feed to the planet
- * @param PlanetFeed feed
+ * Adds a feed to the planet.
+ *
+ * @param PlanetFeed $feed
*/
public function addPerson(&$feed)
{
@@ -120,8 +128,10 @@ class Planet
}
/**
- * Load people from an OPML
- * @return integer Number of people loaded
+ * Load people from an OPML.
+ *
+ * @param string $file File to load the OPML from.
+ * @return integer Number of people loaded.
*/
public function loadOpml($file)
{
@@ -162,17 +172,16 @@ class Planet
}
/**
- * Download
- * @var $max_load percentage of feeds to load
+ * Fetch feeds and see if new data is present.
+ *
+ * @param float $max_load Percentage of feeds to load
*/
public function download($max_load=0.1)
{
$max_load_feeds = ceil(count($this->people) * $max_load);
- $opml = OpmlManager::load(__DIR__.'/../../custom/people.opml');
- foreach ($this->people as $feed) {
+ foreach ($this->people as &$feed) {
//Avoid mass loading with variable cache duration
- //$feed->set_cache_duration($this->config->getCacheTimeout()+rand(0,30));
$feed->set_cache_duration($this->config->getCacheTimeout());
//Load only a few feeds, force other to fetch from the cache
@@ -181,6 +190,8 @@ class Planet
$this->errors[] = new PlanetError(1, 'Forced from cache : '.$feed->getFeed());
}
+ // Bypass remote's SSL/TLS certificate if the user explicitly
+ // asked for it in the configuration.
if ($this->config->checkcerts === false) {
$feed->set_curl_options([
CURLOPT_SSL_VERIFYHOST => false,
@@ -188,28 +199,22 @@ class Planet
]);
}
- //Load feed
$feed->init();
- $isDown = '';
// http://simplepie.org/wiki/reference/simplepie/merge_items ?
- //Add items to index
if (($feed->data) && ($feed->get_item_quantity() > 0)){
$items = $feed->get_items();
$this->items = array_merge($this->items, $items);
+ $feed['isUp'] = true;
} else {
- $this->errors[] = new PlanetError(1, 'No items : '.$feed->getFeed());
- $isDown = '1';
- }
-
- //Mark if the feed is temporary unavailable
- foreach ($opml->entries as $key => $entrie) {
- if ($feed->getFeed() === $entrie['feed']) {
- $opml->entries[$key]['isDown'] = $isDown;
- }
+ $this->errors[] = new PlanetError(1, 'No items or down : ' . $feed->getFeed());
+ $feed['isDown'] = false;
}
}
- OpmlManager::save($opml, __DIR__.'/../../custom/people.opml');
+
+ // FIXME: not sure that it's $this->people?
+ // FIXME: make sure we made a change
+ OpmlManager::save($this->people, __DIR__.'/../../custom/people.opml');
}
public function sort()