Split models and controllers in different files
This commit is contained in:
parent
259ee098b3
commit
4fb68b9b80
@ -1,14 +1,16 @@
|
||||
<?php
|
||||
|
||||
require 'check_setup.php';
|
||||
require 'vendor/password.php';
|
||||
require 'vendor/PicoTools/Dependency_Injection.php';
|
||||
require 'vendor/PicoTools/Translator.php';
|
||||
require 'vendor/PicoDb/Database.php';
|
||||
require 'vendor/PicoDb/Table.php';
|
||||
require 'vendor/PicoFeed/Client.php';
|
||||
require 'models/config.php';
|
||||
require 'models/user.php';
|
||||
require 'models/feed.php';
|
||||
require 'models/item.php';
|
||||
require 'schema.php';
|
||||
require 'model.php';
|
||||
|
||||
if (file_exists('config.php')) require 'config.php';
|
||||
|
||||
@ -33,7 +35,7 @@ PicoTools\container('db', function() {
|
||||
'filename' => DB_FILENAME
|
||||
));
|
||||
|
||||
if ($db->schema()->check(Model\DB_VERSION)) {
|
||||
if ($db->schema()->check(Model\Config\DB_VERSION)) {
|
||||
return $db;
|
||||
}
|
||||
else {
|
||||
|
54
controllers/bookmark.php
Normal file
54
controllers/bookmark.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Ajax call to add or remove a bookmark
|
||||
Router\post_action('bookmark', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$value = Request\int_param('value');
|
||||
|
||||
Model\Item\set_bookmark_value($id, $value);
|
||||
|
||||
Response\json(array('id' => $id, 'value' => $value));
|
||||
});
|
||||
|
||||
// Add new bookmark
|
||||
Router\get_action('bookmark', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$menu = Request\param('menu', 'unread');
|
||||
$source = Request\param('source', 'unread');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\Item\set_bookmark_value($id, Request\int_param('value'));
|
||||
|
||||
if ($source === 'show') {
|
||||
Response\Redirect('?action=show&menu='.$menu.'&id='.$id);
|
||||
}
|
||||
|
||||
Response\Redirect('?action='.$menu.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
// Display bookmarks page
|
||||
Router\get_action('bookmarks', function() {
|
||||
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\Item\count_bookmarks();
|
||||
|
||||
Response\html(Template\layout('bookmarks', array(
|
||||
'order' => '',
|
||||
'direction' => '',
|
||||
'items' => Model\Item\get_bookmarks($offset, Model\Config\get('items_per_page')),
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\Config\get('items_per_page'),
|
||||
'menu' => 'bookmarks',
|
||||
'title' => t('Bookmarks').' ('.$nb_items.')'
|
||||
)));
|
||||
});
|
68
controllers/common.php
Normal file
68
controllers/common.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
require 'common.php';
|
||||
require 'vendor/PicoTools/Template.php';
|
||||
require 'vendor/PicoTools/Helper.php';
|
||||
require 'vendor/PicoFarad/Response.php';
|
||||
require 'vendor/PicoFarad/Request.php';
|
||||
require 'vendor/PicoFarad/Session.php';
|
||||
require 'vendor/PicoFarad/Router.php';
|
||||
require 'helpers.php';
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
|
||||
if (SESSION_SAVE_PATH !== '') session_save_path(SESSION_SAVE_PATH);
|
||||
Session\open(dirname($_SERVER['PHP_SELF']));
|
||||
|
||||
|
||||
// Called before each action
|
||||
Router\before(function($action) {
|
||||
|
||||
$ignore_actions = array('js', 'login', 'google-auth', 'google-redirect-auth', 'mozilla-auth');
|
||||
|
||||
if (! isset($_SESSION['user']) && ! in_array($action, $ignore_actions)) {
|
||||
Response\redirect('?action=login');
|
||||
}
|
||||
|
||||
// Load translations
|
||||
$language = Model\Config\get('language') ?: 'en_US';
|
||||
if ($language !== 'en_US') PicoTools\Translator\load($language);
|
||||
|
||||
// HTTP secure headers
|
||||
$frame_src = \PicoFeed\Filter::$iframe_whitelist;
|
||||
$frame_src[] = 'https://login.persona.org';
|
||||
|
||||
Response\csp(array(
|
||||
'media-src' => '*',
|
||||
'img-src' => '*',
|
||||
'frame-src' => $frame_src
|
||||
));
|
||||
|
||||
Response\xframe();
|
||||
Response\xss();
|
||||
Response\nosniff();
|
||||
});
|
||||
|
||||
// Javascript assets
|
||||
Router\get_action('js', function() {
|
||||
|
||||
$data = file_get_contents('assets/js/app.js');
|
||||
$data .= file_get_contents('assets/js/feed.js');
|
||||
$data .= file_get_contents('assets/js/item.js');
|
||||
$data .= file_get_contents('assets/js/event.js');
|
||||
$data .= file_get_contents('assets/js/nav.js');
|
||||
$data .= 'Miniflux.App.Run();';
|
||||
|
||||
Response\js($data);
|
||||
});
|
||||
|
||||
// Show help
|
||||
Router\get_action('show-help', function() {
|
||||
|
||||
Response\html(Template\load('show_help'));
|
||||
});
|
24
controllers/console.php
Normal file
24
controllers/console.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Flush console messages
|
||||
Router\get_action('flush-console', function() {
|
||||
|
||||
@unlink(DEBUG_FILENAME);
|
||||
Response\redirect('?action=console');
|
||||
});
|
||||
|
||||
|
||||
// Display console
|
||||
Router\get_action('console', function() {
|
||||
|
||||
Response\html(Template\layout('console', array(
|
||||
'content' => @file_get_contents(DEBUG_FILENAME),
|
||||
'title' => t('Console')
|
||||
)));
|
||||
});
|
276
controllers/feed.php
Normal file
276
controllers/feed.php
Normal file
@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Refresh all feeds, used when Javascript is disabled
|
||||
Router\get_action('refresh-all', function() {
|
||||
|
||||
Model\Feed\refresh_all();
|
||||
Session\flash(t('Your subscriptions are updated'));
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
// Edit feed form
|
||||
Router\get_action('edit-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('edit_feed', array(
|
||||
'values' => Model\Feed\get($id),
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Edit subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
// Submit edit feed form
|
||||
Router\post_action('edit-feed', function() {
|
||||
|
||||
$values = Request\values();
|
||||
list($valid, $errors) = Model\Feed\validate_modification($values);
|
||||
|
||||
if ($valid) {
|
||||
|
||||
if (Model\Feed\update($values)) {
|
||||
Session\flash(t('Your subscription has been updated.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to edit your subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
}
|
||||
|
||||
Response\html(Template\layout('edit_feed', array(
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Edit subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
// Disable content grabber for a feed
|
||||
Router\get_action('disable-grabber-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\Feed\disable_grabber($id)) {
|
||||
Session\flash(t('The content grabber is disabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to disable the content grabber for this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
// Enable content grabber for a feed
|
||||
Router\get_action('enable-grabber-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\Feed\enable_grabber($id)) {
|
||||
Session\flash(t('The content grabber is enabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to activate the content grabber for this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
// Confirmation box to disable a feed
|
||||
Router\get_action('confirm-disable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('confirm_disable_feed', array(
|
||||
'feed' => Model\Feed\get($id),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
// Disable a feed
|
||||
Router\get_action('disable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\Feed\disable($id)) {
|
||||
Session\flash(t('This subscription has been disabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to disable this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
// Enable a feed
|
||||
Router\get_action('enable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\Feed\enable($id)) {
|
||||
Session\flash(t('This subscription has been enabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to enable this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
// Confirmation box to remove a feed
|
||||
Router\get_action('confirm-remove-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('confirm_remove_feed', array(
|
||||
'feed' => Model\Feed\get($id),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
// Remove a feed
|
||||
Router\get_action('remove-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\Feed\remove($id)) {
|
||||
Session\flash(t('This subscription has been removed successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to remove this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
// Refresh one feed and redirect to unread items
|
||||
Router\get_action('refresh-feed', function() {
|
||||
|
||||
Model\Feed\refresh(Request\int_param('feed_id'));
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
// Ajax call to refresh one feed
|
||||
Router\post_action('refresh-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id', 0);
|
||||
$result = Model\Feed\refresh($id);
|
||||
|
||||
Response\json(array('feed_id' => $id, 'result' => $result));
|
||||
});
|
||||
|
||||
// Display all feeds
|
||||
Router\get_action('feeds', function() {
|
||||
|
||||
if (! Request\int_param('disable_empty_feeds_check')) {
|
||||
|
||||
$empty_feeds = Model\Feed\get_all_empty();
|
||||
|
||||
if (! empty($empty_feeds)) {
|
||||
|
||||
$listing = array();
|
||||
|
||||
foreach ($empty_feeds as &$feed) {
|
||||
$listing[] = '"'.$feed['title'].'"';
|
||||
}
|
||||
|
||||
$message = t(
|
||||
'There is %d empty feeds, there is maybe an error: %s...',
|
||||
count($empty_feeds),
|
||||
implode(', ', array_slice($listing, 0, 5))
|
||||
);
|
||||
|
||||
Session\flash_error($message);
|
||||
}
|
||||
}
|
||||
|
||||
Response\html(Template\layout('feeds', array(
|
||||
'feeds' => Model\Feed\get_all(),
|
||||
'nothing_to_read' => Request\int_param('nothing_to_read'),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Subscriptions')
|
||||
)));
|
||||
});
|
||||
|
||||
// Display form to add one feed
|
||||
Router\get_action('add', function() {
|
||||
|
||||
Response\html(Template\layout('add', array(
|
||||
'values' => array(),
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('New subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
// Add a feed with the form or directly from the url, it can be used by a bookmarklet by example
|
||||
Router\action('subscribe', function() {
|
||||
|
||||
if (Request\param('url')) {
|
||||
$values = array();
|
||||
$url = Request\param('url');
|
||||
}
|
||||
else {
|
||||
$values = Request\values();
|
||||
$url = isset($values['url']) ? $values['url'] : '';
|
||||
}
|
||||
|
||||
$values += array('download_content' => 0);
|
||||
$url = trim($url);
|
||||
$result = Model\Feed\create($url, $values['download_content']);
|
||||
|
||||
if ($result) {
|
||||
Session\flash(t('Subscription added successfully.'));
|
||||
Response\redirect('?action=feeds');
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to find a subscription.'));
|
||||
}
|
||||
|
||||
Response\html(Template\layout('add', array(
|
||||
'values' => array('url' => $url),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Subscriptions')
|
||||
)));
|
||||
});
|
||||
|
||||
// OPML export
|
||||
Router\get_action('export', function() {
|
||||
|
||||
Response\force_download('feeds.opml');
|
||||
Response\xml(Model\Feed\export_opml());
|
||||
});
|
||||
|
||||
// OPML import form
|
||||
Router\get_action('import', function() {
|
||||
|
||||
Response\html(Template\layout('import', array(
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('OPML Import')
|
||||
)));
|
||||
});
|
||||
|
||||
// OPML importation
|
||||
Router\post_action('import', function() {
|
||||
|
||||
if (Model\Feed\import_opml(Request\file_content('file'))) {
|
||||
|
||||
Session\flash(t('Your feeds have been imported.'));
|
||||
Response\redirect('?action=feeds&disable_empty_feeds_check=1');
|
||||
}
|
||||
else {
|
||||
|
||||
Session\flash_error(t('Unable to import your OPML file.'));
|
||||
Response\redirect('?action=import');
|
||||
}
|
||||
});
|
47
controllers/history.php
Normal file
47
controllers/history.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Display history page
|
||||
Router\get_action('history', function() {
|
||||
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\Item\count_by_status('read');
|
||||
|
||||
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')
|
||||
),
|
||||
'order' => '',
|
||||
'direction' => '',
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\Config\get('items_per_page'),
|
||||
'menu' => 'history',
|
||||
'title' => t('History').' ('.$nb_items.')'
|
||||
)));
|
||||
});
|
||||
|
||||
// Confirmation box to flush history
|
||||
Router\get_action('confirm-flush-history', function() {
|
||||
|
||||
Response\html(Template\layout('confirm_flush_items', array(
|
||||
'menu' => 'history',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
// Flush history
|
||||
Router\get_action('flush-history', function() {
|
||||
|
||||
Model\Item\mark_all_as_removed();
|
||||
Response\redirect('?action=history');
|
||||
});
|
158
controllers/item.php
Normal file
158
controllers/item.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Show item
|
||||
Router\get_action('show', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$menu = Request\param('menu');
|
||||
$item = Model\Item\get($id);
|
||||
$feed = Model\Feed\get($item['feed_id']);
|
||||
|
||||
Model\Item\set_read($id);
|
||||
|
||||
switch ($menu) {
|
||||
case 'unread':
|
||||
$nav = Model\Item\get_nav($item);
|
||||
$nb_unread_items = Model\Item\count_by_status('unread');
|
||||
break;
|
||||
case 'history':
|
||||
$nav = Model\Item\get_nav($item, array('read'));
|
||||
break;
|
||||
case 'feed-items':
|
||||
$nav = Model\Item\get_nav($item, array('unread', 'read'), array(1, 0), $item['feed_id']);
|
||||
break;
|
||||
case 'bookmarks':
|
||||
$nav = Model\Item\get_nav($item, array('unread', 'read'), array(1));
|
||||
break;
|
||||
}
|
||||
|
||||
Response\html(Template\layout('show_item', array(
|
||||
'nb_unread_items' => isset($nb_unread_items) ? $nb_unread_items : null,
|
||||
'item' => $item,
|
||||
'feed' => $feed,
|
||||
'item_nav' => isset($nav) ? $nav : null,
|
||||
'menu' => $menu,
|
||||
'title' => $item['title']
|
||||
)));
|
||||
});
|
||||
|
||||
// Display feed items page
|
||||
Router\get_action('feed-items', function() {
|
||||
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\Item\count_by_feed($feed_id);
|
||||
$feed = Model\Feed\get($feed_id);
|
||||
$order = Request\param('order', 'updated');
|
||||
$direction = Request\param('direction', Model\Config\get('items_sorting_direction'));
|
||||
$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(
|
||||
'order' => $order,
|
||||
'direction' => $direction,
|
||||
'feed' => $feed,
|
||||
'items' => $items,
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\Config\get('items_per_page'),
|
||||
'menu' => 'feed-items',
|
||||
'title' => '('.$nb_items.') '.$feed['title']
|
||||
)));
|
||||
});
|
||||
|
||||
// Ajax call to download an item (fetch the full content from the original website)
|
||||
Router\post_action('download-item', function() {
|
||||
|
||||
Response\json(Model\Item\download_content_id(Request\param('id')));
|
||||
});
|
||||
|
||||
// Ajax call change item status
|
||||
Router\post_action('change-item-status', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
|
||||
Response\json(array(
|
||||
'item_id' => $id,
|
||||
'status' => Model\Item\switch_status($id)
|
||||
));
|
||||
});
|
||||
|
||||
// Ajax call to mark item read
|
||||
Router\post_action('mark-item-read', function() {
|
||||
|
||||
Model\Item\set_read(Request\param('id'));
|
||||
Response\json(array('Ok'));
|
||||
});
|
||||
|
||||
// Ajax call to mark item unread
|
||||
Router\post_action('mark-item-unread', function() {
|
||||
|
||||
Model\Item\set_unread(Request\param('id'));
|
||||
Response\json(array('Ok'));
|
||||
});
|
||||
|
||||
// Mark all unread items as read
|
||||
Router\get_action('mark-as-read', function() {
|
||||
|
||||
Model\Item\mark_all_as_read();
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
// Mark all unread items as read for a specific feed
|
||||
Router\get_action('mark-feed-as-read', function() {
|
||||
|
||||
Model\Item\mark_feed_as_read(Request\int_param('feed_id'));
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
// Mark sent items id as read (Ajax request)
|
||||
Router\post_action('mark-items-as-read', function(){
|
||||
|
||||
Model\Item\mark_items_as_read(Request\values());
|
||||
Response\json(array('OK'));
|
||||
});
|
||||
|
||||
// Mark item as read and redirect to the listing page
|
||||
Router\get_action('mark-item-read', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'unread');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\Item\set_read($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
// Mark item as unread and redirect to the listing page
|
||||
Router\get_action('mark-item-unread', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'history');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\Item\set_unread($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
// Mark item as removed and redirect to the listing page
|
||||
Router\get_action('mark-item-removed', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'history');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\Item\set_removed($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id);
|
||||
});
|
33
controllers/unread.php
Normal file
33
controllers/unread.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Display unread items
|
||||
Router\notfound(function() {
|
||||
|
||||
Model\Item\autoflush();
|
||||
|
||||
$order = Request\param('order', 'updated');
|
||||
$direction = Request\param('direction', Model\Config\get('items_sorting_direction'));
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$items = Model\Item\get_all('unread', $offset, Model\Config\get('items_per_page'), $order, $direction);
|
||||
$nb_items = Model\Item\count_by_status('unread');
|
||||
|
||||
if ($nb_items === 0) Response\redirect('?action=feeds¬hing_to_read=1');
|
||||
|
||||
Response\html(Template\layout('unread_items', array(
|
||||
'order' => $order,
|
||||
'direction' => $direction,
|
||||
'items' => $items,
|
||||
'nb_items' => $nb_items,
|
||||
'nb_unread_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\Config\get('items_per_page'),
|
||||
'title' => 'Miniflux ('.$nb_items.')',
|
||||
'menu' => 'unread'
|
||||
)));
|
||||
});
|
147
controllers/user.php
Normal file
147
controllers/user.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
// Logout and destroy session
|
||||
Router\get_action('logout', function() {
|
||||
|
||||
Session\close();
|
||||
Response\redirect('?action=login');
|
||||
});
|
||||
|
||||
// Display form login
|
||||
Router\get_action('login', function() {
|
||||
|
||||
if (isset($_SESSION['user'])) Response\redirect('?action=unread');
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\Config\get('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\Config\get('auth_mozilla_token') !== '',
|
||||
'errors' => array(),
|
||||
'values' => array()
|
||||
)));
|
||||
});
|
||||
|
||||
// Check credentials and redirect to unread items
|
||||
Router\post_action('login', function() {
|
||||
|
||||
$values = Request\values();
|
||||
list($valid, $errors) = Model\User\validate_login($values);
|
||||
|
||||
if ($valid) Response\redirect('?action=unread');
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\Config\get('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\Config\get('auth_mozilla_token') !== '',
|
||||
'errors' => $errors,
|
||||
'values' => $values
|
||||
)));
|
||||
});
|
||||
|
||||
// Link to a Google Account (redirect)
|
||||
Router\get_action('google-redirect-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
Response\Redirect(AuthProvider\google_get_url(Helper\get_current_base_url(), '?action=google-link'));
|
||||
});
|
||||
|
||||
// Link to a Google Account (association)
|
||||
Router\get_action('google-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\google_validate();
|
||||
|
||||
if ($valid) {
|
||||
Model\Config\save_auth_token('google', $token);
|
||||
Session\flash(t('Your Google Account is linked to Miniflux.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to link Miniflux to your Google Account.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=config');
|
||||
});
|
||||
|
||||
// Authenticate with a Google Account (redirect)
|
||||
Router\get_action('google-redirect-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
Response\Redirect(AuthProvider\google_get_url(Helper\get_current_base_url(), '?action=google-auth'));
|
||||
});
|
||||
|
||||
// Authenticate with a Google Account (callback url)
|
||||
Router\get_action('google-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\google_validate();
|
||||
|
||||
if ($valid && $token === Model\Config\get('auth_google_token')) {
|
||||
|
||||
$_SESSION['user'] = array(
|
||||
'username' => Model\Config\get('username'),
|
||||
'language' => Model\Config\get('language'),
|
||||
);
|
||||
|
||||
Response\redirect('?action=unread');
|
||||
}
|
||||
else {
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\Config\get('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\Config\get('auth_mozilla_token') !== '',
|
||||
'errors' => array('login' => t('Unable to authenticate with Google')),
|
||||
'values' => array()
|
||||
)));
|
||||
}
|
||||
});
|
||||
|
||||
// Authenticate with a Mozilla Persona (ajax check)
|
||||
Router\post_action('mozilla-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\mozilla_validate(Request\value('token'));
|
||||
|
||||
if ($valid && $token === Model\Config\get('auth_mozilla_token')) {
|
||||
|
||||
$_SESSION['user'] = array(
|
||||
'username' => Model\Config\get('username'),
|
||||
'language' => Model\Config\get('language'),
|
||||
);
|
||||
|
||||
Response\text('?action=unread');
|
||||
}
|
||||
else {
|
||||
Response\text("?action=login");
|
||||
}
|
||||
});
|
||||
|
||||
// Link Miniflux to a Mozilla Account (ajax check)
|
||||
Router\post_action('mozilla-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\mozilla_validate(Request\value('token'));
|
||||
|
||||
if ($valid) {
|
||||
Model\Config\save_auth_token('mozilla', $token);
|
||||
Session\flash(t('Your Mozilla Persona Account is linked to Miniflux.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to link Miniflux to your Mozilla Persona Account.'));
|
||||
}
|
||||
|
||||
Response\text("?action=config");
|
||||
});
|
||||
|
||||
// Remove account link
|
||||
Router\get_action('unlink-account-provider', function() {
|
||||
Model\Config\remove_auth_token(Request\param('type'));
|
||||
Response\redirect('?action=config');
|
||||
});
|
@ -15,15 +15,15 @@ else {
|
||||
$options = $_GET;
|
||||
}
|
||||
|
||||
$limit = ! empty($options['limit']) && ctype_digit($options['limit']) ? (int) $options['limit'] : Model\LIMIT_ALL;
|
||||
$limit = ! empty($options['limit']) && ctype_digit($options['limit']) ? (int) $options['limit'] : Model\Feed\LIMIT_ALL;
|
||||
$update_interval = ! empty($options['update-interval']) && ctype_digit($options['update-interval']) ? (int) $options['update-interval'] : null;
|
||||
$call_interval = ! empty($options['call-interval']) && ctype_digit($options['call-interval']) ? (int) $options['call-interval'] : null;
|
||||
|
||||
if ($update_interval !== null && $call_interval !== null && $limit === Model\LIMIT_ALL && $update_interval >= $call_interval) {
|
||||
if ($update_interval !== null && $call_interval !== null && $limit === Model\Feed\LIMIT_ALL && $update_interval >= $call_interval) {
|
||||
|
||||
$feeds_count = \PicoTools\singleton('db')->table('feeds')->count();
|
||||
$limit = ceil($feeds_count / ($update_interval / $call_interval));
|
||||
}
|
||||
|
||||
Model\update_feeds($limit);
|
||||
Model\write_debug();
|
||||
Model\Feed\refresh_all($limit);
|
||||
Model\Config\write_debug();
|
||||
|
@ -4,8 +4,8 @@ require '../vendor/JsonRPC/Client.php';
|
||||
|
||||
use JsonRPC\Client;
|
||||
|
||||
$client = new Client('http://webapps/miniflux/jsonrpc.php');
|
||||
$client->authentication('admin', 'd4i/Tanb55426mi');
|
||||
$client = new Client('http://127.0.0.1:8000/jsonrpc.php');
|
||||
$client->authentication('admin', 'EF8goVO/8YUxcyt');
|
||||
|
||||
$result = $client->execute('feed.create', array('url' => 'http://bbc.co.uk/news'));
|
||||
var_dump($result);
|
||||
|
8
feed.php
8
feed.php
@ -11,7 +11,7 @@ use PicoFarad\Request;
|
||||
use PicoFeed\Writers\Atom;
|
||||
|
||||
// Check token
|
||||
$feed_token = Model\get_config_value('feed_token');
|
||||
$feed_token = Model\Config\get('feed_token');
|
||||
$request_token = Request\param('token');
|
||||
|
||||
if ($feed_token !== $request_token) {
|
||||
@ -19,7 +19,7 @@ if ($feed_token !== $request_token) {
|
||||
}
|
||||
|
||||
// Load translations
|
||||
$language = Model\get_config_value('language') ?: 'en_US';
|
||||
$language = Model\Config\get('language') ?: 'en_US';
|
||||
if ($language !== 'en_US') PicoTools\Translator\load($language);
|
||||
|
||||
// Build Feed
|
||||
@ -28,11 +28,11 @@ $writer->title = t('Bookmarks').' - Miniflux';
|
||||
$writer->site_url = Helper\get_current_base_url();
|
||||
$writer->feed_url = $writer->site_url.'feed.php?token='.urlencode($feed_token);
|
||||
|
||||
$bookmarks = Model\get_bookmarks();
|
||||
$bookmarks = Model\Item\get_bookmarks();
|
||||
|
||||
foreach ($bookmarks as $bookmark) {
|
||||
|
||||
$article = Model\get_item($bookmark['id']);
|
||||
$article = Model\Item\get($bookmark['id']);
|
||||
|
||||
$writer->items[] = array(
|
||||
'id' => $article['id'],
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
namespace Helper;
|
||||
|
||||
|
||||
function css()
|
||||
{
|
||||
$theme = \Model\get_config_value('theme');
|
||||
$theme = \Model\Config\get('theme');
|
||||
|
||||
if ($theme !== 'original') {
|
||||
|
||||
|
900
index.php
900
index.php
@ -1,892 +1,12 @@
|
||||
<?php
|
||||
|
||||
require 'common.php';
|
||||
require 'vendor/PicoTools/Template.php';
|
||||
require 'vendor/PicoTools/Helper.php';
|
||||
require 'vendor/PicoFarad/Response.php';
|
||||
require 'vendor/PicoFarad/Request.php';
|
||||
require 'vendor/PicoFarad/Session.php';
|
||||
require 'vendor/PicoFarad/Router.php';
|
||||
require 'helpers.php';
|
||||
|
||||
use PicoFarad\Router;
|
||||
use PicoFarad\Response;
|
||||
use PicoFarad\Request;
|
||||
use PicoFarad\Session;
|
||||
use PicoTools\Template;
|
||||
|
||||
|
||||
if (SESSION_SAVE_PATH !== '') session_save_path(SESSION_SAVE_PATH);
|
||||
Session\open(dirname($_SERVER['PHP_SELF']));
|
||||
|
||||
|
||||
// Called before each action
|
||||
Router\before(function($action) {
|
||||
|
||||
$ignore_actions = array('js', 'login', 'google-auth', 'google-redirect-auth', 'mozilla-auth');
|
||||
|
||||
if (! isset($_SESSION['user']) && ! in_array($action, $ignore_actions)) {
|
||||
Response\redirect('?action=login');
|
||||
}
|
||||
|
||||
// Load translations
|
||||
$language = Model\get_config_value('language') ?: 'en_US';
|
||||
if ($language !== 'en_US') PicoTools\Translator\load($language);
|
||||
|
||||
// HTTP secure headers
|
||||
$frame_src = \PicoFeed\Filter::$iframe_whitelist;
|
||||
$frame_src[] = 'https://login.persona.org';
|
||||
|
||||
Response\csp(array(
|
||||
'media-src' => '*',
|
||||
'img-src' => '*',
|
||||
'frame-src' => $frame_src
|
||||
));
|
||||
|
||||
Response\xframe();
|
||||
Response\xss();
|
||||
Response\nosniff();
|
||||
});
|
||||
|
||||
|
||||
// Javascript assets
|
||||
Router\get_action('js', function() {
|
||||
|
||||
$data = file_get_contents('assets/js/app.js');
|
||||
$data .= file_get_contents('assets/js/feed.js');
|
||||
$data .= file_get_contents('assets/js/item.js');
|
||||
$data .= file_get_contents('assets/js/event.js');
|
||||
$data .= file_get_contents('assets/js/nav.js');
|
||||
$data .= 'Miniflux.App.Run();';
|
||||
|
||||
Response\js($data);
|
||||
});
|
||||
|
||||
|
||||
// Logout and destroy session
|
||||
Router\get_action('logout', function() {
|
||||
|
||||
Session\close();
|
||||
Response\redirect('?action=login');
|
||||
});
|
||||
|
||||
|
||||
// Display form login
|
||||
Router\get_action('login', function() {
|
||||
|
||||
if (isset($_SESSION['user'])) Response\redirect('?action=unread');
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\get_config_value('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\get_config_value('auth_mozilla_token') !== '',
|
||||
'errors' => array(),
|
||||
'values' => array()
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Check credentials and redirect to unread items
|
||||
Router\post_action('login', function() {
|
||||
|
||||
$values = Request\values();
|
||||
list($valid, $errors) = Model\validate_login($values);
|
||||
|
||||
if ($valid) Response\redirect('?action=unread');
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\get_config_value('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\get_config_value('auth_mozilla_token') !== '',
|
||||
'errors' => $errors,
|
||||
'values' => $values
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Show help
|
||||
Router\get_action('show-help', function() {
|
||||
|
||||
Response\html(Template\load('show_help'));
|
||||
});
|
||||
|
||||
|
||||
// Show item
|
||||
Router\get_action('show', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$menu = Request\param('menu');
|
||||
$item = Model\get_item($id);
|
||||
$feed = Model\get_feed($item['feed_id']);
|
||||
|
||||
Model\set_item_read($id);
|
||||
|
||||
switch ($menu) {
|
||||
case 'unread':
|
||||
$nav = Model\get_nav_item($item);
|
||||
$nb_unread_items = Model\count_items('unread');
|
||||
break;
|
||||
case 'history':
|
||||
$nav = Model\get_nav_item($item, array('read'));
|
||||
break;
|
||||
case 'feed-items':
|
||||
$nav = Model\get_nav_item($item, array('unread', 'read'), array(1, 0), $item['feed_id']);
|
||||
break;
|
||||
case 'bookmarks':
|
||||
$nav = Model\get_nav_item($item, array('unread', 'read'), array(1));
|
||||
break;
|
||||
}
|
||||
|
||||
Response\html(Template\layout('show_item', array(
|
||||
'nb_unread_items' => isset($nb_unread_items) ? $nb_unread_items : null,
|
||||
'item' => $item,
|
||||
'feed' => $feed,
|
||||
'item_nav' => isset($nav) ? $nav : null,
|
||||
'menu' => $menu,
|
||||
'title' => $item['title']
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Mark item as read and redirect to the listing page
|
||||
Router\get_action('mark-item-read', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'unread');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\set_item_read($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
|
||||
// Mark item as unread and redirect to the listing page
|
||||
Router\get_action('mark-item-unread', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'history');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\set_item_unread($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
|
||||
// Mark item as removed and redirect to the listing page
|
||||
Router\get_action('mark-item-removed', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$redirect = Request\param('redirect', 'history');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\set_item_removed($id);
|
||||
|
||||
Response\Redirect('?action='.$redirect.'&offset='.$offset.'&feed_id='.$feed_id);
|
||||
});
|
||||
|
||||
|
||||
// Ajax call to download an item (fetch the full content from the original website)
|
||||
Router\post_action('download-item', function() {
|
||||
|
||||
Response\json(Model\download_item(Request\param('id')));
|
||||
});
|
||||
|
||||
|
||||
// Ajax call to mark item read
|
||||
Router\post_action('mark-item-read', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
Model\set_item_read($id);
|
||||
Response\json(array('Ok'));
|
||||
});
|
||||
|
||||
|
||||
// Ajax call to mark item unread
|
||||
Router\post_action('mark-item-unread', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
Model\set_item_unread($id);
|
||||
Response\json(array('Ok'));
|
||||
});
|
||||
|
||||
|
||||
// Ajax call change item status
|
||||
Router\post_action('change-item-status', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
|
||||
Response\json(array(
|
||||
'item_id' => $id,
|
||||
'status' => Model\switch_item_status($id)
|
||||
));
|
||||
});
|
||||
|
||||
|
||||
// Ajax call to add or remove a bookmark
|
||||
Router\post_action('bookmark', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$value = Request\int_param('value');
|
||||
|
||||
Model\set_bookmark_value($id, $value);
|
||||
|
||||
Response\json(array('id' => $id, 'value' => $value));
|
||||
});
|
||||
|
||||
|
||||
// Add new bookmark
|
||||
Router\get_action('bookmark', function() {
|
||||
|
||||
$id = Request\param('id');
|
||||
$menu = Request\param('menu', 'unread');
|
||||
$source = Request\param('source', 'unread');
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
|
||||
Model\set_bookmark_value($id, Request\int_param('value'));
|
||||
|
||||
if ($source === 'show') {
|
||||
Response\Redirect('?action=show&menu='.$menu.'&id='.$id);
|
||||
}
|
||||
|
||||
Response\Redirect('?action='.$menu.'&offset='.$offset.'&feed_id='.$feed_id.'#item-'.$id);
|
||||
});
|
||||
|
||||
|
||||
// Display history page
|
||||
Router\get_action('history', function() {
|
||||
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\count_items('read');
|
||||
|
||||
Response\html(Template\layout('history', array(
|
||||
'items' => Model\get_items(
|
||||
'read',
|
||||
$offset,
|
||||
Model\get_config_value('items_per_page'),
|
||||
'updated',
|
||||
Model\get_config_value('items_sorting_direction')
|
||||
),
|
||||
'order' => '',
|
||||
'direction' => '',
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||
'menu' => 'history',
|
||||
'title' => t('History').' ('.$nb_items.')'
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Display feed items page
|
||||
Router\get_action('feed-items', function() {
|
||||
|
||||
$feed_id = Request\int_param('feed_id', 0);
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\count_feed_items($feed_id);
|
||||
$feed = Model\get_feed($feed_id);
|
||||
$order = Request\param('order', 'updated');
|
||||
$direction = Request\param('direction', Model\get_config_value('items_sorting_direction'));
|
||||
$items = Model\get_feed_items($feed_id, $offset, Model\get_config_value('items_per_page'), $order, $direction);
|
||||
|
||||
Response\html(Template\layout('feed_items', array(
|
||||
'order' => $order,
|
||||
'direction' => $direction,
|
||||
'feed' => $feed,
|
||||
'items' => $items,
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||
'menu' => 'feed-items',
|
||||
'title' => '('.$nb_items.') '.$feed['title']
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Display bookmarks page
|
||||
Router\get_action('bookmarks', function() {
|
||||
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$nb_items = Model\count_bookmarks();
|
||||
|
||||
Response\html(Template\layout('bookmarks', array(
|
||||
'order' => '',
|
||||
'direction' => '',
|
||||
'items' => Model\get_bookmarks($offset, Model\get_config_value('items_per_page')),
|
||||
'nb_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||
'menu' => 'bookmarks',
|
||||
'title' => t('Bookmarks').' ('.$nb_items.')'
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Mark all unread items as read
|
||||
Router\get_action('mark-as-read', function() {
|
||||
|
||||
Model\mark_as_read();
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
|
||||
// Mark all unread items as read for a specific feed
|
||||
Router\get_action('mark-feed-as-read', function() {
|
||||
|
||||
$feed_id = Request\int_param('feed_id');
|
||||
Model\mark_feed_as_read($feed_id);
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
|
||||
// Mark sent items id as read (Ajax request)
|
||||
Router\post_action('mark-items-as-read', function(){
|
||||
|
||||
Model\mark_items_as_read(Request\values());
|
||||
Response\json(array('OK'));
|
||||
});
|
||||
|
||||
|
||||
// Confirmation box to flush history
|
||||
Router\get_action('confirm-flush-history', function() {
|
||||
|
||||
Response\html(Template\layout('confirm_flush_items', array(
|
||||
'menu' => 'history',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Flush history
|
||||
Router\get_action('flush-history', function() {
|
||||
|
||||
Model\mark_as_removed();
|
||||
Response\redirect('?action=history');
|
||||
});
|
||||
|
||||
|
||||
// Refresh all feeds, used when Javascript is disabled
|
||||
Router\get_action('refresh-all', function() {
|
||||
|
||||
Model\update_feeds();
|
||||
Session\flash(t('Your subscriptions are updated'));
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
|
||||
// Edit feed form
|
||||
Router\get_action('edit-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('edit_feed', array(
|
||||
'values' => Model\get_feed($id),
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Edit subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Submit edit feed form
|
||||
Router\post_action('edit-feed', function() {
|
||||
|
||||
$values = Request\values();
|
||||
list($valid, $errors) = Model\validate_feed_modification($values);
|
||||
|
||||
if ($valid) {
|
||||
|
||||
if (Model\save_feed($values)) {
|
||||
Session\flash(t('Your subscription has been updated.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to edit your subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
}
|
||||
|
||||
Response\html(Template\layout('edit_feed', array(
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Edit subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Disable content grabber for a feed
|
||||
Router\get_action('disable-grabber-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\disable_grabber_feed($id)) {
|
||||
Session\flash(t('The content grabber is disabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to disable the content grabber for this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
|
||||
// Enable content grabber for a feed
|
||||
Router\get_action('enable-grabber-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\enable_grabber_feed($id)) {
|
||||
Session\flash(t('The content grabber is enabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to activate the content grabber for this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
|
||||
// Confirmation box to disable a feed
|
||||
Router\get_action('confirm-disable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('confirm_disable_feed', array(
|
||||
'feed' => Model\get_feed($id),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Disable a feed
|
||||
Router\get_action('disable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\disable_feed($id)) {
|
||||
Session\flash(t('This subscription has been disabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to disable this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
|
||||
// Enable a feed
|
||||
Router\get_action('enable-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\enable_feed($id)) {
|
||||
Session\flash(t('This subscription has been enabled successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to enable this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
|
||||
// Confirmation box to remove a feed
|
||||
Router\get_action('confirm-remove-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
Response\html(Template\layout('confirm_remove_feed', array(
|
||||
'feed' => Model\get_feed($id),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Confirmation')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Remove a feed
|
||||
Router\get_action('remove-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
|
||||
if ($id && Model\remove_feed($id)) {
|
||||
Session\flash(t('This subscription has been removed successfully.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to remove this subscription.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=feeds');
|
||||
});
|
||||
|
||||
|
||||
// Refresh one feed and redirect to unread items
|
||||
Router\get_action('refresh-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id');
|
||||
if ($id) Model\update_feed($id);
|
||||
Response\redirect('?action=unread');
|
||||
});
|
||||
|
||||
|
||||
// Ajax call to refresh one feed
|
||||
Router\post_action('refresh-feed', function() {
|
||||
|
||||
$id = Request\int_param('feed_id', 0);
|
||||
|
||||
if ($id) {
|
||||
$result = Model\update_feed($id);
|
||||
}
|
||||
|
||||
Response\json(array('feed_id' => $id, 'result' => $result));
|
||||
});
|
||||
|
||||
|
||||
// Display all feeds
|
||||
Router\get_action('feeds', function() {
|
||||
|
||||
if (! Request\int_param('disable_empty_feeds_check')) {
|
||||
|
||||
$empty_feeds = Model\get_empty_feeds();
|
||||
|
||||
if (! empty($empty_feeds)) {
|
||||
|
||||
$listing = array();
|
||||
|
||||
foreach ($empty_feeds as &$feed) {
|
||||
$listing[] = '"'.$feed['title'].'"';
|
||||
}
|
||||
|
||||
$message = t(
|
||||
'There is %d empty feeds, there is maybe an error: %s...',
|
||||
count($empty_feeds),
|
||||
implode(', ', array_slice($listing, 0, 5))
|
||||
);
|
||||
|
||||
Session\flash_error($message);
|
||||
}
|
||||
}
|
||||
|
||||
Response\html(Template\layout('feeds', array(
|
||||
'feeds' => Model\get_feeds(),
|
||||
'nothing_to_read' => Request\int_param('nothing_to_read'),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Subscriptions')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Display form to add one feed
|
||||
Router\get_action('add', function() {
|
||||
|
||||
Response\html(Template\layout('add', array(
|
||||
'values' => array(),
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('New subscription')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Add a feed with the form or directly from the url, it can be used by a bookmarklet by example
|
||||
Router\action('subscribe', function() {
|
||||
|
||||
if (Request\param('url')) {
|
||||
$values = array();
|
||||
$url = Request\param('url');
|
||||
}
|
||||
else {
|
||||
$values = Request\values();
|
||||
$url = isset($values['url']) ? $values['url'] : '';
|
||||
}
|
||||
|
||||
$values += array('download_content' => 0);
|
||||
$url = trim($url);
|
||||
$result = Model\import_feed($url, $values['download_content']);
|
||||
|
||||
if ($result) {
|
||||
|
||||
Session\flash(t('Subscription added successfully.'));
|
||||
Response\redirect('?action=feeds');
|
||||
}
|
||||
else {
|
||||
|
||||
Session\flash_error(t('Unable to find a subscription.'));
|
||||
}
|
||||
|
||||
Response\html(Template\layout('add', array(
|
||||
'values' => array('url' => $url),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('Subscriptions')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// OPML export
|
||||
Router\get_action('export', function() {
|
||||
|
||||
Response\force_download('feeds.opml');
|
||||
Response\xml(Model\export_feeds());
|
||||
});
|
||||
|
||||
|
||||
// OPML import form
|
||||
Router\get_action('import', function() {
|
||||
|
||||
Response\html(Template\layout('import', array(
|
||||
'errors' => array(),
|
||||
'menu' => 'feeds',
|
||||
'title' => t('OPML Import')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// OPML importation
|
||||
Router\post_action('import', function() {
|
||||
|
||||
if (Model\import_feeds(Request\file_content('file'))) {
|
||||
|
||||
Session\flash(t('Your feeds have been imported.'));
|
||||
Response\redirect('?action=feeds&disable_empty_feeds_check=1');
|
||||
}
|
||||
else {
|
||||
|
||||
Session\flash_error(t('Unable to import your OPML file.'));
|
||||
Response\redirect('?action=import');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Re-generate tokens
|
||||
Router\get_action('generate-tokens', function() {
|
||||
|
||||
Model\new_tokens();
|
||||
Response\redirect('?action=config#api');
|
||||
});
|
||||
|
||||
|
||||
// Optimize the database manually
|
||||
Router\get_action('optimize-db', function() {
|
||||
|
||||
\PicoTools\singleton('db')->getConnection()->exec('VACUUM');
|
||||
Response\redirect('?action=config');
|
||||
});
|
||||
|
||||
|
||||
// Download the compressed database
|
||||
Router\get_action('download-db', function() {
|
||||
|
||||
Response\force_download('db.sqlite.gz');
|
||||
Response\binary(gzencode(file_get_contents(DB_FILENAME)));
|
||||
});
|
||||
|
||||
|
||||
// Flush console messages
|
||||
Router\get_action('flush-console', function() {
|
||||
|
||||
@unlink(DEBUG_FILENAME);
|
||||
Response\redirect('?action=console');
|
||||
});
|
||||
|
||||
|
||||
// Display console
|
||||
Router\get_action('console', function() {
|
||||
|
||||
Response\html(Template\layout('console', array(
|
||||
'content' => @file_get_contents(DEBUG_FILENAME),
|
||||
'title' => t('Console')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Display preferences page
|
||||
Router\get_action('config', function() {
|
||||
|
||||
Response\html(Template\layout('config', array(
|
||||
'errors' => array(),
|
||||
'values' => Model\get_config(),
|
||||
'db_size' => filesize(DB_FILENAME),
|
||||
'languages' => Model\get_languages(),
|
||||
'autoflush_options' => Model\get_autoflush_options(),
|
||||
'paging_options' => Model\get_paging_options(),
|
||||
'theme_options' => Model\get_themes(),
|
||||
'sorting_options' => Model\get_sorting_directions(),
|
||||
'menu' => 'config',
|
||||
'title' => t('Preferences')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Update preferences
|
||||
Router\post_action('config', function() {
|
||||
|
||||
$values = Request\values() + array('nocontent' => 0);
|
||||
list($valid, $errors) = Model\validate_config_update($values);
|
||||
|
||||
if ($valid) {
|
||||
|
||||
if (Model\save_config($values)) {
|
||||
Session\flash(t('Your preferences are updated.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to update your preferences.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=config');
|
||||
}
|
||||
|
||||
Response\html(Template\layout('config', array(
|
||||
'errors' => $errors,
|
||||
'values' => $values,
|
||||
'db_size' => filesize(DB_FILENAME),
|
||||
'languages' => Model\get_languages(),
|
||||
'autoflush_options' => Model\get_autoflush_options(),
|
||||
'paging_options' => Model\get_paging_options(),
|
||||
'theme_options' => Model\get_themes(),
|
||||
'sorting_options' => Model\get_sorting_directions(),
|
||||
'menu' => 'config',
|
||||
'title' => t('Preferences')
|
||||
)));
|
||||
});
|
||||
|
||||
|
||||
// Link to a Google Account (redirect)
|
||||
Router\get_action('google-redirect-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
Response\Redirect(AuthProvider\google_get_url(Helper\get_current_base_url(), '?action=google-link'));
|
||||
});
|
||||
|
||||
|
||||
// Link to a Google Account (association)
|
||||
Router\get_action('google-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\google_validate();
|
||||
|
||||
if ($valid) {
|
||||
Model\save_auth_token('google', $token);
|
||||
Session\flash(t('Your Google Account is linked to Miniflux.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to link Miniflux to your Google Account.'));
|
||||
}
|
||||
|
||||
Response\redirect('?action=config');
|
||||
});
|
||||
|
||||
|
||||
// Authenticate with a Google Account (redirect)
|
||||
Router\get_action('google-redirect-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
Response\Redirect(AuthProvider\google_get_url(Helper\get_current_base_url(), '?action=google-auth'));
|
||||
});
|
||||
|
||||
|
||||
// Authenticate with a Google Account (callback url)
|
||||
Router\get_action('google-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\google_validate();
|
||||
|
||||
if ($valid && $token === Model\get_config_value('auth_google_token')) {
|
||||
|
||||
$_SESSION['user'] = array(
|
||||
'username' => Model\get_config_value('username'),
|
||||
'language' => Model\get_config_value('language'),
|
||||
);
|
||||
|
||||
Response\redirect('?action=unread');
|
||||
}
|
||||
else {
|
||||
|
||||
Response\html(Template\load('login', array(
|
||||
'google_auth_enable' => Model\get_config_value('auth_google_token') !== '',
|
||||
'mozilla_auth_enable' => Model\get_config_value('auth_mozilla_token') !== '',
|
||||
'errors' => array('login' => t('Unable to authenticate with Google')),
|
||||
'values' => array()
|
||||
)));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Authenticate with a Mozilla Persona (ajax check)
|
||||
Router\post_action('mozilla-auth', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\mozilla_validate(Request\value('token'));
|
||||
|
||||
if ($valid && $token === Model\get_config_value('auth_mozilla_token')) {
|
||||
|
||||
$_SESSION['user'] = array(
|
||||
'username' => Model\get_config_value('username'),
|
||||
'language' => Model\get_config_value('language'),
|
||||
);
|
||||
|
||||
Response\text('?action=unread');
|
||||
}
|
||||
else {
|
||||
Response\text("?action=login");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Link Miniflux to a Mozilla Account (ajax check)
|
||||
Router\post_action('mozilla-link', function() {
|
||||
|
||||
require 'vendor/PicoTools/AuthProvider.php';
|
||||
|
||||
list($valid, $token) = AuthProvider\mozilla_validate(Request\value('token'));
|
||||
|
||||
if ($valid) {
|
||||
Model\save_auth_token('mozilla', $token);
|
||||
Session\flash(t('Your Mozilla Persona Account is linked to Miniflux.'));
|
||||
}
|
||||
else {
|
||||
Session\flash_error(t('Unable to link Miniflux to your Mozilla Persona Account.'));
|
||||
}
|
||||
|
||||
Response\text("?action=config");
|
||||
});
|
||||
|
||||
|
||||
// Remove account link
|
||||
Router\get_action('unlink-account-provider', function() {
|
||||
Model\remove_auth_token(Request\param('type'));
|
||||
Response\redirect('?action=config');
|
||||
});
|
||||
|
||||
|
||||
// Display unread items
|
||||
Router\notfound(function() {
|
||||
|
||||
Model\autoflush();
|
||||
|
||||
$order = Request\param('order', 'updated');
|
||||
$direction = Request\param('direction', Model\get_config_value('items_sorting_direction'));
|
||||
$offset = Request\int_param('offset', 0);
|
||||
$items = Model\get_items('unread', $offset, Model\get_config_value('items_per_page'), $order, $direction);
|
||||
$nb_items = Model\count_items('unread');
|
||||
|
||||
if ($nb_items === 0) Response\redirect('?action=feeds¬hing_to_read=1');
|
||||
|
||||
Response\html(Template\layout('unread_items', array(
|
||||
'order' => $order,
|
||||
'direction' => $direction,
|
||||
'items' => $items,
|
||||
'nb_items' => $nb_items,
|
||||
'nb_unread_items' => $nb_items,
|
||||
'offset' => $offset,
|
||||
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||
'title' => 'Miniflux ('.$nb_items.')',
|
||||
'menu' => 'unread'
|
||||
)));
|
||||
});
|
||||
require 'check_setup.php';
|
||||
require 'controllers/common.php';
|
||||
require 'controllers/console.php';
|
||||
require 'controllers/user.php';
|
||||
require 'controllers/config.php';
|
||||
require 'controllers/item.php';
|
||||
require 'controllers/history.php';
|
||||
require 'controllers/bookmark.php';
|
||||
require 'controllers/feed.php';
|
||||
require 'controllers/unread.php';
|
||||
|
54
jsonrpc.php
54
jsonrpc.php
@ -7,26 +7,26 @@ use JsonRPC\Server;
|
||||
|
||||
$server = new Server;
|
||||
$server->authentication(array(
|
||||
Model\get_config_value('username') => Model\get_config_value('api_token')
|
||||
\Model\Config\get('username') => \Model\Config\get('api_token')
|
||||
));
|
||||
|
||||
// Get all feeds
|
||||
$server->register('feed.list', function () {
|
||||
|
||||
return Model\get_feeds();
|
||||
return Model\Feed\get_all();
|
||||
});
|
||||
|
||||
// Get one feed
|
||||
$server->register('feed.info', function ($feed_id) {
|
||||
|
||||
return Model\get_feed($feed_id);
|
||||
return Model\Feed\get($feed_id);
|
||||
});
|
||||
|
||||
// Add a new feed
|
||||
$server->register('feed.create', function($url) {
|
||||
|
||||
$result = Model\import_feed($url);
|
||||
Model\write_debug();
|
||||
$result = Model\Feed\create($url);
|
||||
Model\Config\write_debug();
|
||||
|
||||
return $result;
|
||||
});
|
||||
@ -34,133 +34,133 @@ $server->register('feed.create', function($url) {
|
||||
// Delete a feed
|
||||
$server->register('feed.delete', function($feed_id) {
|
||||
|
||||
return Model\remove_feed($feed_id);
|
||||
return Model\Feed\remove($feed_id);
|
||||
});
|
||||
|
||||
// Delete all feeds
|
||||
$server->register('feed.delete_all', function() {
|
||||
|
||||
return Model\remove_feeds();
|
||||
return Model\Feed\remove_all();
|
||||
});
|
||||
|
||||
// Enable a feed
|
||||
$server->register('feed.enable', function($feed_id) {
|
||||
|
||||
return Model\enable_feed($feed_id);
|
||||
return Model\Feed\enable($feed_id);
|
||||
});
|
||||
|
||||
// Disable a feed
|
||||
$server->register('feed.disable', function($feed_id) {
|
||||
|
||||
return Model\disable_feed($feed_id);
|
||||
return Model\Feed\disable($feed_id);
|
||||
});
|
||||
|
||||
// Update a feed
|
||||
$server->register('feed.update', function($feed_id) {
|
||||
|
||||
return Model\update_feed($feed_id);
|
||||
return Model\Feed\refresh($feed_id);
|
||||
});
|
||||
|
||||
// Get all items for a specific feed
|
||||
$server->register('item.feed.list', function ($feed_id, $offset = null, $limit = null) {
|
||||
|
||||
return Model\get_feed_items($feed_id, $offset, $limit);
|
||||
return Model\Item\get_all_by_feed($feed_id, $offset, $limit);
|
||||
});
|
||||
|
||||
// Count all feed items
|
||||
$server->register('item.feed.count', function ($feed_id) {
|
||||
|
||||
return Model\count_feed_items($feed_id);
|
||||
return Model\Item\count_by_feed($feed_id);
|
||||
});
|
||||
|
||||
// Get all bookmark items
|
||||
$server->register('item.bookmark.list', function ($offset = null, $limit = null) {
|
||||
|
||||
return Model\get_bookmarks($offset, $limit);
|
||||
return Model\Item\get_bookmarks($offset, $limit);
|
||||
});
|
||||
|
||||
// Count bookmarks
|
||||
$server->register('item.bookmark.count', function () {
|
||||
|
||||
return Model\count_bookmarks();
|
||||
return Model\Item\count_bookmarks();
|
||||
});
|
||||
|
||||
// Add a bookmark
|
||||
$server->register('item.bookmark.create', function ($item_id) {
|
||||
|
||||
return Model\set_bookmark_value($item_id, 1);
|
||||
return Model\Item\set_bookmark_value($item_id, 1);
|
||||
});
|
||||
|
||||
// Remove a bookmark
|
||||
$server->register('item.bookmark.delete', function ($item_id) {
|
||||
|
||||
return Model\set_bookmark_value($item_id, 0);
|
||||
return Model\Item\set_bookmark_value($item_id, 0);
|
||||
});
|
||||
|
||||
// Get all unread items
|
||||
$server->register('item.list_unread', function ($offset = null, $limit = null) {
|
||||
|
||||
return Model\get_items('unread', $offset, $limit);
|
||||
return Model\Item\get_all('unread', $offset, $limit);
|
||||
});
|
||||
|
||||
// Count all unread items
|
||||
$server->register('item.count_unread', function () {
|
||||
|
||||
return Model\count_items('unread');
|
||||
return Model\Item\count_by_status('unread');
|
||||
});
|
||||
|
||||
// Get all read items
|
||||
$server->register('item.list_read', function ($offset = null, $limit = null) {
|
||||
|
||||
return Model\get_items('read', $offset, $limit);
|
||||
return Model\Item\get_all('read', $offset, $limit);
|
||||
});
|
||||
|
||||
// Count all read items
|
||||
$server->register('item.count_read', function () {
|
||||
|
||||
return Model\count_items('read');
|
||||
return Model\Item\count_by_status('read');
|
||||
});
|
||||
|
||||
// Get one item
|
||||
$server->register('item.info', function ($item_id) {
|
||||
|
||||
return Model\get_item($item_id);
|
||||
return Model\Item\get($item_id);
|
||||
});
|
||||
|
||||
// Delete an item
|
||||
$server->register('item.delete', function($item_id) {
|
||||
|
||||
return Model\set_item_removed($item_id);
|
||||
return Model\Item\set_removed($item_id);
|
||||
});
|
||||
|
||||
// Mark item as read
|
||||
$server->register('item.mark_as_read', function($item_id) {
|
||||
|
||||
return Model\set_item_read($item_id);
|
||||
return Model\Item\set_read($item_id);
|
||||
});
|
||||
|
||||
// Mark item as unread
|
||||
$server->register('item.mark_as_unread', function($item_id) {
|
||||
|
||||
return Model\set_item_unread($item_id);
|
||||
return Model\Item\set_unread($item_id);
|
||||
});
|
||||
|
||||
// Change the status of list of items
|
||||
$server->register('item.set_list_status', function($status, array $items) {
|
||||
|
||||
return Model\set_items_status($status, $items);
|
||||
return Model\Item\set_status($status, $items);
|
||||
});
|
||||
|
||||
// Flush all read items
|
||||
$server->register('item.flush', function() {
|
||||
|
||||
return Model\mark_as_removed();
|
||||
return Model\Item\mark_all_as_removed();
|
||||
});
|
||||
|
||||
// Mark all unread items as read
|
||||
$server->register('item.mark_all_as_read', function() {
|
||||
|
||||
return Model\mark_as_read();
|
||||
return Model\Item\mark_all_as_read();
|
||||
});
|
||||
|
||||
echo $server->execute();
|
@ -42,6 +42,7 @@ return array(
|
||||
'Bookmarklet:' => 'Bookmarklet :',
|
||||
'Subscribe with Miniflux' => 'S\'abonner avec Miniflux',
|
||||
'Drag and drop this link to your bookmarks' => 'Glisser-déposer ce lien dans vos favoris',
|
||||
'The content grabber is disabled successfully.' => 'Le téléchargement de contenu a été désactivé avec succès.',
|
||||
'The content grabber is enabled successfully.' => 'Le téléchargement de contenu est activé avec succès.',
|
||||
'Unable to activate the content grabber for this subscription.' => 'Impossible d\'activer le téléchargement de contenu pour cet abonnement.',
|
||||
'enable full content' => 'télécharger le contenu complet',
|
||||
|
338
models/feed.php
Normal file
338
models/feed.php
Normal file
@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
namespace Model\Feed;
|
||||
|
||||
require_once 'vendor/PicoFeed/Filter.php';
|
||||
require_once 'vendor/PicoFeed/Export.php';
|
||||
require_once 'vendor/PicoFeed/Import.php';
|
||||
require_once 'vendor/PicoFeed/Reader.php';
|
||||
require_once 'vendor/SimpleValidator/Validator.php';
|
||||
require_once 'vendor/SimpleValidator/Base.php';
|
||||
require_once 'vendor/SimpleValidator/Validators/Required.php';
|
||||
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
const LIMIT_ALL = -1;
|
||||
|
||||
// Update feed information
|
||||
function update(array $values)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->eq('id', $values['id'])
|
||||
->save(array(
|
||||
'title' => $values['title'],
|
||||
'site_url' => $values['site_url'],
|
||||
'feed_url' => $values['feed_url']
|
||||
));
|
||||
}
|
||||
|
||||
// Export all feeds
|
||||
function export_opml()
|
||||
{
|
||||
$opml = new \PicoFeed\Export(get_all());
|
||||
return $opml->execute();
|
||||
}
|
||||
|
||||
// Import OPML file
|
||||
function import_opml($content)
|
||||
{
|
||||
$import = new \PicoFeed\Import($content);
|
||||
$feeds = $import->execute();
|
||||
|
||||
if ($feeds) {
|
||||
|
||||
$db = \PicoTools\singleton('db');
|
||||
$db->startTransaction();
|
||||
|
||||
foreach ($feeds as $feed) {
|
||||
|
||||
if (! $db->table('feeds')->eq('feed_url', $feed->feed_url)->count()) {
|
||||
|
||||
$db->table('feeds')->save(array(
|
||||
'title' => $feed->title,
|
||||
'site_url' => $feed->site_url,
|
||||
'feed_url' => $feed->feed_url
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$db->closeTransaction();
|
||||
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add a new feed from an URL
|
||||
function create($url, $grabber = false)
|
||||
{
|
||||
$reader = new \PicoFeed\Reader;
|
||||
$resource = $reader->download($url, '', '', HTTP_TIMEOUT, \Model\Config\HTTP_USERAGENT);
|
||||
|
||||
$parser = $reader->getParser();
|
||||
|
||||
if ($parser !== false) {
|
||||
|
||||
$parser->grabber = $grabber;
|
||||
$feed = $parser->execute();
|
||||
|
||||
if ($feed === false) {
|
||||
\Model\Config\write_debug();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $feed->url) $feed->url = $reader->getUrl();
|
||||
|
||||
if (! $feed->title) {
|
||||
\Model\Config\write_debug();
|
||||
return false;
|
||||
}
|
||||
|
||||
$db = \PicoTools\singleton('db');
|
||||
|
||||
if (! $db->table('feeds')->eq('feed_url', $reader->getUrl())->count()) {
|
||||
|
||||
// Etag and LastModified are added the next update
|
||||
$rs = $db->table('feeds')->save(array(
|
||||
'title' => $feed->title,
|
||||
'site_url' => $feed->url,
|
||||
'feed_url' => $reader->getUrl(),
|
||||
'download_content' => $grabber ? 1 : 0
|
||||
));
|
||||
|
||||
if ($rs) {
|
||||
|
||||
$feed_id = $db->getConnection()->getLastId();
|
||||
\Model\Item\update_all($feed_id, $feed->items, $grabber);
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return (int) $feed_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Refresh all feeds
|
||||
function refresh_all($limit = LIMIT_ALL)
|
||||
{
|
||||
$feeds_id = get_ids($limit);
|
||||
|
||||
foreach ($feeds_id as $feed_id) {
|
||||
refresh($feed_id);
|
||||
}
|
||||
|
||||
// Auto-vacuum for people using the cronjob
|
||||
\PicoTools\singleton('db')->getConnection()->exec('VACUUM');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Refresh one feed
|
||||
function refresh($feed_id)
|
||||
{
|
||||
$feed = get($feed_id);
|
||||
if (empty($feed)) return false;
|
||||
|
||||
$reader = new \PicoFeed\Reader;
|
||||
|
||||
$resource = $reader->download(
|
||||
$feed['feed_url'],
|
||||
$feed['last_modified'],
|
||||
$feed['etag'],
|
||||
HTTP_TIMEOUT,
|
||||
\Model\Config\HTTP_USERAGENT
|
||||
);
|
||||
|
||||
// Update the `last_checked` column each time, HTTP cache or not
|
||||
update_last_checked($feed_id);
|
||||
|
||||
if (! $resource->isModified()) {
|
||||
update_parsing_error($feed_id, 0);
|
||||
\Model\Config\write_debug();
|
||||
return true;
|
||||
}
|
||||
|
||||
$parser = $reader->getParser();
|
||||
|
||||
if ($parser !== false) {
|
||||
|
||||
if ($feed['download_content']) {
|
||||
|
||||
// Don't fetch previous items, only new one
|
||||
$parser->grabber_ignore_urls = \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('feed_id', $feed_id)
|
||||
->findAllByColumn('url');
|
||||
|
||||
$parser->grabber = true;
|
||||
$parser->grabber_timeout = HTTP_TIMEOUT;
|
||||
$parser->grabber_user_agent = \Model\Config\HTTP_FAKE_USERAGENT;
|
||||
}
|
||||
|
||||
$result = $parser->execute();
|
||||
|
||||
if ($result !== false) {
|
||||
|
||||
update_parsing_error($feed_id, 0);
|
||||
update_cache($feed_id, $resource->getLastModified(), $resource->getEtag());
|
||||
\Model\Item\update_all($feed_id, $result->items, $parser->grabber);
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
update_parsing_error($feed_id, 1);
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the list of feeds ID to refresh
|
||||
function get_ids($limit = LIMIT_ALL)
|
||||
{
|
||||
$table_feeds = \PicoTools\singleton('db')->table('feeds')
|
||||
->eq('enabled', 1)
|
||||
->asc('last_checked');
|
||||
|
||||
if ($limit !== LIMIT_ALL) {
|
||||
$table_feeds->limit((int) $limit);
|
||||
}
|
||||
|
||||
return $table_feeds->listing('id', 'id');
|
||||
}
|
||||
|
||||
// Get feeds with no item
|
||||
function get_all_empty()
|
||||
{
|
||||
$feeds = \PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->columns('feeds.id', 'feeds.title', 'COUNT(items.id) AS nb_items')
|
||||
->join('items', 'feed_id', 'id')
|
||||
->isNull('feeds.last_checked')
|
||||
->groupBy('feeds.id')
|
||||
->findAll();
|
||||
|
||||
foreach ($feeds as $key => &$feed) {
|
||||
|
||||
if ($feed['nb_items'] > 0) {
|
||||
unset($feeds[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $feeds;
|
||||
}
|
||||
|
||||
// Get all feeds
|
||||
function get_all()
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->asc('title')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
// Get one feed
|
||||
function get($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->eq('id', $feed_id)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
// Update parsing error column
|
||||
function update_parsing_error($feed_id, $value)
|
||||
{
|
||||
\PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->save(array('parsing_error' => $value));
|
||||
}
|
||||
|
||||
// Update last check date
|
||||
function update_last_checked($feed_id)
|
||||
{
|
||||
\PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->eq('id', $feed_id)
|
||||
->save(array(
|
||||
'last_checked' => time()
|
||||
));
|
||||
}
|
||||
|
||||
// Update Etag and last Modified columns
|
||||
function update_cache($feed_id, $last_modified, $etag)
|
||||
{
|
||||
\PicoTools\singleton('db')
|
||||
->table('feeds')
|
||||
->eq('id', $feed_id)
|
||||
->save(array(
|
||||
'last_modified' => $last_modified,
|
||||
'etag' => $etag
|
||||
));
|
||||
}
|
||||
|
||||
// Remove one feed
|
||||
function remove($feed_id)
|
||||
{
|
||||
// Items are removed by a sql constraint
|
||||
return \PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->remove();
|
||||
}
|
||||
|
||||
// Remove all feeds
|
||||
function remove_all()
|
||||
{
|
||||
return \PicoTools\singleton('db')->table('feeds')->remove();
|
||||
}
|
||||
|
||||
// Enable a feed (activate refresh)
|
||||
function enable($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->save((array('enabled' => 1)));
|
||||
}
|
||||
|
||||
// Disable feed
|
||||
function disable($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->save((array('enabled' => 0)));
|
||||
}
|
||||
|
||||
// Enable content download
|
||||
function enable_grabber($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->save((array('download_content' => 1)));
|
||||
}
|
||||
|
||||
// Disable content download
|
||||
function disable_grabber($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')->table('feeds')->eq('id', $feed_id)->save((array('download_content' => 0)));
|
||||
}
|
||||
|
||||
// Validation for edit
|
||||
function validate_modification(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('id', t('The feed id is required')),
|
||||
new Validators\Required('title', t('The title is required')),
|
||||
new Validators\Required('site_url', t('The site url is required')),
|
||||
new Validators\Required('feed_url', t('The feed url is required')),
|
||||
));
|
||||
|
||||
$result = $v->execute();
|
||||
$errors = $v->getErrors();
|
||||
|
||||
return array(
|
||||
$result,
|
||||
$errors
|
||||
);
|
||||
}
|
471
models/item.php
Normal file
471
models/item.php
Normal file
@ -0,0 +1,471 @@
|
||||
<?php
|
||||
|
||||
namespace Model\Item;
|
||||
|
||||
require_once 'vendor/Readability/Readability.php';
|
||||
require_once 'vendor/PicoFeed/Grabber.php';
|
||||
require_once 'vendor/PicoFeed/Filter.php';
|
||||
|
||||
// Get all items
|
||||
function get_all($status, $offset = null, $limit = null, $order_column = 'updated', $order_direction = 'desc')
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns(
|
||||
'items.id',
|
||||
'items.title',
|
||||
'items.updated',
|
||||
'items.url',
|
||||
'items.bookmark',
|
||||
'items.feed_id',
|
||||
'items.status',
|
||||
'items.content',
|
||||
'feeds.site_url',
|
||||
'feeds.title AS feed_title'
|
||||
)
|
||||
->join('feeds', 'id', 'feed_id')
|
||||
->eq('status', $status)
|
||||
->orderBy($order_column, $order_direction)
|
||||
->offset($offset)
|
||||
->limit($limit)
|
||||
->findAll();
|
||||
}
|
||||
|
||||
// Get the number of items per status
|
||||
function count_by_status($status)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('status', $status)
|
||||
->count();
|
||||
}
|
||||
|
||||
// Get the number of bookmarks
|
||||
function count_bookmarks()
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('bookmark', 1)
|
||||
->in('status', array('read', 'unread'))
|
||||
->count();
|
||||
}
|
||||
|
||||
// Get all bookmarks
|
||||
function get_bookmarks($offset = null, $limit = null)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns(
|
||||
'items.id',
|
||||
'items.title',
|
||||
'items.updated',
|
||||
'items.url',
|
||||
'items.bookmark',
|
||||
'items.status',
|
||||
'items.content',
|
||||
'items.feed_id',
|
||||
'feeds.site_url',
|
||||
'feeds.title AS feed_title'
|
||||
)
|
||||
->join('feeds', 'id', 'feed_id')
|
||||
->in('status', array('read', 'unread'))
|
||||
->eq('bookmark', 1)
|
||||
->orderBy('updated', \Model\Config\get('items_sorting_direction'))
|
||||
->offset($offset)
|
||||
->limit($limit)
|
||||
->findAll();
|
||||
}
|
||||
|
||||
// Get the number of items per feed
|
||||
function count_by_feed($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('feed_id', $feed_id)
|
||||
->in('status', array('unread', 'read'))
|
||||
->count();
|
||||
}
|
||||
|
||||
// Get all items per feed
|
||||
function get_all_by_feed($feed_id, $offset = null, $limit = null, $order_column = 'updated', $order_direction = 'desc')
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns(
|
||||
'items.id',
|
||||
'items.title',
|
||||
'items.updated',
|
||||
'items.url',
|
||||
'items.feed_id',
|
||||
'items.status',
|
||||
'items.content',
|
||||
'items.bookmark',
|
||||
'feeds.site_url'
|
||||
)
|
||||
->join('feeds', 'id', 'feed_id')
|
||||
->in('status', array('unread', 'read'))
|
||||
->eq('feed_id', $feed_id)
|
||||
->orderBy($order_column, $order_direction)
|
||||
->offset($offset)
|
||||
->limit($limit)
|
||||
->findAll();
|
||||
}
|
||||
|
||||
// Get one item by id
|
||||
function get($id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
// Get item naviguation (next/prev items)
|
||||
function get_nav($item, $status = array('unread'), $bookmark = array(1, 0), $feed_id = null)
|
||||
{
|
||||
$query = \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns('id', 'status', 'title', 'bookmark')
|
||||
->neq('status', 'removed')
|
||||
->orderBy('updated', \Model\Config\get('items_sorting_direction'));
|
||||
|
||||
if ($feed_id) $query->eq('feed_id', $feed_id);
|
||||
|
||||
$items = $query->findAll();
|
||||
|
||||
$next_item = null;
|
||||
$previous_item = null;
|
||||
|
||||
for ($i = 0, $ilen = count($items); $i < $ilen; $i++) {
|
||||
|
||||
if ($items[$i]['id'] == $item['id']) {
|
||||
|
||||
if ($i > 0) {
|
||||
|
||||
$j = $i - 1;
|
||||
|
||||
while ($j >= 0) {
|
||||
|
||||
if (in_array($items[$j]['status'], $status) && in_array($items[$j]['bookmark'], $bookmark)) {
|
||||
$previous_item = $items[$j];
|
||||
break;
|
||||
}
|
||||
|
||||
$j--;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i < ($ilen - 1)) {
|
||||
|
||||
$j = $i + 1;
|
||||
|
||||
while ($j < $ilen) {
|
||||
|
||||
if (in_array($items[$j]['status'], $status) && in_array($items[$j]['bookmark'], $bookmark)) {
|
||||
$next_item = $items[$j];
|
||||
break;
|
||||
}
|
||||
|
||||
$j++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'next' => $next_item,
|
||||
'previous' => $previous_item
|
||||
);
|
||||
}
|
||||
|
||||
// Change item status to removed and clear content
|
||||
function set_removed($id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('status' => 'removed', 'content' => ''));
|
||||
}
|
||||
|
||||
// Change item status to read
|
||||
function set_read($id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('status' => 'read'));
|
||||
}
|
||||
|
||||
// Change item status to unread
|
||||
function set_unread($id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('status' => 'unread'));
|
||||
}
|
||||
|
||||
// Change item status to "read", "unread" or "removed"
|
||||
function set_status($status, array $items)
|
||||
{
|
||||
if (! in_array($status, array('read', 'unread', 'removed'))) return false;
|
||||
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->in('id', $items)
|
||||
->save(array('status' => $status));
|
||||
}
|
||||
|
||||
// Enable/disable bookmark flag
|
||||
function set_bookmark_value($id, $value)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('bookmark' => $value));
|
||||
}
|
||||
|
||||
// Swap item status read <-> unread
|
||||
function switch_status($id)
|
||||
{
|
||||
$item = \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns('status')
|
||||
->eq('id', $id)
|
||||
->findOne();
|
||||
|
||||
if ($item['status'] == 'unread') {
|
||||
|
||||
\PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('status' => 'read'));
|
||||
|
||||
return 'read';
|
||||
}
|
||||
else {
|
||||
|
||||
\PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $id)
|
||||
->save(array('status' => 'unread'));
|
||||
|
||||
return 'unread';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// Mark all unread items as read
|
||||
function mark_all_as_read()
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('status', 'unread')
|
||||
->save(array('status' => 'read'));
|
||||
}
|
||||
|
||||
// Mark all read items to removed
|
||||
function mark_all_as_removed()
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('status', 'read')
|
||||
->eq('bookmark', 0)
|
||||
->save(array('status' => 'removed', 'content' => ''));
|
||||
}
|
||||
|
||||
// Mark only specified items as read
|
||||
function mark_items_as_read(array $items_id)
|
||||
{
|
||||
\PicoTools\singleton('db')->startTransaction();
|
||||
|
||||
foreach ($items_id as $id) {
|
||||
set_read($id);
|
||||
}
|
||||
|
||||
\PicoTools\singleton('db')->closeTransaction();
|
||||
}
|
||||
|
||||
// Mark all items of a feed as read
|
||||
function mark_feed_as_read($feed_id)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns('items.id')
|
||||
->eq('status', 'unread')
|
||||
->eq('feed_id', $feed_id)
|
||||
->update(array('status' => 'read'));
|
||||
}
|
||||
|
||||
// Mark all read items to removed after X days
|
||||
function autoflush()
|
||||
{
|
||||
$autoflush = \Model\Config\get('autoflush');
|
||||
|
||||
if ($autoflush) {
|
||||
|
||||
\PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('bookmark', 0)
|
||||
->eq('status', 'read')
|
||||
->lt('updated', strtotime('-'.$autoflush.'day'))
|
||||
->save(array('status' => 'removed', 'content' => ''));
|
||||
}
|
||||
}
|
||||
|
||||
// Update all items
|
||||
function update_all($feed_id, array $items, $grabber = false)
|
||||
{
|
||||
$nocontent = (bool) \Model\Config\get('nocontent');
|
||||
|
||||
$items_in_feed = array();
|
||||
$db = \PicoTools\singleton('db');
|
||||
|
||||
$db->startTransaction();
|
||||
|
||||
foreach ($items as $item) {
|
||||
|
||||
// Item parsed correctly?
|
||||
if ($item->id) {
|
||||
|
||||
// Insert only new item
|
||||
if ($db->table('items')->eq('id', $item->id)->count() !== 1) {
|
||||
|
||||
if (! $item->content && ! $nocontent && $grabber) {
|
||||
$item->content = download_content($item->url);
|
||||
}
|
||||
|
||||
$db->table('items')->save(array(
|
||||
'id' => $item->id,
|
||||
'title' => $item->title,
|
||||
'url' => $item->url,
|
||||
'updated' => $item->updated,
|
||||
'author' => $item->author,
|
||||
'content' => $nocontent ? '' : $item->content,
|
||||
'status' => 'unread',
|
||||
'feed_id' => $feed_id
|
||||
));
|
||||
}
|
||||
|
||||
// Items inside this feed
|
||||
$items_in_feed[] = $item->id;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from the database items marked as "removed"
|
||||
// and not present inside the feed
|
||||
if (! empty($items_in_feed)) {
|
||||
|
||||
$removed_items = \PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->columns('id')
|
||||
->notin('id', $items_in_feed)
|
||||
->eq('status', 'removed')
|
||||
->eq('feed_id', $feed_id)
|
||||
->desc('updated')
|
||||
->findAllByColumn('id');
|
||||
|
||||
// Keep a buffer of 2 items
|
||||
// It's workaround for buggy feeds (cache issue with some Wordpress plugins)
|
||||
if (is_array($removed_items)) {
|
||||
|
||||
$items_to_remove = array_slice($removed_items, 2);
|
||||
|
||||
if (! empty($items_to_remove)) {
|
||||
|
||||
\PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->in('id', $items_to_remove)
|
||||
->eq('status', 'removed')
|
||||
->eq('feed_id', $feed_id)
|
||||
->remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$db->closeTransaction();
|
||||
}
|
||||
|
||||
// Download content from an URL
|
||||
function download_content_url($url)
|
||||
{
|
||||
$client = \PicoFeed\Client::create();
|
||||
$client->url = $url;
|
||||
$client->timeout = HTTP_TIMEOUT;
|
||||
$client->user_agent = \Model\Config\HTTP_FAKE_USERAGENT;
|
||||
$client->execute();
|
||||
|
||||
$html = $client->getContent();
|
||||
|
||||
if (! empty($html)) {
|
||||
|
||||
// Try first with PicoFeed grabber and with Readability after
|
||||
$grabber = new \PicoFeed\Grabber($url, $html, $client->getEncoding());
|
||||
$content = '';
|
||||
|
||||
if ($grabber->parse()) {
|
||||
$content = $grabber->content;
|
||||
}
|
||||
|
||||
if (empty($content)) {
|
||||
$content = download_content_readability($grabber->html, $url);
|
||||
}
|
||||
|
||||
// Filter content
|
||||
$filter = new \PicoFeed\Filter($content, $url);
|
||||
return $filter->execute();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// Download content from item ID
|
||||
function download_content_id($item_id)
|
||||
{
|
||||
$item = get($item_id);
|
||||
$content = download_content_url($item['url']);
|
||||
|
||||
if (! empty($content)) {
|
||||
|
||||
if (! \Model\Config\get('nocontent')) {
|
||||
|
||||
// Save content
|
||||
\PicoTools\singleton('db')
|
||||
->table('items')
|
||||
->eq('id', $item['id'])
|
||||
->save(array('content' => $content));
|
||||
}
|
||||
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return array(
|
||||
'result' => true,
|
||||
'content' => $content
|
||||
);
|
||||
}
|
||||
|
||||
\Model\Config\write_debug();
|
||||
|
||||
return array(
|
||||
'result' => false,
|
||||
'content' => ''
|
||||
);
|
||||
}
|
||||
|
||||
// Download content with Readability PHP port
|
||||
function download_content_readability($content, $url)
|
||||
{
|
||||
if (! empty($content)) {
|
||||
|
||||
$readability = new \Readability($content, $url);
|
||||
|
||||
if ($readability->init()) {
|
||||
return $readability->getContent()->innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
57
models/user.php
Normal file
57
models/user.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Model\User;
|
||||
|
||||
require_once 'vendor/SimpleValidator/Validator.php';
|
||||
require_once 'vendor/SimpleValidator/Base.php';
|
||||
require_once 'vendor/SimpleValidator/Validators/Required.php';
|
||||
require_once 'vendor/SimpleValidator/Validators/MaxLength.php';
|
||||
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
// Get a user by username
|
||||
function get($username)
|
||||
{
|
||||
return \PicoTools\singleton('db')
|
||||
->table('config')
|
||||
->columns('username', 'password', 'language')
|
||||
->eq('username', $username)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
// Validate authentication
|
||||
function validate_login(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('username', t('The user name is required')),
|
||||
new Validators\MaxLength('username', t('The maximum length is 50 characters'), 50),
|
||||
new Validators\Required('password', t('The password is required'))
|
||||
));
|
||||
|
||||
$result = $v->execute();
|
||||
$errors = $v->getErrors();
|
||||
|
||||
if ($result) {
|
||||
|
||||
$user = get($values['username']);
|
||||
|
||||
if ($user && \password_verify($values['password'], $user['password'])) {
|
||||
|
||||
unset($user['password']);
|
||||
|
||||
$_SESSION['user'] = $user;
|
||||
$_SESSION['config'] = \Model\Config\get_all();
|
||||
}
|
||||
else {
|
||||
|
||||
$result = false;
|
||||
$errors['login'] = t('Bad username or password');
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
$result,
|
||||
$errors
|
||||
);
|
||||
}
|
@ -30,7 +30,7 @@ function version_15($pdo)
|
||||
|
||||
function version_14($pdo)
|
||||
{
|
||||
$pdo->exec('ALTER TABLE config ADD COLUMN feed_token TEXT DEFAULT "'.\Model\generate_token().'"');
|
||||
$pdo->exec('ALTER TABLE config ADD COLUMN feed_token TEXT DEFAULT "'.\Model\Config\generate_token().'"');
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ function version_13($pdo)
|
||||
|
||||
function version_12($pdo)
|
||||
{
|
||||
$pdo->exec('ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT "'.\Model\generate_token().'"');
|
||||
$pdo->exec('ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT "'.\Model\Config\generate_token().'"');
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user