Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make selfoss navigable #869

Merged
merged 35 commits into from
Feb 12, 2017
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e976397
make it possible to request specific extra items in item list
niol Dec 22, 2016
f9db3dc
ensure read items are counted for loading more items (fix #774)
niol Dec 22, 2016
ddefcad
make selfoss navigable (#243)
niol Dec 22, 2016
116932a
fix loosing tag or source filtering on mobile
niol Dec 23, 2016
41eabb8
workaround firefox different handling of hash decoding for unicode tags
niol Dec 29, 2016
d832d80
assume the hash is encoded to handle tags with % sign in hash
niol Dec 29, 2016
5427a2f
use seek pagination instead of offset
niol Jan 2, 2017
c12c424
ensure entry requested in location.hash is shown
niol Jan 2, 2017
f481955
open source nav if source requested in location.hash
niol Jan 2, 2017
a50092e
fix seek pagination on smartphone when last entry was marked read
niol Jan 3, 2017
0ccbb01
fix clicking the entry source to get to source listing
niol Jan 3, 2017
3e25460
ensure .stream-error message events are set even on first load
niol Jan 3, 2017
2360e3f
fix ‘Refresh this source’ button inserted also to subsequent pages (#…
niol Jan 3, 2017
a5f6c93
prevent unwanted scrolling to selected entry on stream more
niol Jan 6, 2017
26dc95a
prevent selected entry from being requested again upon stream more
niol Jan 15, 2017
667b061
ensure hash is processed after changing hash programmatically
niol Jan 15, 2017
96c6020
fix tag with % js failure
niol Feb 6, 2017
4b45e9f
Fix broken sqlite
jtojnar Feb 5, 2017
fbbd653
fix settings not reachable
niol Feb 6, 2017
79b46a6
fix cannot come back from setting (JS failure)
niol Feb 6, 2017
1242a83
fix cannot got from setting to tag or source
niol Feb 6, 2017
4f403f0
fix lost tag or source when coming back from settings
niol Feb 6, 2017
d522eac
show error upon invalid tag, source id, section or subsection
niol Feb 6, 2017
04cf4f5
fix highlight 'all tags' when hitting 'back' after visiting a tag
niol Feb 7, 2017
83ca0e6
fix seek pagination with sqlite
niol Feb 7, 2017
c330f1b
fix update location hash when using keyboard shortcuts
niol Feb 8, 2017
3c42506
fix r shortcut
niol Feb 8, 2017
b877487
fix hash not updated on reload when an entry has been opened before
niol Feb 8, 2017
9733f88
fix item id in url useless and back/forward after shortcuts
niol Feb 8, 2017
27a1cc0
fix double mark on mobile
niol Feb 9, 2017
1ba3eac
prevent mixing seek and offset pagination
niol Feb 10, 2017
74f0cdb
fix extra_ids not being SELECTed if out of seek pagination or LIMIT
niol Feb 10, 2017
8e6b807
add comment explaining the specific query when explictely requesting ids
niol Feb 10, 2017
8bd3265
fix order by desc ordering of items
niol Feb 10, 2017
53283b1
fix selfoss.filter.type not set from the hash
niol Feb 12, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions controllers/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,19 @@ public function home() {
$options = array();
if (\F3::get('homepage')!='')
$options = array( 'type' => \F3::get('homepage') );

// use ajax given params?
if(count($_GET)>0)
$options = $_GET;


if(!isset($options['ajax'])) {
// show as full html page
$this->view->publicMode = \F3::get('auth')->isLoggedin()!==true && \F3::get('public')==1;
$this->view->loggedin = \F3::get('auth')->isLoggedin()===true;
echo $this->view->render('templates/home.phtml');
return;
}

// get search param
if(isset($options['search']) && strlen($options['search'])>0)
$this->view->search = $options['search'];
Expand Down Expand Up @@ -81,11 +89,6 @@ public function home() {
"sources" => $this->view->sources
));
}

// show as full html page
$this->view->publicMode = \F3::get('auth')->isLoggedin()!==true && \F3::get('public')==1;
$this->view->loggedin = \F3::get('auth')->isLoggedin()===true;
echo $this->view->render('templates/home.phtml');
}


Expand Down Expand Up @@ -230,7 +233,10 @@ private function loadItems($options, $tags) {
|| $_SERVER['REMOTE_ADDR'] === $_SERVER['SERVER_ADDR']
|| $_SERVER['REMOTE_ADDR'] === "127.0.0.1"
|| \F3::get('auth')->isLoggedin() == 1;
if ($options['source'] && $canUpdate) {
$firstPage = $options['offset'] == 0
&& $options['offset_from_id'] == ''
&& $options['offset_from_datetime'] == '';
if ($options['source'] && $canUpdate && $firstPage) {
$itemsHtml = '<button type="button" id="refresh-source" class="refresh-source">' . \F3::get('lang_source_refresh') . '</button>';
}

Expand Down
76 changes: 60 additions & 16 deletions daos/mysql/Items.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,16 @@ public function cleanup(\DateTime $date = NULL) {
*/
public function get($options = array()) {
$params = array();
$where = '';
$where = array($this->stmt->bool(true));
$order = 'DESC';

// only starred
if(isset($options['type']) && $options['type']=='starred')
$where .= ' AND '.$this->stmt->isTrue('starred');
$where[] = $this->stmt->isTrue('starred');

// only unread
else if(isset($options['type']) && $options['type']=='unread'){
$where .= ' AND '.$this->stmt->isTrue('unread');
$where[] = $this->stmt->isTrue('unread');
if(\F3::get('unread_order')=='asc'){
$order = 'ASC';
}
Expand All @@ -212,30 +212,74 @@ public function get($options = array()) {
if(isset($options['search']) && strlen($options['search'])>0) {
$search = implode('%', \helpers\Search::splitTerms($options['search']));
$params[':search'] = $params[':search2'] = $params[':search3'] = array("%".$search."%", \PDO::PARAM_STR);
$where .= ' AND (items.title LIKE :search OR items.content LIKE :search2 OR sources.title LIKE :search3) ';
$where[] = '(items.title LIKE :search OR items.content LIKE :search2 OR sources.title LIKE :search3) ';
}

// tag filter
if(isset($options['tag']) && strlen($options['tag'])>0) {
$params[':tag'] = array( "%,".$options['tag'].",%" , \PDO::PARAM_STR );
if ( \F3::get( 'db_type' ) == 'mysql' ) {
$where .= " AND ( CONCAT( ',' , sources.tags , ',' ) LIKE _utf8mb4 :tag COLLATE utf8mb4_general_ci ) ";
} else {
$where .= " AND ( (',' || sources.tags || ',') LIKE :tag ) ";
}
$params[':tag'] = $options['tag'];
$where[] = "items.source=sources.id";
$where[] = $this->stmt->csvRowMatches('sources.tags', ':tag');
}
// source filter
elseif(isset($options['source']) && strlen($options['source'])>0) {
$params[':source'] = array($options['source'], \PDO::PARAM_INT);
$where .= " AND items.source=:source ";
$where[] = "items.source=:source ";
}

// update time filter
if(isset($options['updatedsince']) && strlen($options['updatedsince'])>0) {
$params[':updatedsince'] = array($options['updatedsince'], \PDO::PARAM_STR);
$where .= " AND items.updatetime > :updatedsince ";
$where[] = "items.updatetime > :updatedsince ";
}

// seek pagination (alternative to offset)
if( isset($options['offset_from_datetime'])
&& strlen($options['offset_from_datetime']) > 0
&& isset($options['offset_from_id'])
&& is_numeric($options['offset_from_id']) ) {

$offset_from_datetime_sql = $this->stmt->datetime($options['offset_from_datetime']);
$params[':offset_from_datetime'] = array(
$offset_from_datetime_sql, \PDO::PARAM_STR
);
$params[':offset_from_datetime2'] = array(
$offset_from_datetime_sql, \PDO::PARAM_STR
);
$params[':offset_from_id'] = array(
$options['offset_from_id'], \PDO::PARAM_INT
);
$ltgt = null;
if( $order == 'ASC' )
$ltgt = '>';
else
$ltgt = '<';

// Because of sqlite lack of tuple comparison support, we use a
// more complicated condition.
$where[] = "(items.datetime $ltgt :offset_from_datetime OR
(items.datetime = :offset_from_datetime2 AND
items.id $ltgt :offset_from_id)
)";
}

$where_ids = '';
// extra ids to include in stream
if( isset($options['extra_ids'])
&& count($options['extra_ids']) > 0
// limit the query to a sensible max
&& count($options['extra_ids']) <= \F3::get('items_perpage') ) {

$extra_ids_stmt = $this->stmt->intRowMatches('items.id',
$options['extra_ids']);
if( !is_null($extra_ids_stmt) )
$where_ids = $extra_ids_stmt;
}

// finalize items filter
$where_sql = implode(' AND ', $where);
if( $where_ids != '' ) $where_sql = "(($where_sql) OR $where_ids)";

// set limit
if(!is_numeric($options['items']) || $options['items']>200)
$options['items'] = \F3::get('items_perpage');
Expand All @@ -247,16 +291,16 @@ public function get($options = array()) {
// first check whether more items are available
$result = \F3::get('db')->exec('SELECT items.id
FROM '.\F3::get('db_prefix').'items AS items, '.\F3::get('db_prefix').'sources AS sources
WHERE items.source=sources.id '.$where.'
WHERE items.source=sources.id AND '.$where_sql.'
LIMIT 1 OFFSET ' . ($options['offset']+$options['items']), $params);
$this->hasMore = count($result);

// get items from database
return \F3::get('db')->exec('SELECT
return \F3::get('db')->exec('SELECT
items.id, datetime, items.title AS title, content, unread, starred, source, thumbnail, icon, uid, link, updatetime, author, sources.title as sourcetitle, sources.tags as tags
FROM '.\F3::get('db_prefix').'items AS items, '.\F3::get('db_prefix').'sources AS sources
WHERE items.source=sources.id '.$where.'
ORDER BY items.datetime '.$order.'
WHERE items.source=sources.id AND '.$where_sql.'
ORDER BY items.datetime '.$order.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually they are only ordered by datetime, this should be also ordered by id for seek pagination to work properly.

LIMIT ' . $options['items'] . ' OFFSET '. $options['offset'], $params);
}

Expand Down
47 changes: 47 additions & 0 deletions daos/mysql/Statements.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,51 @@ public static function csvRowMatches($column, $value) {

return "CONCAT(',', $column, ',') LIKE CONCAT('%,', $value, ',%') COLLATE utf8mb4_general_ci";
}

/**
* check column against int list.
*
* @param int column to check
* @param array of string or int values to match column against
* @return full statement
*/
public static function intRowMatches($column, $ints) {
// checks types
if( !is_array($ints) && sizeof($ints) < 1 ) return null;
$all_ints = array();
foreach( $ints as $ints_str ) {
$i = (int)$ints_str;
if( $i > 0 ) $all_ints[] = $i;
}

if( sizeof($all_ints) > 0 ) {
$comma_ints = implode(',', $all_ints);
return $column." IN ($comma_ints)";
}

return null;
}

/**
* Convert boolean into a representation recognized by the database engine.
*
* @return string representation of boolean
*/
public static function bool($bool) {
return $bool ? 'TRUE' : 'FALSE';
}


/**
* Convert a date string into a representation suitable for comparison by
* the database engine.
*
* @param datestr ISO8601 datetime
* @return string representation of datetime
*/
public static function datetime($datestr) {
return $datestr; // mysql supports ISO8601 datetime comparisons
}


}
24 changes: 24 additions & 0 deletions daos/sqlite/Statements.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,28 @@ public static function insert($query, $params) {
public static function csvRowMatches($column, $value) {
return "(',' || $column || ',') LIKE ('%,' || $value || ',%')";
}

/**
* Convert boolean into a representation recognized by the database engine.
*
* @return string representation of boolean
*/
public static function bool($bool) {
return $bool ? '1' : '0';
}


/**
* Convert a date string into a representation suitable for comparison by
* the database engine.
*
* @param datestr ISO8601 datetime
* @return string representation of datetime
*/
public static function datetime($datestr) {
$date = new \DateTime($datestr);
return $date->format('Y-m-d H:i:s');
}


}
1 change: 1 addition & 0 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
'public/js/jquery.hotkeys.js',
'public/js/selfoss-base.js',
'public/js/selfoss-shares.js',
'public/js/selfoss-db.js',
'public/js/selfoss-events.js',
'public/js/selfoss-events-navigation.js',
'public/js/selfoss-events-search.js',
Expand Down
Loading