1
0
mirror of https://github.com/moparisthebest/wallabag synced 2024-11-23 17:42:15 -05:00

import without cron

This commit is contained in:
Maryana Rozhankivska 2014-04-02 20:55:19 +03:00
parent 22db488d21
commit 182faf2696
9 changed files with 351 additions and 261 deletions

168
inc/3rdparty/libraries/feedwriter/FeedWriter.php vendored Normal file → Executable file
View File

@ -9,9 +9,9 @@ define('JSONP', 3, true);
* Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed) * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed)
* *
* Modified for FiveFilters.org's Full-Text RSS project * Modified for FiveFilters.org's Full-Text RSS project
* to allow for inclusion of hubs, JSON output. * to allow for inclusion of hubs, JSON output.
* Stripped RSS1 and ATOM support. * Stripped RSS1 and ATOM support.
* *
* @package UnivarselFeedWriter * @package UnivarselFeedWriter
* @author Anis uddin Ahmad <anisniit@gmail.com> * @author Anis uddin Ahmad <anisniit@gmail.com>
* @link http://www.ajaxray.com/projects/rss * @link http://www.ajaxray.com/projects/rss
@ -26,32 +26,32 @@ define('JSONP', 3, true);
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
private $xsl = null; // stylesheet to render RSS (used by Chrome) private $xsl = null; // stylesheet to render RSS (used by Chrome)
private $json = null; // JSON object private $json = null; // JSON object
private $version = null; private $version = null;
/** /**
* Constructor * Constructor
* *
* @param constant the version constant (RSS2 or JSON). * @param constant the version constant (RSS2 or JSON).
*/ */
function __construct($version = RSS2) function __construct($version = RSS2)
{ {
$this->version = $version; $this->version = $version;
// Setting default value for assential channel elements // Setting default value for assential channel elements
$this->channels['title'] = $version . ' Feed'; $this->channels['title'] = $version . ' Feed';
$this->channels['link'] = 'http://www.ajaxray.com/blog'; $this->channels['link'] = 'http://www.ajaxray.com/blog';
//Tag names to encode in CDATA //Tag names to encode in CDATA
$this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary'); $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');
} }
public function setFormat($format) { public function setFormat($format) {
$this->version = $format; $this->version = $format;
} }
// Start # public functions --------------------------------------------- // Start # public functions ---------------------------------------------
/** /**
* Set a channel element * Set a channel element
* @access public * @access public
@ -63,11 +63,11 @@ define('JSONP', 3, true);
{ {
$this->channels[$elementName] = $content ; $this->channels[$elementName] = $content ;
} }
/** /**
* Set multiple channel elements from an array. Array elements * Set multiple channel elements from an array. Array elements
* should be 'channelName' => 'channelContent' format. * should be 'channelName' => 'channelContent' format.
* *
* @access public * @access public
* @param array array of channels * @param array array of channels
* @return void * @return void
@ -75,30 +75,30 @@ define('JSONP', 3, true);
public function setChannelElementsFromArray($elementArray) public function setChannelElementsFromArray($elementArray)
{ {
if(! is_array($elementArray)) return; if(! is_array($elementArray)) return;
foreach ($elementArray as $elementName => $content) foreach ($elementArray as $elementName => $content)
{ {
$this->setChannelElement($elementName, $content); $this->setChannelElement($elementName, $content);
} }
} }
/** /**
* Genarate the actual RSS/JSON file * Genarate the actual RSS/JSON file
* *
* @access public * @access public
* @return void * @return void
*/ */
public function genarateFeed() public function genarateFeed()
{ {
if ($this->version == RSS2) { if ($this->version == RSS2) {
header('Content-type: text/xml; charset=UTF-8'); // header('Content-type: text/xml; charset=UTF-8');
// this line prevents Chrome 20 from prompting download // this line prevents Chrome 20 from prompting download
// used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss
header('X-content-type-options: nosniff'); // header('X-content-type-options: nosniff');
} elseif ($this->version == JSON) { } elseif ($this->version == JSON) {
header('Content-type: application/json; charset=UTF-8'); // header('Content-type: application/json; charset=UTF-8');
$this->json = new stdClass(); $this->json = new stdClass();
} elseif ($this->version == JSONP) { } elseif ($this->version == JSONP) {
header('Content-type: application/javascript; charset=UTF-8'); // header('Content-type: application/javascript; charset=UTF-8');
$this->json = new stdClass(); $this->json = new stdClass();
} }
$this->printHead(); $this->printHead();
@ -109,10 +109,10 @@ define('JSONP', 3, true);
echo json_encode($this->json); echo json_encode($this->json);
} }
} }
/** /**
* Create a new FeedItem. * Create a new FeedItem.
* *
* @access public * @access public
* @return object instance of FeedItem class * @return object instance of FeedItem class
*/ */
@ -121,24 +121,24 @@ define('JSONP', 3, true);
$Item = new FeedItem($this->version); $Item = new FeedItem($this->version);
return $Item; return $Item;
} }
/** /**
* Add a FeedItem to the main class * Add a FeedItem to the main class
* *
* @access public * @access public
* @param object instance of FeedItem class * @param object instance of FeedItem class
* @return void * @return void
*/ */
public function addItem($feedItem) public function addItem($feedItem)
{ {
$this->items[] = $feedItem; $this->items[] = $feedItem;
} }
// Wrapper functions ------------------------------------------------------------------- // Wrapper functions -------------------------------------------------------------------
/** /**
* Set the 'title' channel element * Set the 'title' channel element
* *
* @access public * @access public
* @param srting value of 'title' channel tag * @param srting value of 'title' channel tag
* @return void * @return void
@ -147,59 +147,59 @@ define('JSONP', 3, true);
{ {
$this->setChannelElement('title', $title); $this->setChannelElement('title', $title);
} }
/** /**
* Add a hub to the channel element * Add a hub to the channel element
* *
* @access public * @access public
* @param string URL * @param string URL
* @return void * @return void
*/ */
public function addHub($hub) public function addHub($hub)
{ {
$this->hubs[] = $hub; $this->hubs[] = $hub;
} }
/** /**
* Set XSL URL * Set XSL URL
* *
* @access public * @access public
* @param string URL * @param string URL
* @return void * @return void
*/ */
public function setXsl($xsl) public function setXsl($xsl)
{ {
$this->xsl = $xsl; $this->xsl = $xsl;
} }
/** /**
* Set self URL * Set self URL
* *
* @access public * @access public
* @param string URL * @param string URL
* @return void * @return void
*/ */
public function setSelf($self) public function setSelf($self)
{ {
$this->self = $self; $this->self = $self;
} }
/** /**
* Set the 'description' channel element * Set the 'description' channel element
* *
* @access public * @access public
* @param srting value of 'description' channel tag * @param srting value of 'description' channel tag
* @return void * @return void
*/ */
public function setDescription($desciption) public function setDescription($desciption)
{ {
$tag = ($this->version == ATOM)? 'subtitle' : 'description'; $tag = ($this->version == ATOM)? 'subtitle' : 'description';
$this->setChannelElement($tag, $desciption); $this->setChannelElement($tag, $desciption);
} }
/** /**
* Set the 'link' channel element * Set the 'link' channel element
* *
* @access public * @access public
* @param srting value of 'link' channel tag * @param srting value of 'link' channel tag
* @return void * @return void
@ -208,10 +208,10 @@ define('JSONP', 3, true);
{ {
$this->setChannelElement('link', $link); $this->setChannelElement('link', $link);
} }
/** /**
* Set the 'image' channel element * Set the 'image' channel element
* *
* @access public * @access public
* @param srting title of image * @param srting title of image
* @param srting link url of the imahe * @param srting link url of the imahe
@ -222,14 +222,14 @@ define('JSONP', 3, true);
{ {
$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url)); $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
} }
// End # public functions ---------------------------------------------- // End # public functions ----------------------------------------------
// Start # private functions ---------------------------------------------- // Start # private functions ----------------------------------------------
/** /**
* Prints the xml and rss namespace * Prints the xml and rss namespace
* *
* @access private * @access private
* @return void * @return void
*/ */
@ -247,10 +247,10 @@ define('JSONP', 3, true);
$this->json->rss = array('@attributes' => array('version' => '2.0')); $this->json->rss = array('@attributes' => array('version' => '2.0'));
} }
} }
/** /**
* Closes the open tags at the end of file * Closes the open tags at the end of file
* *
* @access private * @access private
* @return void * @return void
*/ */
@ -258,14 +258,14 @@ define('JSONP', 3, true);
{ {
if ($this->version == RSS2) if ($this->version == RSS2)
{ {
echo '</channel>',PHP_EOL,'</rss>'; echo '</channel>',PHP_EOL,'</rss>';
} }
// do nothing for JSON // do nothing for JSON
} }
/** /**
* Creates a single node as xml format * Creates a single node as xml format
* *
* @access private * @access private
* @param string name of the tag * @param string name of the tag
* @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
@ -273,22 +273,22 @@ define('JSONP', 3, true);
* @return string formatted xml tag * @return string formatted xml tag
*/ */
private function makeNode($tagName, $tagContent, $attributes = null) private function makeNode($tagName, $tagContent, $attributes = null)
{ {
if ($this->version == RSS2) if ($this->version == RSS2)
{ {
$nodeText = ''; $nodeText = '';
$attrText = ''; $attrText = '';
if (is_array($attributes)) if (is_array($attributes))
{ {
foreach ($attributes as $key => $value) foreach ($attributes as $key => $value)
{ {
$attrText .= " $key=\"$value\" "; $attrText .= " $key=\"$value\" ";
} }
} }
$nodeText .= "<{$tagName}{$attrText}>"; $nodeText .= "<{$tagName}{$attrText}>";
if (is_array($tagContent)) if (is_array($tagContent))
{ {
foreach ($tagContent as $key => $value) foreach ($tagContent as $key => $value)
{ {
$nodeText .= $this->makeNode($key, $value); $nodeText .= $this->makeNode($key, $value);
} }
@ -297,7 +297,7 @@ define('JSONP', 3, true);
{ {
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent); //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
$nodeText .= htmlspecialchars($tagContent); $nodeText .= htmlspecialchars($tagContent);
} }
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>"; //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
$nodeText .= "</$tagName>"; $nodeText .= "</$tagName>";
return $nodeText . PHP_EOL; return $nodeText . PHP_EOL;
@ -321,7 +321,7 @@ define('JSONP', 3, true);
} }
return ''; // should not get here return ''; // should not get here
} }
private function json_keys(array $array) { private function json_keys(array $array) {
$new = array(); $new = array();
foreach ($array as $key => $val) { foreach ($array as $key => $val) {
@ -334,7 +334,7 @@ define('JSONP', 3, true);
} }
return $new; return $new;
} }
/** /**
* @desc Print channels * @desc Print channels
* @access private * @access private
@ -344,7 +344,7 @@ define('JSONP', 3, true);
{ {
//Start channel tag //Start channel tag
if ($this->version == RSS2) { if ($this->version == RSS2) {
echo '<channel>' . PHP_EOL; echo '<channel>' . PHP_EOL;
// add hubs // add hubs
foreach ($this->hubs as $hub) { foreach ($this->hubs as $hub) {
//echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom')); //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));
@ -356,7 +356,7 @@ define('JSONP', 3, true);
echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL; echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
} }
//Print Items of channel //Print Items of channel
foreach ($this->channels as $key => $value) foreach ($this->channels as $key => $value)
{ {
echo $this->makeNode($key, $value); echo $this->makeNode($key, $value);
} }
@ -364,26 +364,26 @@ define('JSONP', 3, true);
$this->json->rss['channel'] = (object)$this->json_keys($this->channels); $this->json->rss['channel'] = (object)$this->json_keys($this->channels);
} }
} }
/** /**
* Prints formatted feed items * Prints formatted feed items
* *
* @access private * @access private
* @return void * @return void
*/ */
private function printItems() private function printItems()
{ {
foreach ($this->items as $item) { foreach ($this->items as $item) {
$itemElements = $item->getElements(); $itemElements = $item->getElements();
echo $this->startItem(); echo $this->startItem();
if ($this->version == JSON || $this->version == JSONP) { if ($this->version == JSON || $this->version == JSONP) {
$json_item = array(); $json_item = array();
} }
foreach ($itemElements as $thisElement) { foreach ($itemElements as $thisElement) {
foreach ($thisElement as $instance) { foreach ($thisElement as $instance) {
if ($this->version == RSS2) { if ($this->version == RSS2) {
echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']); echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
} elseif ($this->version == JSON || $this->version == JSONP) { } elseif ($this->version == JSON || $this->version == JSONP) {
@ -406,10 +406,10 @@ define('JSONP', 3, true);
} }
} }
} }
/** /**
* Make the starting tag of channels * Make the starting tag of channels
* *
* @access private * @access private
* @return void * @return void
*/ */
@ -417,14 +417,14 @@ define('JSONP', 3, true);
{ {
if ($this->version == RSS2) if ($this->version == RSS2)
{ {
echo '<item>' . PHP_EOL; echo '<item>' . PHP_EOL;
} }
// nothing for JSON // nothing for JSON
} }
/** /**
* Closes feed item tag * Closes feed item tag
* *
* @access private * @access private
* @return void * @return void
*/ */
@ -432,10 +432,10 @@ define('JSONP', 3, true);
{ {
if ($this->version == RSS2) if ($this->version == RSS2)
{ {
echo '</item>' . PHP_EOL; echo '</item>' . PHP_EOL;
} }
// nothing for JSON // nothing for JSON
} }
// End # private functions ---------------------------------------------- // End # private functions ----------------------------------------------
} }

View File

@ -18,7 +18,7 @@ class Database {
'default' => 'ORDER BY entries.id' 'default' => 'ORDER BY entries.id'
); );
function __construct() function __construct()
{ {
switch (STORAGE) { switch (STORAGE) {
case 'sqlite': case 'sqlite':
@ -27,11 +27,11 @@ class Database {
break; break;
case 'mysql': case 'mysql':
$db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB; $db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD); $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
break; break;
case 'postgres': case 'postgres':
$db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB; $db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD); $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
break; break;
} }
@ -51,7 +51,7 @@ class Database {
} }
$hasAdmin = count($query->fetchAll()); $hasAdmin = count($query->fetchAll());
if ($hasAdmin == 0) if ($hasAdmin == 0)
return false; return false;
return true; return true;
@ -140,7 +140,7 @@ class Database {
$sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
$params = array($id_user, 'language', LANG); $params = array($id_user, 'language', LANG);
$query = $this->executeQuery($sql, $params); $query = $this->executeQuery($sql, $params);
$sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
$params = array($id_user, 'theme', DEFAULT_THEME); $params = array($id_user, 'theme', DEFAULT_THEME);
$query = $this->executeQuery($sql, $params); $query = $this->executeQuery($sql, $params);
@ -153,7 +153,7 @@ class Database {
$query = $this->executeQuery($sql, array($id)); $query = $this->executeQuery($sql, array($id));
$result = $query->fetchAll(); $result = $query->fetchAll();
$user_config = array(); $user_config = array();
foreach ($result as $key => $value) { foreach ($result as $key => $value) {
$user_config[$value['name']] = $value['value']; $user_config[$value['name']] = $value['value'];
} }
@ -201,10 +201,10 @@ class Database {
$params_update = array($password, $userId); $params_update = array($password, $userId);
$query = $this->executeQuery($sql_update, $params_update); $query = $this->executeQuery($sql_update, $params_update);
} }
public function updateUserConfig($userId, $key, $value) { public function updateUserConfig($userId, $key, $value) {
$config = $this->getConfigUser($userId); $config = $this->getConfigUser($userId);
if (! isset($config[$key])) { if (! isset($config[$key])) {
$sql = "INSERT INTO users_config (value, user_id, name) VALUES (?, ?, ?)"; $sql = "INSERT INTO users_config (value, user_id, name) VALUES (?, ?, ?)";
} }
@ -252,8 +252,16 @@ class Database {
return $entries; return $entries;
} }
public function retrieveUnfetchedEntriesCount($user_id) {
$sql = "SELECT count(*) FROM entries WHERE (content = '' OR content IS NULL) AND user_id=?";
$query = $this->executeQuery($sql, array($user_id));
list($count) = $query->fetch();
return $count;
}
public function retrieveAll($user_id) { public function retrieveAll($user_id) {
$sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? ORDER BY id"; $sql = "SELECT * FROM entries WHERE user_id=? ORDER BY id";
$query = $this->executeQuery($sql, array($user_id)); $query = $this->executeQuery($sql, array($user_id));
$entries = $query->fetchAll(); $entries = $query->fetchAll();
@ -272,7 +280,7 @@ class Database {
public function retrieveOneByURL($url, $user_id) { public function retrieveOneByURL($url, $user_id) {
$entry = NULL; $entry = NULL;
$sql = "SELECT * FROM entries WHERE content <> '' AND url=? AND user_id=?"; $sql = "SELECT * FROM entries WHERE url=? AND user_id=?";
$params = array($url, $user_id); $params = array($url, $user_id);
$query = $this->executeQuery($sql, $params); $query = $this->executeQuery($sql, $params);
$entry = $query->fetchAll(); $entry = $query->fetchAll();
@ -289,22 +297,21 @@ class Database {
public function getEntriesByView($view, $user_id, $limit = '', $tag_id = 0) { public function getEntriesByView($view, $user_id, $limit = '', $tag_id = 0) {
switch ($view) { switch ($view) {
case 'archive': case 'archive':
$sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 1); $params = array($user_id, 1);
break; break;
case 'fav' : case 'fav' :
$sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_fav=? "; $sql = "SELECT * FROM entries WHERE user_id=? AND is_fav=? ";
$params = array($user_id, 1); $params = array($user_id, 1);
break; break;
case 'tag' : case 'tag' :
$sql = "SELECT entries.* FROM entries $sql = "SELECT entries.* FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE entries.content <> '' AND WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
entries.user_id=? AND tags_entries.tag_id = ? ";
$params = array($user_id, $tag_id); $params = array($user_id, $tag_id);
break; break;
default: default:
$sql = "SELECT * FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 0); $params = array($user_id, 0);
break; break;
} }
@ -320,22 +327,21 @@ class Database {
public function getEntriesByViewCount($view, $user_id, $tag_id = 0) { public function getEntriesByViewCount($view, $user_id, $tag_id = 0) {
switch ($view) { switch ($view) {
case 'archive': case 'archive':
$sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 1); $params = array($user_id, 1);
break; break;
case 'fav' : case 'fav' :
$sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_fav=? "; $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_fav=? ";
$params = array($user_id, 1); $params = array($user_id, 1);
break; break;
case 'tag' : case 'tag' :
$sql = "SELECT count(*) FROM entries $sql = "SELECT count(*) FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE entries.content <> '' AND WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
entries.user_id=? AND tags_entries.tag_id = ? ";
$params = array($user_id, $tag_id); $params = array($user_id, $tag_id);
break; break;
default: default:
$sql = "SELECT count(*) FROM entries WHERE content <> '' AND user_id=? AND is_read=? "; $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 0); $params = array($user_id, 0);
break; break;
} }
@ -353,11 +359,24 @@ class Database {
return $query; return $query;
} }
public function add($url, $title, $content, $user_id) { /**
$sql_action = 'INSERT INTO entries ( url, title, content, user_id ) VALUES (?, ?, ?, ?)'; *
$params_action = array($url, $title, $content, $user_id); * @param string $url
$query = $this->executeQuery($sql_action, $params_action); * @param string $title
return $query; * @param string $content
* @param integer $user_id
* @return integer $id of inserted record
*/
public function add($url, $title, $content, $user_id, $isFavorite=0, $isRead=0) {
$sql_action = 'INSERT INTO entries ( url, title, content, user_id, is_fav, is_read ) VALUES (?, ?, ?, ?, ?, ?)';
$params_action = array($url, $title, $content, $user_id, $isFavorite, $isRead);
if ( !$this->executeQuery($sql_action, $params_action) ) {
$id = null;
}
else {
$id = intval($this->getLastId( (STORAGE == 'postgres') ? 'users_id_seq' : '' ));
}
return $id;
} }
public function deleteById($id, $user_id) { public function deleteById($id, $user_id) {
@ -388,7 +407,7 @@ class Database {
public function getLastId($column = '') { public function getLastId($column = '') {
return $this->getHandle()->lastInsertId($column); return $this->getHandle()->lastInsertId($column);
} }
public function search($term){ public function search($term){
$search = '%'.$term.'%'; $search = '%'.$term.'%';
$query = $this->getHandle()->prepare("SELECT * FROM entries WHERE content LIKE ? OR title LIKE ? OR url LIKE ?"); //searches in content, title and URL $query = $this->getHandle()->prepare("SELECT * FROM entries WHERE content LIKE ? OR title LIKE ? OR url LIKE ?"); //searches in content, title and URL
@ -401,7 +420,7 @@ class Database {
$sql = "SELECT DISTINCT tags.*, count(entries.id) AS entriescount FROM tags $sql = "SELECT DISTINCT tags.*, count(entries.id) AS entriescount FROM tags
LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
LEFT JOIN entries ON tags_entries.entry_id=entries.id LEFT JOIN entries ON tags_entries.entry_id=entries.id
WHERE entries.content <> '' AND entries.user_id=? WHERE entries.user_id=?
". (($term) ? "AND lower(tags.value) LIKE ?" : '') ." ". (($term) ? "AND lower(tags.value) LIKE ?" : '') ."
GROUP BY tags.id, tags.value GROUP BY tags.id, tags.value
ORDER BY tags.value"; ORDER BY tags.value";
@ -416,7 +435,7 @@ class Database {
$sql = "SELECT DISTINCT tags.* FROM tags $sql = "SELECT DISTINCT tags.* FROM tags
LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
LEFT JOIN entries ON tags_entries.entry_id=entries.id LEFT JOIN entries ON tags_entries.entry_id=entries.id
WHERE entries.content <> '' AND tags.id=? AND entries.user_id=?"; WHERE tags.id=? AND entries.user_id=?";
$params = array(intval($id), $user_id); $params = array(intval($id), $user_id);
$query = $this->executeQuery($sql, $params); $query = $this->executeQuery($sql, $params);
$tag = $query->fetchAll(); $tag = $query->fetchAll();
@ -425,11 +444,10 @@ class Database {
} }
public function retrieveEntriesByTag($tag_id, $user_id) { public function retrieveEntriesByTag($tag_id, $user_id) {
$sql = $sql =
"SELECT entries.* FROM entries "SELECT entries.* FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE entries.content <> '' AND WHERE tags_entries.tag_id = ? AND entries.user_id=?";
tags_entries.tag_id = ? AND entries.user_id=?";
$query = $this->executeQuery($sql, array($tag_id, $user_id)); $query = $this->executeQuery($sql, array($tag_id, $user_id));
$entries = $query->fetchAll(); $entries = $query->fetchAll();
@ -437,7 +455,7 @@ class Database {
} }
public function retrieveTagsByEntry($entry_id) { public function retrieveTagsByEntry($entry_id) {
$sql = $sql =
"SELECT tags.* FROM tags "SELECT tags.* FROM tags
LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
WHERE tags_entries.entry_id = ?"; WHERE tags_entries.entry_id = ?";

View File

@ -18,7 +18,7 @@ class Poche
public $tpl; public $tpl;
public $messages; public $messages;
public $pagination; public $pagination;
private $currentTheme = ''; private $currentTheme = '';
private $currentLanguage = ''; private $currentLanguage = '';
private $notInstalledMessage = array(); private $notInstalledMessage = array();
@ -42,11 +42,11 @@ class Poche
if ($this->configFileIsAvailable()) { if ($this->configFileIsAvailable()) {
$this->init(); $this->init();
} }
if ($this->themeIsInstalled()) { if ($this->themeIsInstalled()) {
$this->initTpl(); $this->initTpl();
} }
if ($this->systemIsInstalled()) { if ($this->systemIsInstalled()) {
$this->store = new Database(); $this->store = new Database();
$this->messages = new Messages(); $this->messages = new Messages();
@ -57,8 +57,8 @@ class Poche
$this->store->checkTags(); $this->store->checkTags();
} }
} }
private function init() private function init()
{ {
Tools::initPhp(); Tools::initPhp();
@ -74,28 +74,28 @@ class Poche
$language = $this->user->getConfigValue('language'); $language = $this->user->getConfigValue('language');
putenv('LC_ALL=' . $language); putenv('LC_ALL=' . $language);
setlocale(LC_ALL, $language); setlocale(LC_ALL, $language);
bindtextdomain($language, LOCALE); bindtextdomain($language, LOCALE);
textdomain($language); textdomain($language);
# Pagination # Pagination
$this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p'); $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p');
# Set up theme # Set up theme
$themeDirectory = $this->user->getConfigValue('theme'); $themeDirectory = $this->user->getConfigValue('theme');
if ($themeDirectory === false) { if ($themeDirectory === false) {
$themeDirectory = DEFAULT_THEME; $themeDirectory = DEFAULT_THEME;
} }
$this->currentTheme = $themeDirectory; $this->currentTheme = $themeDirectory;
# Set up language # Set up language
$languageDirectory = $this->user->getConfigValue('language'); $languageDirectory = $this->user->getConfigValue('language');
if ($languageDirectory === false) { if ($languageDirectory === false) {
$languageDirectory = DEFAULT_THEME; $languageDirectory = DEFAULT_THEME;
} }
$this->currentLanguage = $languageDirectory; $this->currentLanguage = $languageDirectory;
} }
@ -108,7 +108,7 @@ class Poche
return true; return true;
} }
public function themeIsInstalled() { public function themeIsInstalled() {
$passTheme = TRUE; $passTheme = TRUE;
# Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet
@ -123,27 +123,27 @@ class Poche
self::$canRenderTemplates = false; self::$canRenderTemplates = false;
$passTheme = FALSE; $passTheme = FALSE;
} }
# Check if the selected theme and its requirements are present # Check if the selected theme and its requirements are present
$theme = $this->getTheme(); $theme = $this->getTheme();
if ($theme != '' && ! is_dir(THEME . '/' . $theme)) { if ($theme != '' && ! is_dir(THEME . '/' . $theme)) {
$this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')'; $this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')';
self::$canRenderTemplates = false; self::$canRenderTemplates = false;
$passTheme = FALSE; $passTheme = FALSE;
} }
$themeInfo = $this->getThemeInfo($theme); $themeInfo = $this->getThemeInfo($theme);
if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
foreach ($themeInfo['requirements'] as $requiredTheme) { foreach ($themeInfo['requirements'] as $requiredTheme) {
if (! is_dir(THEME . '/' . $requiredTheme)) { if (! is_dir(THEME . '/' . $requiredTheme)) {
$this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')'; $this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')';
self::$canRenderTemplates = false; self::$canRenderTemplates = false;
$passTheme = FALSE; $passTheme = FALSE;
} }
} }
@ -153,21 +153,21 @@ class Poche
return FALSE; return FALSE;
} }
return true; return true;
} }
/** /**
* all checks before installation. * all checks before installation.
* @todo move HTML to template * @todo move HTML to template
* @return boolean * @return boolean
*/ */
public function systemIsInstalled() public function systemIsInstalled()
{ {
$msg = TRUE; $msg = TRUE;
$configSalt = defined('SALT') ? constant('SALT') : ''; $configSalt = defined('SALT') ? constant('SALT') : '';
if (empty($configSalt)) { if (empty($configSalt)) {
$this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.'; $this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.';
$msg = FALSE; $msg = FALSE;
@ -193,7 +193,7 @@ class Poche
return true; return true;
} }
public function getNotInstalledMessage() { public function getNotInstalledMessage() {
return $this->notInstalledMessage; return $this->notInstalledMessage;
} }
@ -202,7 +202,7 @@ class Poche
{ {
$loaderChain = new Twig_Loader_Chain(); $loaderChain = new Twig_Loader_Chain();
$theme = $this->getTheme(); $theme = $this->getTheme();
# add the current theme as first to the loader chain so Twig will look there first for overridden template files # add the current theme as first to the loader chain so Twig will look there first for overridden template files
try { try {
$loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme)); $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme));
@ -210,7 +210,7 @@ class Poche
# @todo isInstalled() should catch this, inject Twig later # @todo isInstalled() should catch this, inject Twig later
die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)'); die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)');
} }
# add all required themes to the loader chain # add all required themes to the loader chain
$themeInfo = $this->getThemeInfo($theme); $themeInfo = $this->getThemeInfo($theme);
if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
@ -223,16 +223,16 @@ class Poche
} }
} }
} }
if (DEBUG_POCHE) { if (DEBUG_POCHE) {
$twigParams = array(); $twigParams = array();
} else { } else {
$twigParams = array('cache' => CACHE); $twigParams = array('cache' => CACHE);
} }
$this->tpl = new Twig_Environment($loaderChain, $twigParams); $this->tpl = new Twig_Environment($loaderChain, $twigParams);
$this->tpl->addExtension(new Twig_Extensions_Extension_I18n()); $this->tpl->addExtension(new Twig_Extensions_Extension_I18n());
# filter to display domain name of an url # filter to display domain name of an url
$filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain'); $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain');
$this->tpl->addFilter($filter); $this->tpl->addFilter($filter);
@ -251,7 +251,7 @@ class Poche
'poche_url' => Tools::getPocheUrl() 'poche_url' => Tools::getPocheUrl()
)); ));
if (isset($_GET['install'])) { if (isset($_GET['install'])) {
if (($_POST['password'] == $_POST['password_repeat']) if (($_POST['password'] == $_POST['password_repeat'])
&& $_POST['password'] != "" && $_POST['login'] != "") { && $_POST['password'] != "" && $_POST['login'] != "") {
# let's rock, install poche baby ! # let's rock, install poche baby !
if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']))) if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login'])))
@ -268,7 +268,7 @@ class Poche
} }
exit(); exit();
} }
public function getTheme() { public function getTheme() {
return $this->currentTheme; return $this->currentTheme;
} }
@ -293,7 +293,7 @@ class Poche
if (is_file($themeIniFile) && is_readable($themeIniFile)) { if (is_file($themeIniFile) && is_readable($themeIniFile)) {
$themeInfo = parse_ini_file($themeIniFile); $themeInfo = parse_ini_file($themeIniFile);
} }
if ($themeInfo === false) { if ($themeInfo === false) {
$themeInfo = array(); $themeInfo = array();
} }
@ -304,7 +304,7 @@ class Poche
return $themeInfo; return $themeInfo;
} }
public function getInstalledThemes() { public function getInstalledThemes() {
$handle = opendir(THEME); $handle = opendir(THEME);
$themes = array(); $themes = array();
@ -331,28 +331,28 @@ class Poche
public function getInstalledLanguages() { public function getInstalledLanguages() {
$handle = opendir(LOCALE); $handle = opendir(LOCALE);
$languages = array(); $languages = array();
while (($language = readdir($handle)) !== false) { while (($language = readdir($handle)) !== false) {
# Languages are stored in a directory, so all directory names are languages # Languages are stored in a directory, so all directory names are languages
# @todo move language installation data to database # @todo move language installation data to database
if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) { if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) {
continue; continue;
} }
$current = false; $current = false;
if ($language === $this->getLanguage()) { if ($language === $this->getLanguage()) {
$current = true; $current = true;
} }
$languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current); $languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current);
} }
return $languages; return $languages;
} }
public function getDefaultConfig() public function getDefaultConfig()
{ {
return array( return array(
'pager' => PAGINATION, 'pager' => PAGINATION,
'language' => LANG, 'language' => LANG,
@ -385,19 +385,15 @@ class Poche
$body = ''; $body = '';
} }
//search for possible duplicate if not in import mode //search for possible duplicate
$duplicate = NULL; $duplicate = NULL;
if (!$import) { if (!$import) {
$duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId()); $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId());
} }
if ($this->store->add($url->getUrl(), $title, $body, $this->user->getId())) { $last_id = $this->store->add($url->getUrl(), $title, $body, $this->user->getId());
if ( $last_id && !$import ) {
Tools::logm('add link ' . $url->getUrl()); Tools::logm('add link ' . $url->getUrl());
$sequence = '';
if (STORAGE == 'postgres') {
$sequence = 'entries_id_seq';
}
$last_id = $this->store->getLastId($sequence);
if (DOWNLOAD_PICTURES) { if (DOWNLOAD_PICTURES) {
$content = filtre_picture($body, $url->getUrl(), $last_id); $content = filtre_picture($body, $url->getUrl(), $last_id);
Tools::logm('updating content article'); Tools::logm('updating content article');
@ -417,9 +413,7 @@ class Poche
} }
} }
if (!$import) { $this->messages->add('s', _('the link has been added successfully'));
$this->messages->add('s', _('the link has been added successfully'));
}
} }
else { else {
if (!$import) { if (!$import) {
@ -603,7 +597,7 @@ class Poche
'tags' => $tags, 'tags' => $tags,
); );
break; break;
case 'search': case 'search':
if (isset($_GET['search'])){ if (isset($_GET['search'])){
$search = $_GET['search']; $search = $_GET['search'];
@ -647,7 +641,7 @@ class Poche
'nb_results' => '', 'nb_results' => '',
'listmode' => (isset($_COOKIE['listmode']) ? true : false), 'listmode' => (isset($_COOKIE['listmode']) ? true : false),
); );
//if id is given - we retrive entries by tag: id is tag id //if id is given - we retrive entries by tag: id is tag id
if ($id) { if ($id) {
$tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId()); $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId());
@ -672,8 +666,8 @@ class Poche
} }
/** /**
* update the password of the current user. * update the password of the current user.
* if MODE_DEMO is TRUE, the password can't be updated. * if MODE_DEMO is TRUE, the password can't be updated.
* @todo add the return value * @todo add the return value
* @todo set the new password in function header like this updatePassword($newPassword) * @todo set the new password in function header like this updatePassword($newPassword)
* @return boolean * @return boolean
@ -701,44 +695,44 @@ class Poche
} }
} }
} }
public function updateTheme() public function updateTheme()
{ {
# no data # no data
if (empty($_POST['theme'])) { if (empty($_POST['theme'])) {
} }
# we are not going to change it to the current theme... # we are not going to change it to the current theme...
if ($_POST['theme'] == $this->getTheme()) { if ($_POST['theme'] == $this->getTheme()) {
$this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!')); $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!'));
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
$themes = $this->getInstalledThemes(); $themes = $this->getInstalledThemes();
$actualTheme = false; $actualTheme = false;
foreach (array_keys($themes) as $theme) { foreach (array_keys($themes) as $theme) {
if ($theme == $_POST['theme']) { if ($theme == $_POST['theme']) {
$actualTheme = true; $actualTheme = true;
break; break;
} }
} }
if (! $actualTheme) { if (! $actualTheme) {
$this->messages->add('e', _('that theme does not seem to be installed')); $this->messages->add('e', _('that theme does not seem to be installed'));
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
$this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']); $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']);
$this->messages->add('s', _('you have changed your theme preferences')); $this->messages->add('s', _('you have changed your theme preferences'));
$currentConfig = $_SESSION['poche_user']->config; $currentConfig = $_SESSION['poche_user']->config;
$currentConfig['theme'] = $_POST['theme']; $currentConfig['theme'] = $_POST['theme'];
$_SESSION['poche_user']->setConfig($currentConfig); $_SESSION['poche_user']->setConfig($currentConfig);
$this->emptyCache(); $this->emptyCache();
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
@ -747,40 +741,40 @@ class Poche
# no data # no data
if (empty($_POST['language'])) { if (empty($_POST['language'])) {
} }
# we are not going to change it to the current language... # we are not going to change it to the current language...
if ($_POST['language'] == $this->getLanguage()) { if ($_POST['language'] == $this->getLanguage()) {
$this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!')); $this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!'));
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
$languages = $this->getInstalledLanguages(); $languages = $this->getInstalledLanguages();
$actualLanguage = false; $actualLanguage = false;
foreach ($languages as $language) { foreach ($languages as $language) {
if ($language['value'] == $_POST['language']) { if ($language['value'] == $_POST['language']) {
$actualLanguage = true; $actualLanguage = true;
break; break;
} }
} }
if (! $actualLanguage) { if (! $actualLanguage) {
$this->messages->add('e', _('that language does not seem to be installed')); $this->messages->add('e', _('that language does not seem to be installed'));
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
$this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']); $this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']);
$this->messages->add('s', _('you have changed your language preferences')); $this->messages->add('s', _('you have changed your language preferences'));
$currentConfig = $_SESSION['poche_user']->config; $currentConfig = $_SESSION['poche_user']->config;
$currentConfig['language'] = $_POST['language']; $currentConfig['language'] = $_POST['language'];
$_SESSION['poche_user']->setConfig($currentConfig); $_SESSION['poche_user']->setConfig($currentConfig);
$this->emptyCache(); $this->emptyCache();
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
/** /**
* get credentials from differents sources * get credentials from differents sources
* it redirects the user to the $referer link * it redirects the user to the $referer link
@ -835,7 +829,7 @@ class Poche
/** /**
* log out the poche user. It cleans the session. * log out the poche user. It cleans the session.
* @todo add the return value * @todo add the return value
* @return boolean * @return boolean
*/ */
public function logout() public function logout()
{ {
@ -891,7 +885,7 @@ class Poche
* import from Pocket. poche needs a ./ril_export.html file * import from Pocket. poche needs a ./ril_export.html file
* @todo add the return value * @todo add the return value
* @param string $targetFile the file used for importing * @param string $targetFile the file used for importing
* @return boolean * @return boolean
*/ */
private function importFromPocket($targetFile) private function importFromPocket($targetFile)
{ {
@ -922,7 +916,7 @@ class Poche
$this->action('add_tag',$url,$last_id,true,false,$tags); $this->action('add_tag',$url,$last_id,true,false,$tags);
} }
} }
# the second <ul> is for read links # the second <ul> is for read links
$read = 1; $read = 1;
} }
@ -937,7 +931,7 @@ class Poche
* import from Readability. poche needs a ./readability file * import from Readability. poche needs a ./readability file
* @todo add the return value * @todo add the return value
* @param string $targetFile the file used for importing * @param string $targetFile the file used for importing
* @return boolean * @return boolean
*/ */
private function importFromReadability($targetFile) private function importFromReadability($targetFile)
{ {
@ -994,7 +988,7 @@ class Poche
/** /**
* import from Poche exported file * import from Poche exported file
* @param string $targetFile the file used for importing * @param string $targetFile the file used for importing
* @return boolean * @return boolean
*/ */
private function importFromPoche($targetFile) private function importFromPoche($targetFile)
{ {
@ -1014,12 +1008,12 @@ class Poche
$url = new Url(base64_encode($value['url'])); $url = new Url(base64_encode($value['url']));
$favorite = ($value['is_fav'] == -1); $favorite = ($value['is_fav'] == -1);
$archive = ($value['is_read'] == -1); $archive = ($value['is_read'] == -1);
# we can add the url # we can add the url
if (!is_null($url) && $url->isCorrect()) { if (!is_null($url) && $url->isCorrect()) {
$this->action('add', $url, 0, TRUE); $this->action('add', $url, 0, TRUE);
$count++; $count++;
if ($favorite) { if ($favorite) {
$last_id = $this->store->getLastId($sequence); $last_id = $this->store->getLastId($sequence);
@ -1030,7 +1024,7 @@ class Poche
$this->action('toggle_archive', $url, $last_id, TRUE); $this->action('toggle_archive', $url, $last_id, TRUE);
} }
} }
} }
unlink($targetFile); unlink($targetFile);
@ -1041,37 +1035,115 @@ class Poche
/** /**
* import datas into your poche * import datas into your poche
* @param string $from name of the service to import : pocket, instapaper or readability * @return boolean
* @todo add the return value
* @return boolean
*/ */
public function import($from) public function import() {
{
$providers = array( if ( isset($_FILES['file']) ) {
'pocket' => 'importFromPocket', // assume, that file is in json format
'readability' => 'importFromReadability', $str_data = file_get_contents($_FILES['file']['tmp_name']);
'instapaper' => 'importFromInstapaper', $data = json_decode($str_data, true);
'poche' => 'importFromPoche',
); if ( $data === null ) {
//not json - assume html
if (! isset($providers[$from])) { $html = new simple_html_dom();
$this->messages->add('e', _('Unknown import provider.')); $html->load_file($_FILES['file']['tmp_name']);
Tools::redirect(); $data = array();
$read = 0;
foreach (array('ol','ul') as $list) {
foreach ($html->find($list) as $ul) {
foreach ($ul->find('li') as $li) {
$tmpEntry = array();
$a = $li->find('a');
$tmpEntry['url'] = $a[0]->href;
$tmpEntry['tags'] = $a[0]->tags;
$tmpEntry['is_read'] = $read;
if ($tmpEntry['url']) {
$data[] = $tmpEntry;
}
}
# the second <ol/ul> is for read links
$read = ((sizeof($data) && $read)?0:1);
}
}
} }
$targetFile = CACHE . '/' . constant(strtoupper($from) . '_FILE'); $i = 0; //counter for articles inserted
foreach ($data as $record) {
if (! file_exists($targetFile)) { //echo '<pre>';
$this->messages->add('e', _('Could not find required "' . $targetFile . '" import file.')); //var_dump($record);
Tools::redirect(); // foreach ($record as $key=>$val) {
// echo "\n=================\n$i: $key: $val\n";
// }
// exit;
$url = trim($record['url']);
if ( $url ) {
$title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>');
$body = (isset($record['content']) ? $record['content'] : '');
$isRead = (isset($record['is_read']) ? intval($record['is_read']) : 0);
$isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : 0);
//insert new record
$id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead);
if ( $id ) {
//increment no of records inserted
$i++;
if ( isset($record['tags']) && trim($record['tags']) ) {
//@TODO: set tags
}
}
}
} }
$this->$providers[$from]($targetFile); if ( $i > 0 ) {
$this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".'));
}
}
//file parsing finished here
//now download article contents if any
//check if we need to download any content
$recordsDownloadRequired = $this->store->retrieveUnfetchedEntriesCount($this->user->getId());
if ( $recordsDownloadRequired == 0 ) {
//nothing to download
$this->messages->add('s', _('Import finished.'));
Tools::redirect();
}
else {
//if just inserted - don't download anything, download will start in next reload
if ( !isset($_FILES['file']) ) {
//download next batch
$items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', CACHE);
$purifier = new HTMLPurifier($config);
foreach ($items as $item) {
$url = new Url(base64_encode($item['url']));
$content = Tools::getPageContent($url);
$title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
$body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
//clean content to prevent xss attack
$title = $purifier->purify($title);
$body = $purifier->purify($body);
$this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
}
}
}
return array('includeImport'=>true, 'import'=>array('recordsDownloadRequired'=>$recordsDownloadRequired, 'recordsUnderDownload'=> IMPORT_LIMIT, 'delay'=> IMPORT_DELAY * 1000) );
} }
public function uploadFile() { public function uploadFile() {
if(isset($_FILES['file'])) if (isset($_FILES['file']))
{ {
$dir = CACHE . '/'; $dir = CACHE . '/';
$file = basename($_FILES['file']['name']); $file = basename($_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) { if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) {
@ -1081,7 +1153,7 @@ class Poche
$this->messages->add('e', _('Error while importing file. Do you have access to upload it?')); $this->messages->add('e', _('Error while importing file. Do you have access to upload it?'));
} }
} }
Tools::redirect('?view=config'); Tools::redirect('?view=config');
} }
@ -1093,7 +1165,7 @@ class Poche
{ {
$filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json"; $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
header('Content-Disposition: attachment; filename='.$filename); header('Content-Disposition: attachment; filename='.$filename);
$entries = $this->store->retrieveAll($this->user->getId()); $entries = $this->store->retrieveAll($this->user->getId());
echo $this->tpl->render('export.twig', array( echo $this->tpl->render('export.twig', array(
'export' => Tools::renderJson($entries), 'export' => Tools::renderJson($entries),

View File

@ -7,7 +7,7 @@
* @copyright 2013 * @copyright 2013
* @license http://www.wtfpl.net/ see COPYING file * @license http://www.wtfpl.net/ see COPYING file
*/ */
class Tools class Tools
{ {
public static function initPhp() public static function initPhp()
@ -42,7 +42,7 @@ class Tools
&& (strtolower($_SERVER['HTTPS']) == 'on')) && (strtolower($_SERVER['HTTPS']) == 'on'))
|| (isset($_SERVER["SERVER_PORT"]) || (isset($_SERVER["SERVER_PORT"])
&& $_SERVER["SERVER_PORT"] == '443') // HTTPS detection. && $_SERVER["SERVER_PORT"] == '443') // HTTPS detection.
|| (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection || (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection
&& $_SERVER["SERVER_PORT"] == SSL_PORT) && $_SERVER["SERVER_PORT"] == SSL_PORT)
|| (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'); && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
@ -148,7 +148,7 @@ class Tools
); );
# only download page lesser than 4MB # only download page lesser than 4MB
$data = @file_get_contents($url, false, $context, -1, 4000000); $data = @file_get_contents($url, false, $context, -1, 4000000);
if (isset($http_response_header) and isset($http_response_header[0])) { if (isset($http_response_header) and isset($http_response_header[0])) {
$httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE)); $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE));
@ -200,7 +200,7 @@ class Tools
} }
} }
public static function encodeString($string) public static function encodeString($string)
{ {
return sha1($string . SALT); return sha1($string . SALT);
} }

View File

@ -52,12 +52,8 @@ define ('CACHE', ROOT . '/cache');
define ('PAGINATION', '10'); define ('PAGINATION', '10');
define ('POCKET_FILE', '/ril_export.html'); //limit for download of articles during import
define ('READABILITY_FILE', '/readability'); define ('IMPORT_LIMIT', 5);
define ('INSTAPAPER_FILE', '/instapaper-export.html'); //delay between downloads (in sec)
define ('POCHE_FILE', '/poche-export'); define ('IMPORT_DELAY', 5);
define ('IMPORT_POCKET_FILE', ROOT . POCKET_FILE);
define ('IMPORT_READABILITY_FILE', ROOT . READABILITY_FILE);
define ('IMPORT_INSTAPAPER_FILE', ROOT . INSTAPAPER_FILE);
define ('IMPORT_POCHE_FILE', ROOT . POCHE_FILE);

5
index.php Normal file → Executable file
View File

@ -40,7 +40,7 @@ $tpl_vars = array(
if (! empty($notInstalledMessage)) { if (! empty($notInstalledMessage)) {
if (! Poche::$canRenderTemplates || ! Poche::$configFileAvailable) { if (! Poche::$canRenderTemplates || ! Poche::$configFileAvailable) {
# We cannot use Twig to display the error message # We cannot use Twig to display the error message
echo '<h1>Errors</h1><ol>'; echo '<h1>Errors</h1><ol>';
foreach ($notInstalledMessage as $message) { foreach ($notInstalledMessage as $message) {
echo '<li>' . $message . '</li>'; echo '<li>' . $message . '</li>';
@ -67,7 +67,8 @@ if (isset($_GET['login'])) {
# Update password # Update password
$poche->updatePassword(); $poche->updatePassword();
} elseif (isset($_GET['import'])) { } elseif (isset($_GET['import'])) {
$import = $poche->import($_GET['from']); $import = $poche->import();
$tpl_vars = array_merge($tpl_vars, $import);
} elseif (isset($_GET['download'])) { } elseif (isset($_GET['download'])) {
Tools::download_db(); Tools::download_db();
} elseif (isset($_GET['empty-cache'])) { } elseif (isset($_GET['empty-cache'])) {

15
themes/default/_import.twig Executable file
View File

@ -0,0 +1,15 @@
<script type="text/javascript">
<!--
$(document).ready(function() {
$("body").css("cursor", "wait");
setTimeout(function(){
window.location = '/?import';
}, {{ import.delay }} );
});
//-->
</script>
<div class="messages warning">
<p>{% trans "Download required for " %} {{ import.recordsDownloadRequired }} {% trans "records" %}.</p>
<p>{% trans "Downloading next " %} {{ import.recordsUnderDownload }} {% trans "articles, please wait" %}...</p>
</div>

25
themes/default/config.twig Normal file → Executable file
View File

@ -104,36 +104,19 @@
{% endif %} {% endif %}
<h2>{% trans "Import" %}</h2> <h2>{% trans "Import" %}</h2>
<p>{% trans "Importing from other services can be quite long, and webservers default configuration often prevents long scripts execution time, so it must be done in multiple parts." %}</p> <p>{% trans "You can import your Pocket, Readability, Instapaper, Wallabag or any data in appropriate json or html format." %}</p>
<p>1. {% trans "First, select the export file on your computer and upload it." %}</p> <p>{% trans "Please select export file on your computer:" %}</p>
<form method="post" action="?uploadfile" name="uploadfile" enctype="multipart/form-data"> <form method="post" action="?import" name="uploadfile" enctype="multipart/form-data">
<fieldset class="w500p"> <fieldset class="w500p">
<div class="row"> <div class="row">
<label class="col w150p" for="file">{% trans "File:" %}</label> <label class="col w150p" for="file">{% trans "File:" %}</label>
<input class="col" type="file" id="file" name="file" tabindex="4"> <input class="col" type="file" id="file" name="file" tabindex="4">
</div> </div>
<div class="row mts txtcenter"> <div class="row mts txtcenter">
<button class="bouton" type="submit" tabindex="4">{% trans "Upload" %}</button> <button class="bouton" type="submit" tabindex="4">{% trans "Import" %}</button>
</div> </div>
</fieldset> </fieldset>
<input type="hidden" name="MAX_FILE_SIZE" value="1048576">
<input type="hidden" name="returnurl" value="{{ referer }}">
</form> </form>
<p>2. {% trans "Then, click on the right link below." %}</p>
<ul>
<li><a href="./?import&amp;from=pocket">{% trans "Import from Pocket" %}</a> {{ '(after uploaded %s file)'|trans|format(constant('POCKET_FILE')) }}</li>
<li><a href="./?import&amp;from=readability">{% trans "Import from Readability" %}</a> {{ '(after uploaded %s file)'|trans|format(constant('READABILITY_FILE')) }}</li>
<li><a href="./?import&amp;from=instapaper">{% trans "Import from Instapaper" %}</a> {{ '(after uploaded %s file)'|trans|format(constant('INSTAPAPER_FILE')) }}</li>
<li><a href="./?import&amp;from=poche">{% trans "Import from wallabag" %}</a> {{ '(after uploaded %s file)'|trans|format(constant('POCHE_FILE')) }}</li>
</ul>
{% if token == '' %}
<p>{% trans "3. Your feed token is currently empty and must first be generated to fetch content. Click <a href='?feed&amp;action=generate'>here to generate it</a>." %}</p>
{% else %}
<p>3. {% trans "Finally, you have to fetch content for imported items." %} <a href="cron.php?limit=10&amp;user-id={{ user_id }}&amp;token={{token}}" target="_blank">{% trans "Click here" %}</a> {% trans "to fetch content for 10 articles" %}.</p>
<p>{% trans "If you have console access to your server, you can also create a cron task:" %}</p>
<pre><code>0 */4 * * * cd /path/to/wallabag && php cron.php --limit=10 --user-id={{user_id}} --token={{token}} >/dev/null 2>&1</code></pre>
{% endif %}
<h2>{% trans "Export your wallabag data" %}</h2> <h2>{% trans "Export your wallabag data" %}</h2>
{% if constant('STORAGE') == 'sqlite' %} {% if constant('STORAGE') == 'sqlite' %}

View File

@ -16,6 +16,11 @@
{% include '_sorting.twig' %} {% include '_sorting.twig' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if includeImport %}
{% include '_import.twig' %}
{% endif %}
{% if tag %} {% if tag %}
<h3>{% trans "Tag" %}: <b>{{ tag.value }}</b></h3> <h3>{% trans "Tag" %}: <b>{{ tag.value }}</b></h3>
{% endif %} {% endif %}