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

[#4] Natural sorting before limiting. #41

Merged
merged 4 commits into from
Mar 24, 2017

Conversation

charger
Copy link

@charger charger commented Mar 21, 2017

No description provided.

@kghbln kghbln requested a review from JeroenDeDauw March 21, 2017 22:08
@kghbln
Copy link
Member

kghbln commented Mar 21, 2017

Thanks for the pull request. I have requested a review by @JeroenDeDauw

Copy link
Member

@JeroenDeDauw JeroenDeDauw left a comment

Choose a reason for hiding this comment

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

Thanks a lot! There are a number of small issues, and tests for the new behavior are missing. If you could address those, that'd be extra awesome. If not, I'll try to poke at them soonish.

@@ -201,6 +219,11 @@ private function getOptions() {

$options['LIMIT'] = (int)$this->options[self::OPT_LIMIT];

$sort_oder = $this->options[self::OPT_SORT_ORDER];
if ($sort_oder != self::NONE) {
$options['ORDER BY'] = "LENGTH(page_title) $sort_oder, page_title $sort_oder";
Copy link
Member

Choose a reason for hiding this comment

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

What is LENGTH(page_title) $sort_oder for?

Copy link
Member

Choose a reason for hiding this comment

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

Is there no way to escape these values? My knowledge of the MW DB stuff is a bit rusty... Having no explicit escaping here makes me uneasy.

Copy link
Author

Choose a reason for hiding this comment

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

This is naive "native sort". It is not so polished as PHP's strnatcmp but works fine in the most cases.

Copy link
Member

Choose a reason for hiding this comment

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

What does that have to do with sorting by the length of the page title? That is what this SQL does in my understanding.

Copy link
Author

Choose a reason for hiding this comment

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

Is there no way to escape these values? My knowledge of the MW DB stuff is a bit rusty... Having no explicit escaping here makes me uneasy.

'desc' or 'asc' is not a value, so escape is not applicable.
Only way to set this attribute- is setter setSortOrder which reject any values except asc or desc,

@@ -45,6 +49,7 @@ public function __construct( DBConnectionProvider $connectionProvider ) {
self::OPT_INCLUDE_REDIRECTS => false,
self::OPT_LIMIT => 500,
self::OPT_OFFSET => 0,
self::OPT_SORT_ORDER => 'asc',
Copy link
Member

Choose a reason for hiding this comment

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

Wrong indent

*/
public function setSortOrder( $sortOrder ) {
if ( $sortOrder != self::DESCENDING && $sortOrder != self::ASCENDING && $sortOrder != self::NONE ) {
throw new InvalidArgumentException( 'Invalid $sortOrder specified' );
Copy link
Member

Choose a reason for hiding this comment

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

Inconsistent indent

const OPT_SORT_ORDER = 'sort';
const ASCENDING = 'asc';
const DESCENDING = 'desc';
const NONE = '';
Copy link
Member

Choose a reason for hiding this comment

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

SORT_ASCENDING

$this->subPageFinder->setLimit( $limit );
$this->subPageFinder->setSortOrder( $sortOrder );
Copy link
Member

Choose a reason for hiding this comment

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

This relies on the constant values matching the user input, which is bad practice

Copy link
Author

Choose a reason for hiding this comment

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

Inside setSortOrder I check that $sortOrder is 'asc' or 'desc'. I think this is secure enough.
What alternative should I use?

Copy link
Member

Choose a reason for hiding this comment

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

It's cool you put in that check - it will make errors more apparent.

The issue here is that there is no abstraction between presentation layer, application logic and data access layer. If that is not clear to you, nvm, I'll take care of it then.

@@ -73,6 +73,7 @@ private function getRenderedList( SubPageList $subPageList, $titleText ) {
'showpage' => new ProcessedParam( 'showpage', true, false ),
'default' => new ProcessedParam( 'default', '', true ),
'limit' => new ProcessedParam( 'limit', 200, true ),
'sort' => new ProcessedParam( 'sort', 'asc', true ),
Copy link
Member

Choose a reason for hiding this comment

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

Not entirely sure why this was added. I don't see why the test would fail without it just by looking at this PR, but then perhaps I'm being blind.

What is definitely the case is that the new behavior is not tested

Copy link
Author

Choose a reason for hiding this comment

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

It caused to error "Undefined index: sort"
I think this is because of mocks.
I'm not so good at PHPUnit.

@charger
Copy link
Author

charger commented Mar 22, 2017

I found a problem with my solution. For example we have subpages:

Releases/1.10
Releases/1.5
Releases/1.2
Releases/1.15
Releases/2.1

<SubPageList/> Without limits uses only PHP sorting and returns:

Releases/1.2
Releases/1.5
Releases/1.10
Releases/1.15
Releases/2.1

<SubPageList sort="desc" limit=3> Uses naive "native sorting" in SQL (length(title) asc, title asc), will returns:

Releases/1.2
Releases/1.5
Releases/2.1 <- here should be 1.10

<SubPageList sort="desc" limit=3> If use plain SQL sorting (title asc), it will get from DB:

Releases/1.10
Releases/1.15
Releases/1.2

and then sort it in PHP:

Releases/1.2
Releases/1.10 <- here should be 1.5
Releases/1.15

This illustrates problem: sorting and limiting must be or in SQL or in PHP, but not be spread. It's hard to implement real native sorting in SQL so

  1. we should remove PHP sorting and use not native "ORDER BY"
  2. Or we should remove LIMIT from SQL and implement it in PHP (this is infective but I doubt is exist WiKi with 100500 subpages)

What do you think, which point I should implement?

@JeroenDeDauw
Copy link
Member

JeroenDeDauw commented Mar 22, 2017

I had a look at the code and found that the situation is not really as simple as I thought. It's not the case that we select some pages from the db and then just sort them. What happens is that they get selected from the db, then manipulated into a tree like data structure which is traversed in TreeListRenderer and has each level individually sorted. From a code architecture level this is kinda weird: why would sorting happen in TreeListRenderer, which is definitely UI code, and not application logic code.

I'd be fine with selecting ALL subpages, if that was just the direct ones. However with indirect ones selected as well, I can imagine having a 100 subages that each have 100 themselves, and then you have a problem. So it seems that doing the sorting in SQL is the only approach that is going to work. I'm fine with removing the PHP sorting if SQL is used instead.

*
* @throws InvalidArgumentException
*/
public function setSortOrder( $sortOrder ) {
Copy link
Member

Choose a reason for hiding this comment

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

Indent is still messed up. This project uses tabs, you seem to be using spaces

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, my Idea IDE was not configured properly. Sorry.

@JeroenDeDauw JeroenDeDauw merged commit ce71289 into ProfessionalWiki:master Mar 24, 2017
@charger charger deleted the sql_nat_sort branch March 24, 2017 09:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants