From c1d74b8332d8eb68677380fcbdbf1885c734c9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Guillot?= Date: Wed, 24 Dec 2014 17:54:27 -0500 Subject: [PATCH] Add favicon support --- assets/css/app.css | 4 ++ controllers/bookmark.php | 4 +- controllers/config.php | 2 +- controllers/history.php | 16 ++--- controllers/item.php | 2 + lib/helpers.php | 9 +++ locales/cs_CZ/translations.php | 1 + locales/de_DE/translations.php | 1 + locales/es_ES/translations.php | 1 + locales/fr_FR/translations.php | 1 + locales/it_IT/translations.php | 1 + locales/pt_BR/translations.php | 1 + locales/zh_CN/translations.php | 1 + models/config.php | 31 ++-------- models/feed.php | 61 ++++++++++++++++++- models/schema.php | 16 ++++- templates/bookmarks.php | 9 ++- templates/config.php | 3 +- templates/feed_items.php | 1 + templates/history.php | 9 ++- templates/item.php | 3 +- templates/show_item.php | 7 --- templates/unread_items.php | 1 + vendor/autoload.php | 2 +- vendor/composer/autoload_real.php | 10 +-- vendor/composer/installed.json | 8 +-- .../picofeed/lib/PicoFeed/Reader/Favicon.php | 24 +++++++- .../picofeed/tests/Reader/FaviconTest.php | 8 +++ 28 files changed, 176 insertions(+), 61 deletions(-) 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 @@
- $item, 'menu' => $menu, 'offset' => $offset, 'hide' => false, 'display_mode' => $display_mode)) ?> + $item, + 'menu' => $menu, + 'offset' => $offset, + 'hide' => false, + 'display_mode' => $display_mode, + 'favicons' => $favicons, + )) ?> $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 @@

-
@@ -62,6 +61,8 @@
+
+
diff --git a/templates/feed_items.php b/templates/feed_items.php index 5858c37..447f1eb 100644 --- a/templates/feed_items.php +++ b/templates/feed_items.php @@ -28,6 +28,7 @@ 'offset' => $offset, 'hide' => false, 'display_mode' => $display_mode, + 'favicons' => $favicons, )) ?> diff --git a/templates/history.php b/templates/history.php index 7ee61d8..51713b7 100644 --- a/templates/history.php +++ b/templates/history.php @@ -15,7 +15,14 @@
- $item, 'menu' => $menu, 'offset' => $offset, 'hide' => true, 'display_mode' => $display_mode)) ?> + $item, + 'menu' => $menu, + 'offset' => $offset, + 'hide' => true, + 'display_mode' => $display_mode, + 'favicons' => $favicons, + )) ?> $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction)) ?> diff --git a/templates/item.php b/templates/item.php index d1dcb84..64a7c50 100644 --- a/templates/item.php +++ b/templates/item.php @@ -10,12 +10,13 @@

> +

- +
>
diff --git a/templates/show_item.php b/templates/show_item.php index dc3a102..d61c66b 100644 --- a/templates/show_item.php +++ b/templates/show_item.php @@ -44,13 +44,6 @@ data-action="bookmark" > -
  • - -
  • diff --git a/templates/unread_items.php b/templates/unread_items.php index c631dc6..b9c21d8 100644 --- a/templates/unread_items.php +++ b/templates/unread_items.php @@ -22,6 +22,7 @@ 'offset' => $offset, 'hide' => true, 'display_mode' => $display_mode, + 'favicons' => $favicons, )) ?> diff --git a/vendor/autoload.php b/vendor/autoload.php index 28da304..f57883d 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985::getLoader(); +return ComposerAutoloaderInita5bf9ee28a13532106d0068a171b06ab::getLoader(); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 757f362..381a2df 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985 +class ComposerAutoloaderInita5bf9ee28a13532106d0068a171b06ab { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInita5bf9ee28a13532106d0068a171b06ab', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInita5bf9ee28a13532106d0068a171b06ab', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ class ComposerAutoloaderInit2e47cecea56754de3b457018a8eee985 $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire2e47cecea56754de3b457018a8eee985($file); + composerRequirea5bf9ee28a13532106d0068a171b06ab($file); } return $loader; } } -function composerRequire2e47cecea56754de3b457018a8eee985($file) +function composerRequirea5bf9ee28a13532106d0068a171b06ab($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 5e89b01..4643708 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -162,18 +162,18 @@ "source": { "type": "git", "url": "https://github.com/fguillot/picoFeed.git", - "reference": "b3f2202845be5895ce818f1393cdd28b0aa1b8cb" + "reference": "e785e62ee79a02478e9691cc0cc50e689f2bf4a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fguillot/picoFeed/zipball/b3f2202845be5895ce818f1393cdd28b0aa1b8cb", - "reference": "b3f2202845be5895ce818f1393cdd28b0aa1b8cb", + "url": "https://api.github.com/repos/fguillot/picoFeed/zipball/e785e62ee79a02478e9691cc0cc50e689f2bf4a4", + "reference": "e785e62ee79a02478e9691cc0cc50e689f2bf4a4", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2014-12-24 20:46:58", + "time": "2014-12-24 22:35:22", "type": "library", "installation-source": "dist", "autoload": { diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Reader/Favicon.php b/vendor/fguillot/picofeed/lib/PicoFeed/Reader/Favicon.php index 1d97151..5d183e2 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Reader/Favicon.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Reader/Favicon.php @@ -20,6 +20,20 @@ use PicoFeed\Parser\XmlParser; */ class Favicon { + /** + * Valid types for favicon (supported by browsers) + * + * @access private + * @var array + */ + private $types = array( + 'image/png', + 'image/gif', + 'image/x-icon', + 'image/jpeg', + 'image/jpg', + ); + /** * Config class instance * @@ -74,7 +88,13 @@ class Favicon */ public function getType() { - return $this->content_type; + foreach ($this->types as $type) { + if (strpos($this->content_type, $type) === 0) { + return $type; + } + } + + return 'image/x-icon'; } /** @@ -87,7 +107,7 @@ class Favicon { return sprintf( 'data:%s;base64,%s', - $this->content_type, + $this->getType(), base64_encode($this->content) ); } diff --git a/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php b/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php index eaf7012..af1c193 100644 --- a/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php +++ b/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php @@ -155,4 +155,12 @@ class FaviconTest extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $favicon->getDataUri()); } + + public function testDataUriWithBadContentType() + { + $favicon = new Favicon; + $this->assertNotEmpty($favicon->find('http://www.lemonde.fr/')); + $expected = 'data:image/x-icon;base64,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'; + $this->assertEquals($expected, $favicon->getDataUri()); + } }