diff --git a/assets/css/app.css b/assets/css/app.css
index 21886f9..469f59e 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -662,6 +662,10 @@ a.icon:hover {
padding-bottom: 10px;
}
+.items article .favicon {
+ height: 16px;
+}
+
/* other pages */
section li {
margin-left: 15px;
diff --git a/controllers/bookmark.php b/controllers/bookmark.php
index 6e798c1..49ae51b 100644
--- a/controllers/bookmark.php
+++ b/controllers/bookmark.php
@@ -42,12 +42,14 @@ Router\get_action('bookmarks', function() {
$offset = Request\int_param('offset', 0);
$nb_items = Model\Item\count_bookmarks();
+ $items = Model\Item\get_bookmarks($offset, Model\Config\get('items_per_page'));
Response\html(Template\layout('bookmarks', array(
+ 'favicons' => Model\Feed\get_item_favicons($items),
'order' => '',
'direction' => '',
'display_mode' => Model\Config\get('items_display_mode'),
- 'items' => Model\Item\get_bookmarks($offset, Model\Config\get('items_per_page')),
+ 'items' => $items,
'nb_items' => $nb_items,
'offset' => $offset,
'items_per_page' => Model\Config\get('items_per_page'),
diff --git a/controllers/config.php b/controllers/config.php
index 6dfd2aa..2d1a680 100644
--- a/controllers/config.php
+++ b/controllers/config.php
@@ -134,7 +134,7 @@ Router\get_action('config', function() {
// Update preferences
Router\post_action('config', function() {
- $values = Request\values() + array('nocontent' => 0, 'image_proxy' => 0);
+ $values = Request\values() + array('nocontent' => 0, 'image_proxy' => 0, 'favicons' => 0);
Model\Config\check_csrf_values($values);
list($valid, $errors) = Model\Config\validate_modification($values);
diff --git a/controllers/history.php b/controllers/history.php
index d0d0c8d..b4fbd0f 100644
--- a/controllers/history.php
+++ b/controllers/history.php
@@ -11,15 +11,17 @@ Router\get_action('history', function() {
$offset = Request\int_param('offset', 0);
$nb_items = Model\Item\count_by_status('read');
+ $items = Model\Item\get_all(
+ 'read',
+ $offset,
+ Model\Config\get('items_per_page'),
+ 'updated',
+ Model\Config\get('items_sorting_direction')
+ );
Response\html(Template\layout('history', array(
- 'items' => Model\Item\get_all(
- 'read',
- $offset,
- Model\Config\get('items_per_page'),
- 'updated',
- Model\Config\get('items_sorting_direction')
- ),
+ 'favicons' => Model\Feed\get_item_favicons($items),
+ 'items' => $items,
'order' => '',
'direction' => '',
'display_mode' => Model\Config\get('items_display_mode'),
diff --git a/controllers/item.php b/controllers/item.php
index cd10ce1..48f4842 100644
--- a/controllers/item.php
+++ b/controllers/item.php
@@ -25,6 +25,7 @@ Router\get_action('unread', function() {
}
Response\html(Template\layout('unread_items', array(
+ 'favicons' => Model\Feed\get_item_favicons($items),
'order' => $order,
'direction' => $direction,
'display_mode' => Model\Config\get('items_display_mode'),
@@ -88,6 +89,7 @@ Router\get_action('feed-items', function() {
$items = Model\Item\get_all_by_feed($feed_id, $offset, Model\Config\get('items_per_page'), $order, $direction);
Response\html(Template\layout('feed_items', array(
+ 'favicons' => Model\Feed\get_favicons(array($feed['id'])),
'order' => $order,
'direction' => $direction,
'display_mode' => Model\Config\get('items_display_mode'),
diff --git a/lib/helpers.php b/lib/helpers.php
index 79b0649..dc812e3 100644
--- a/lib/helpers.php
+++ b/lib/helpers.php
@@ -2,6 +2,15 @@
namespace Helper;
+function favicon(array $favicons, $feed_id)
+{
+ if (isset($favicons[$feed_id])) {
+ return '';
+ }
+
+ return '';
+}
+
function isRTL(array $item)
{
return ! empty($item['rtl']) || \PicoFeed\Parser\Parser::isLanguageRTL($item['language']);
diff --git a/locales/cs_CZ/translations.php b/locales/cs_CZ/translations.php
index 9ee3ac4..db30021 100644
--- a/locales/cs_CZ/translations.php
+++ b/locales/cs_CZ/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/locales/de_DE/translations.php b/locales/de_DE/translations.php
index 6fa5cf9..f2fd933 100644
--- a/locales/de_DE/translations.php
+++ b/locales/de_DE/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/locales/es_ES/translations.php b/locales/es_ES/translations.php
index 1bd6705..bf283bc 100644
--- a/locales/es_ES/translations.php
+++ b/locales/es_ES/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/locales/fr_FR/translations.php b/locales/fr_FR/translations.php
index b8ff433..03e8d90 100644
--- a/locales/fr_FR/translations.php
+++ b/locales/fr_FR/translations.php
@@ -232,4 +232,5 @@ return array(
'Application' => 'Application',
'Enable image proxy' => 'Activer le proxy pour les images',
'Avoid mixed content warnings with HTTPS' => 'Évite les alertes du navigateur web en HTTPS',
+ 'Download favicons' => 'Télécharger les icônes des sites web',
);
diff --git a/locales/it_IT/translations.php b/locales/it_IT/translations.php
index f6585a4..29303b0 100644
--- a/locales/it_IT/translations.php
+++ b/locales/it_IT/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/locales/pt_BR/translations.php b/locales/pt_BR/translations.php
index 20a2086..1311ef4 100644
--- a/locales/pt_BR/translations.php
+++ b/locales/pt_BR/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/locales/zh_CN/translations.php b/locales/zh_CN/translations.php
index 684a07b..d6923e4 100644
--- a/locales/zh_CN/translations.php
+++ b/locales/zh_CN/translations.php
@@ -232,4 +232,5 @@ return array(
// 'Application' => '',
// 'Enable image proxy' => '',
// 'Avoid mixed content warnings with HTTPS' => '',
+ // 'Download favicons' => '',
);
diff --git a/models/config.php b/models/config.php
index 6719539..42f3cb5 100644
--- a/models/config.php
+++ b/models/config.php
@@ -285,34 +285,13 @@ function get($name)
// Get all config parameters
function get_all()
{
- return Database::get('db')
+ $config = Database::get('db')
->table('config')
- ->columns(
- 'username',
- 'language',
- 'timezone',
- 'autoflush',
- 'autoflush_unread',
- 'nocontent',
- 'items_per_page',
- 'theme',
- 'api_token',
- 'feed_token',
- 'fever_token',
- 'bookmarklet_token',
- 'items_sorting_direction',
- 'items_display_mode',
- 'redirect_nothing_to_read',
- 'auto_update_url',
- 'pinboard_enabled',
- 'pinboard_token',
- 'pinboard_tags',
- 'instapaper_enabled',
- 'instapaper_username',
- 'instapaper_password',
- 'image_proxy'
- )
->findOne();
+
+ unset($config['password']);
+
+ return $config;
}
// Validation for edit action
diff --git a/models/feed.php b/models/feed.php
index 2b31f70..d1e98c6 100644
--- a/models/feed.php
+++ b/models/feed.php
@@ -2,18 +2,72 @@
namespace Model\Feed;
+use Model\Config;
+use Model\Item;
use SimpleValidator\Validator;
use SimpleValidator\Validators;
use PicoDb\Database;
-use Model\Config;
-use Model\Item;
use PicoFeed\Serialization\Export;
use PicoFeed\Serialization\Import;
use PicoFeed\Reader\Reader;
+use PicoFeed\Reader\Favicon;
use PicoFeed\PicoFeedException;
const LIMIT_ALL = -1;
+// Download and store the favicon
+function fetch_favicon($feed_id, $site_url)
+{
+ $favicon = new Favicon;
+
+ return Database::get('db')
+ ->table('favicons')
+ ->save(array(
+ 'feed_id' => $feed_id,
+ 'link' => $favicon->find($site_url),
+ 'icon' => $favicon->getDataUri(),
+ ));
+}
+
+// Refresh favicon
+function refresh_favicon($feed_id, $site_url)
+{
+ if (Config\get('favicons') == 1 && ! has_favicon($feed_id)) {
+ fetch_favicon($feed_id, $site_url);
+ }
+}
+
+// Return true if the feed have a favicon
+function has_favicon($feed_id)
+{
+ return Database::get('db')->table('favicons')->eq('feed_id', $feed_id)->count() === 1;
+}
+
+// Get favicons for those feeds
+function get_favicons(array $feed_ids)
+{
+ if (Config\get('favicons') == 0) {
+ return array();
+ }
+
+ return Database::get('db')
+ ->table('favicons')
+ ->in('feed_id', $feed_ids)
+ ->listing('feed_id', 'icon');
+}
+
+// Get all favicons for a list of items
+function get_item_favicons(array $items)
+{
+ $feed_ids = array();
+
+ foreach ($items as $item) {
+ $feeds_ids[] = $item['feed_id'];
+ }
+
+ return get_favicons($feed_ids);
+}
+
// Update feed information
function update(array $values)
{
@@ -117,6 +171,8 @@ function create($url, $enable_grabber = false, $force_rtl = false)
$feed_id = $db->getConnection()->getLastId();
Item\update_all($feed_id, $feed->getItems());
+ refresh_favicon($feed_id, $feed->getSiteUrl());
+
Config\write_debug();
return (int) $feed_id;
@@ -187,6 +243,7 @@ function refresh($feed_id)
update_cache($feed_id, $resource->getLastModified(), $resource->getEtag());
Item\update_all($feed_id, $feed->getItems());
+ refresh_favicon($feed_id, $feed->getSiteUrl());
}
update_parsing_error($feed_id, 0);
diff --git a/models/schema.php b/models/schema.php
index efbdd3a..7bc56ec 100644
--- a/models/schema.php
+++ b/models/schema.php
@@ -5,7 +5,21 @@ namespace Schema;
use PDO;
use Model\Config;
-const VERSION = 33;
+const VERSION = 34;
+
+function version_34($pdo)
+{
+ $pdo->exec('ALTER TABLE config ADD COLUMN favicons INTEGER DEFAULT 0');
+
+ $pdo->exec(
+ 'CREATE TABLE favicons (
+ feed_id INTEGER UNIQUE,
+ link TEXT,
+ icon TEXT,
+ FOREIGN KEY(feed_id) REFERENCES feeds(id) ON DELETE CASCADE
+ )'
+ );
+}
function version_33($pdo)
{
diff --git a/templates/bookmarks.php b/templates/bookmarks.php
index 3d43849..a9a862a 100644
--- a/templates/bookmarks.php
+++ b/templates/bookmarks.php
@@ -12,7 +12,14 @@
- = \PicoFarad\Template\load('item', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'hide' => false, 'display_mode' => $display_mode)) ?>
+ = \PicoFarad\Template\load('item', array(
+ 'item' => $item,
+ 'menu' => $menu,
+ 'offset' => $offset,
+ 'hide' => false,
+ 'display_mode' => $display_mode,
+ 'favicons' => $favicons,
+ )) ?>
= \PicoFarad\Template\load('paging', array('menu' => $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction)) ?>
diff --git a/templates/config.php b/templates/config.php
index c298576..1b2326c 100644
--- a/templates/config.php
+++ b/templates/config.php
@@ -12,7 +12,6 @@