aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGravatar Marien Fressinaud <dev@marienfressinaud.fr> 2014-03-29 20:18:57 +0100
committerGravatar Marien Fressinaud <dev@marienfressinaud.fr> 2014-03-29 20:18:57 +0100
commit9ea3819402746d8425d4a608f2d5f3c0f5bc29fb (patch)
treea4836c792d14e5489ebabe6e5d9f46e9b098ce93 /app
parent7676a197a4767f735dabae6ad9cf40ef65e91aa7 (diff)
Better OPML import / export
- use a new OPML library (https://github.com/marienfressinaud/lib_opml) - import has been completely rewritten (far better!) - introduce addFeedObject and addCategoryObject (in DAO for the moment). Permit to add easily feeds and categories (check if they already exist in DB) - introduce html_chars_utf8 (wrap htmlspecialchars for UTF-8)
Diffstat (limited to 'app')
-rw-r--r--app/Controllers/importExportController.php124
-rw-r--r--app/Exceptions/OpmlException.php6
-rw-r--r--app/Models/CategoryDAO.php12
-rw-r--r--app/Models/FeedDAO.php29
-rw-r--r--app/views/helpers/export/opml.phtml43
5 files changed, 147 insertions, 67 deletions
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index cbadeb6ca..b6b4d0fed 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -129,71 +129,101 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
private function import_opml($opml_file) {
- $categories = array();
- $feeds = array();
+ $opml_array = array();
try {
- list($categories, $feeds) = opml_import($opml_file);
- } catch (FreshRSS_Opml_Exception $e) {
+ $opml_array = libopml_parse_string($opml_file);
+ } catch (LibOPML_Exception $e) {
Minz_Log::warning($e->getMessage());
return true;
}
$this->catDAO->checkDefault();
- // on ajoute les catégories en masse dans une fonction à part
- $this->addCategories($categories);
-
- // on calcule la date des articles les plus anciens qu'on accepte
- $nb_month_old = $this->view->conf->old_entries;
- $date_min = time() - (3600 * 24 * 30 * $nb_month_old);
+ return $this->addOpmlElements($opml_array['body']);
+ }
- // la variable $error permet de savoir si une erreur est survenue
- // Le but est de ne pas arrêter l'import même en cas d'erreur
- // L'utilisateur sera mis au courant s'il y a eu des erreurs, mais
- // ne connaîtra pas les détails. Ceux-ci seront toutefois logguées
+ private function addOpmlElements($opml_elements, $parent_cat = null) {
$error = false;
- foreach ($feeds as $feed) {
- try {
- $values = array(
- 'id' => $feed->id(),
- 'url' => $feed->url(),
- 'category' => $feed->category(),
- 'name' => $feed->name(),
- 'website' => $feed->website(),
- 'description' => $feed->description(),
- 'lastUpdate' => 0,
- 'httpAuth' => $feed->httpAuth()
- );
+ foreach ($opml_elements as $elt) {
+ $res = false;
+ if (isset($elt['xmlUrl'])) {
+ $res = $this->addFeedOpml($elt, $parent_cat);
+ } else {
+ $res = $this->addCategoryOpml($elt, $parent_cat);
+ }
- // ajout du flux que s'il n'est pas déjà en BDD
- if (!$this->feedDAO->searchByUrl($values['url'])) {
- $id = $this->feedDAO->addFeed($values);
- if ($id) {
- $feed->_id($id);
- $feed->faviconPrepare();
- } else {
- $error = true;
- }
- }
- } catch (FreshRSS_Feed_Exception $e) {
- $error = true;
- Minz_Log::record($e->getMessage(), Minz_Log::WARNING);
+ if (!$error && $res) {
+ // oops: there is at least one error!
+ $error = $res;
}
}
return $error;
}
- private function addCategories($categories) {
- foreach ($categories as $cat) {
- if (!$this->catDAO->searchByName($cat->name())) {
- $values = array(
- 'id' => $cat->id(),
- 'name' => $cat->name(),
- );
- $this->catDAO->addCategory($values);
+ private function addFeedOpml($feed_elt, $parent_cat) {
+ if (is_null($parent_cat)) {
+ // This feed has no parent category so we get the default one
+ $parent_cat = $catDAO->getDefault()->name();
+ }
+
+ $cat = $this->catDAO->searchByName($parent_cat);
+
+ if (!$cat) {
+ return true;
+ }
+
+ // We get different useful information
+ $url = html_chars_utf8($feed_elt['xmlUrl']);
+ $name = html_chars_utf8($feed_elt['text']);
+ $website = '';
+ if (isset($feed_elt['htmlUrl'])) {
+ $website = html_chars_utf8($feed_elt['htmlUrl']);
+ }
+ $description = '';
+ if (isset($feed_elt['description'])) {
+ $description = html_chars_utf8($feed_elt['description']);
+ }
+
+ $error = false;
+ try {
+ // Create a Feed object and add it in DB
+ $feed = new FreshRSS_Feed($url);
+ $feed->_category($cat->id());
+ $feed->_name($name);
+ $feed->_website($website);
+ $feed->_description($description);
+
+ // addFeedObject checks if feed is already in DB so nothing else to
+ // check here
+ $id = $this->feedDAO->addFeedObject($feed);
+ $error = ($id === false);
+ } catch (FreshRSS_Feed_Exception $e) {
+ Minz_Log::record($e->getMessage(), Minz_Log::WARNING);
+ $error = true;
+ }
+
+ return $error;
+ }
+
+ private function addCategoryOpml($cat_elt, $parent_cat) {
+ // Create a new Category object
+ $cat = new FreshRSS_Category(html_chars_utf8($cat_elt['text']));
+
+ $id = $this->catDAO->addCategoryObject($cat);
+ $error = ($id === false);
+
+ if (isset($cat_elt['@outlines'])) {
+ // Our cat_elt contains more categories or more feeds, so we
+ // add them recursively.
+ // Note: FreshRSS does not support yet category arborescence
+ $res = $this->addOpmlElements($cat_elt['@outlines'], $cat->name());
+ if (!$error && $res) {
+ $error = true;
}
}
+
+ return $error;
}
private function import_articles($article_file, $starred = false) {
diff --git a/app/Exceptions/OpmlException.php b/app/Exceptions/OpmlException.php
deleted file mode 100644
index e0ea3e493..000000000
--- a/app/Exceptions/OpmlException.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-class FreshRSS_Opml_Exception extends FreshRSS_Feed_Exception {
- public function __construct ($name_file) {
- parent::__construct ('OPML file is invalid');
- }
-}
diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php
index f3c02e3e4..8be732b98 100644
--- a/app/Models/CategoryDAO.php
+++ b/app/Models/CategoryDAO.php
@@ -18,6 +18,18 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo {
}
}
+ public function addCategoryObject($category) {
+ if (!$this->searchByName($category->name())) {
+ // Category does not exist yet in DB so we add it before continue
+ $values = array(
+ 'name' => $category->name(),
+ );
+ return $this->addCategory($values);
+ }
+
+ return false;
+ }
+
public function updateCategory ($id, $valuesTmp) {
$sql = 'UPDATE `' . $this->prefix . 'category` SET name=? WHERE id=?';
$stm = $this->bd->prepare ($sql);
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index ca25c3aeb..eac21df7e 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -24,6 +24,35 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
}
+ public function addFeedObject($feed) {
+ // TODO: not sure if we should write this method in DAO since DAO
+ // should not be aware about feed class
+
+ // Add feed only if we don't find it in DB
+ if (!$this->searchByUrl($feed->url())) {
+ $values = array(
+ 'id' => $feed->id(),
+ 'url' => $feed->url(),
+ 'category' => $feed->category(),
+ 'name' => $feed->name(),
+ 'website' => $feed->website(),
+ 'description' => $feed->description(),
+ 'lastUpdate' => 0,
+ 'httpAuth' => $feed->httpAuth()
+ );
+
+ $id = $this->addFeed($values);
+ if ($id) {
+ $feed->_id($id);
+ $feed->faviconPrepare();
+ }
+
+ return $id;
+ }
+
+ return false;
+ }
+
public function updateFeed ($id, $valuesTmp) {
$set = '';
foreach ($valuesTmp as $key => $v) {
diff --git a/app/views/helpers/export/opml.phtml b/app/views/helpers/export/opml.phtml
index 2e66e5054..adbac904d 100644
--- a/app/views/helpers/export/opml.phtml
+++ b/app/views/helpers/export/opml.phtml
@@ -1,15 +1,30 @@
<?php
-require_once(LIB_PATH . '/lib_opml.php');
-
-echo '<?xml version="1.0" encoding="UTF-8" ?>';
-?>
-<!-- Generated by <?php echo Minz_Configuration::title (); ?> -->
-<opml version="2.0">
- <head>
- <title><?php echo Minz_Configuration::title (); ?> OPML Feed</title>
- <dateCreated><?php echo date('D, d M Y H:i:s'); ?></dateCreated>
- </head>
- <body>
-<?php echo opml_export ($this->categories); ?>
- </body>
-</opml>
+
+$opml_array = array(
+ 'head' => array(
+ 'title' => Minz_Configuration::title(),
+ 'dateCreated' => date('D, d M Y H:i:s')
+ ),
+ 'body' => array()
+);
+
+foreach ($this->categories as $key => $cat) {
+ $opml_array['body'][$key] = array(
+ 'text' => $cat['name'],
+ '@outlines' => array()
+ );
+
+ foreach ($cat['feeds'] as $feed) {
+ $opml_array['body'][$key]['@outlines'][] = array(
+ 'text' => $feed->name(),
+ 'type' => 'rss',
+ 'xmlUrl' => $feed->url(),
+ 'htmlUrl' => $feed->website(),
+ 'description' => htmlspecialchars(
+ $feed->description(), ENT_COMPAT, 'UTF-8'
+ )
+ );
+ }
+}
+
+echo libopml_render($opml_array);