HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Any example of using the new sort & filter module?

2»

Comments

  • Oh, and for my paranoid sanity, I added a new setting for those cases I do not want possible usage of !filter and other raw entries...

    if(c('Plugins.FilterDiscussion.FilterLock', true)){
      if(!Gdn::request()->get('!filter')){
        return;
      }
    }
    
  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    Funny, we have {userid} in our more current intranet version. I think we did the same for named categories (converting name to its corresponding number).

    I think there's also support for "like", null, and not-null operators.

    Have you noticed the built in hook you can call from another plug-in?

    Being in intranet we weren't concerned about security that much.

  • Yes, I saw the hook thing .... but I am still learning this Vanilla style, and quite could not make heads or tail about it.....yet!

  • charrondevcharrondev Developer Lead (PHP, JS) Montreal Vanilla Staff

    For what it's worth the "weird" styling of function overrides and event hooks is changing as we move forward. We've been leaning pretty heavily on our dependency injection container recently rather than events and hooks.

    We have a bit of documentation here https://docs.vanillaforums.com/developer/framework/dependency-injection/.

    I think the first full piece that we'll have in there will be a fully pluggable text formatting & embed pipeline. This will apply to rich as well as other formats, but I've sidetracked with other things recently instead of finishing it.

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    @charrondev - Please, please, please - don't break backward compatibility

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    @donshakespeare - the plugin hook is pretty simple and the plugin includes an example on how to use it. See this example:

    public function FilterDiscussion_UsingFilter_Handler($Sender, $Args) {
    

    You can put this function in one of your on plugins and the FilterDiscussion plugin will use the filters set by your plugin. Here are the two parameters:

    $Filtersource - the source of the filter: "URL" (the filter came from url parameters), "Default" (default filter saved in the confguration file under Plugins.FilterDiscussion.DefaultFilter)

    $Filter - (array) the actual filter(s).

    Your plugin can change $Filter to any valid filter value. That simple.

    The example hook in th plugin takes the "testfireevent" filter and replaces it with a filter that is supposed to pick all discussions containing "test" in the title which were not created by userid 1. Just an example...

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    @donshakespeare - I just uploaded the latest version from our intranet.

    Another note about security -- the plugin requires FilterDiscussion.View permission so the admin has full control on who can use the plugin. You may have not noticed it if you are the admin;-)

  • Awesome! Going to try it out. Good work!

    P.S

    When I first saw your plugin, I said: byebye Sphinx ....

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    Well, before you say bye bye to anyone -- please consider that performing a filter on a non-indexed column in a large SQL table may have a performance impact. Performing a filter with the LIKE or NOT LIKE operators is even worse.  Thus depending on the size of your forum (the size of the discussion table) and the resources dedicated to your SQL database, using this instead of Sphinx may not be advisable.


    as far as I know Sphinx searches both the Discussion and the Comments tables while this plugin only filters on the Discussion table. Even ignoring the performance differences, the results will be different.

  • ^^ Absolutely agree.

    With your plugin, I am gunning for something similar to what Discourse has done. With Discourse, one is never lost. You can sort, filter etc, it is a sweet ride.

    Before I start hacking the code, what do you think is the feasibility of adding directional sort?

    Something Like /filterdiscussion?CategoryID=NE:32&Type=EQ:Question&CountViews=GT:0&sort=CountViews:asc

    &sort=CountViews:asc tells what column is to be sorted how.



  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    Hi Don,

    I understand and had planned to do this a while ago. I actually did that in my DiscussionAlert plugin - see snipet below:

    // Sort Alerts before the rest
    	public function discussionModel_beforeGet_handler($sender, $args) {
    		Gdn::sql()->orderBy('Alert', 'desc'); //'asc');
    		Gdn::sql()->orderBy('Postitnote', 'desc'); //'asc');
    		Gdn::sql()->orderBy('DateLastComment', 'desc');
    	}
    

    So all you need to do is a little parsing and then appying the orderby clause.

    Unfortunately I am really busy right now, so if you are in a hurry feel free to update the plugin and send me your code - I will integrate it into a new version crediting you (of course) when I get to it.

    Let me know how it goes.

  • charrondevcharrondev Developer Lead (PHP, JS) Montreal Vanilla Staff

    @rbrahmson no intentions of removing any existing events without a lengthy (years long) deprecation period. I don’t think many new events will be added though.

  • @rbrahmson since all I needed was the one-liner you shared, Gdn::sql()->orderBy ..., something that would have cost me at least 34 years to figure out, the rest became a piece of cake.

    Here is what I am suing and it is working quite well (so far ...)

    In the plugin's DiscussionModel_BeforeGet_Handler

    I added this first part to avoid the error of "Not in the Discussion table"

    // elseif ($key == "!msg") {
    //...}		
    elseif ($key == "sort") {
    	if ($Debug) echo '<br>&sort Value :'.$value.'<br>';
    	continue;
    } 
    // elseif (!in_array($key, $Fields)) { //Not in the current table?
    //...}
    

    And then at the tail end of said function

    //get sort param directly from url
    if(Gdn::request()->get('sort')){
    	$sortValue = Gdn::request()->get('sort');
    }
    //get sort param from Saved Filter or other
    elseif((Gdn::request()->get('!filter') || empty(Gdn::request()->get())) && $Urlparms['sort']){
    	$sortValue = $Urlparms['sort'];
    }
    if($sortValue){
    	$defaultOrder = 'desc';
    
    	//example: &sort=CountViews <---single column given, with no order specified
    	if(strpos($sortValue, ':') === false && in_array($sortValue, $Fields)){
    		Gdn::sql()->orderBy($sortValue, $defaultOrder);
    	}
    
    	//example: &sort=CountViews:asc <---single column given, with order specified
    	elseif(strpos($sortValue, ':') !== false && strpos($sortValue, '|') == false){
    		$sortPair = explode(':', $sortValue);
    		Gdn::sql()->orderBy($sortPair[0], $sortPair[1]);
    	}
    
    	//example: &sort=CountViews:asc|CountComments:desc|DateLastComment:desc  <---multiple columns given, must have specified orders
    	elseif(strpos($sortValue, ':') !== false && strpos($sortValue, '|') !== false){
    		$sortPair = explode('|', $sortValue);
    		foreach ($sortPair as $sortP) {
    			if(strpos($sortP, ':') !== false){
        			$newSortPair = explode(':', $sortP);
        			if(in_array($newSortPair[0], $Fields) && ($newSortPair[1] == 'asc' || $newSortPair[1] == 'desc')){
    					Gdn::sql()->orderBy($newSortPair[0], $newSortPair[1]);
    				}
    			}
    		}
    	}
    }
    
    // if ($Titlemsg) {
    //     $Title = $Titlemsg;
    // }
    // Gdn::Controller()->Title($Title);
    // //That's all folks!
    

    I wonder how I can unsticky those pesky announcements, so that they fall in line, this below is too harsh

    // $args['Wheres']['Announce'] = 0;
    

    Did I say already, like twice already before? great plugin!

  • BTW, the above code is for this kind of access

    /filterdiscussion?sort=CountViews:desc


    On another important note @rbrahmson to use Gdn::request()->get() instead of the $_GET is that now you can internally route the url nicely like:

    discussions/filter/([a-z]+)

    ==>

    discussions/FilterDiscussion\?!filter=$1


    If $_GET were in place, the plugin would not be able to get the saved filter name, because it is not present in the requested url in an expected form.


    Cheers!

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    @donshakespeare - In the next few days I will upload the next version that supports sorting from our intranet to github. Please test if you can. You will notice that it is using a different syntax than your code (it is an artifact of how we use the plugin in our intranet).

    What I amnot sure about is your Gdn::request()->get() point. Can you elaborate?

  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭
    edited May 2019

    A new trial version is available in github. Testers and feedback are welcome.

    New features:

    • Ability to sort the filtered discussion list
    • Support for multiple AND conditions on the same column
    • Support for filtering by category and user names (even though their internal database representation is numeric)
    • Revised readme
    • Unit tested with Vanilla 2.8
  • rbrahmsonrbrahmson "You may say I'm a dreamer / But I'm not the only one" NY ✭✭✭

    BTW @donshakespeare - the following does not seem to work:

    // $args['Wheres']['Announce'] = 0;
    

    A peek at the source reveals that Announce(ments) have special treatments ;-(

    Filtering on that fiels through the plugin also fails...

Sign In or Register to comment.