HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.
Please upgrade here. These earlier versions are no longer being updated and have security issues.

YAGA Ranks being awarded 1 post later than they should be

I was wondering if someone could help me with a problem I'm experiencing with the way ranks are being awarded on my forums. Each rank is awarded based on post count (well not technically, but I'll explain that in a moment). For example, in order to achieve rank 5 on my forums the user must hit 20 posts, but it isn't until they hit 21 posts that they actually rank up. Here's a screenshot to show I have this setup correctly:

However, I've modified the way post count is calculated based on my specific needs. With the help of a few nice guys here I've created a plugin that hooks into the GDN_User model and manages a new field called "CustomCount". This new field is almost identical to the field "CountComments", the only difference is that it doesn't count posts in a specified discussion. The reason for this is that I have a certain discussion that is intended for spam posts. Obviously this would skew the ranking system if people could just spam posts in this discussion and rank up quickly.

So what I've done is modified the way YAGA calculates post count by replacing "CountComments" with the new field, "CustomCount". Here is all that I've modified:

  1. I've renamed class.postcount.php to class.discountedcount.php
  2. Within this newly named file, on line 10 I've changed class PostCount implements YagaRule to class DiscountedCount implements YagaRule
  3. On line 14 I've changed $CountPosts = $User->CountDiscussions + $User->CountComments; to $CountPosts = $User->CountDiscussions + $User->CustomCount;
  4. On line 75 I've changed return T('Yaga.Rules.PostCount'); to return ('Discounted Post Count');
    1. Within class.rankmodel.php, on line 86 I've changed $Posts = $User->CountDiscussions + $User->CountComments; to $Posts = $User->CountDiscussions + $User->CustomCount;

Is there something I've done wrong? Or maybe something I forgot to modify? It's very strange because it is working with these modifications, just not working properly.

«1

Comments

  • hgtonighthgtonight ∞ · New Moderator

    This is an issue with your modification?

    Does this also happen without the modification?

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @hgtonight I just reverted the two yaga files back to reflect "CountComments" and tested it out. As soon as I hit my 35th post, it ranked up. So the error does not occur without the modification.

    It's odd because I know my plugin is working correctly as I've tested it by posting, then looking at the GDN_User table. Would you like me to add the code from my plugin?

  • hgtonighthgtonight ∞ · New Moderator

    @Skisma said:

    It's odd because I know my plugin is working correctly as I've tested it by posting, then looking at the GDN_User table. Would you like me to add the code from my plugin?

    If you could share your plugin and any modifications to your Yaga install, I might be able to help.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @hgtonight Ok cool. I've listed the only YAGA modifications made above.

    Here is my plugin file:

    <?php if (!defined('APPLICATION')) exit();
    
    $PluginInfo['DisablePostCount'] = array(
        'Name' => 'DisablePostCount',
        'Description' => 'Disables post count in specified discussions.',
        'Version' => '1.0',
        'Author' => "Skisma, Bleistivt",
        'MobileFriendly' => TRUE,
        'SettingsUrl' => '/settings/disablepostcount',
        'SettingsPermission' => 'Garden.Settings.Manage'
    );
    
    class DisablePostCountPlugin extends Gdn_Plugin {
        public function SettingsController_DisablePostCount_Create($Sender) {
            $Sender->Permission('Garden.Settings.Manage');
            $Sender->AddSideMenu('/settings/disablepostcount');
            $Sender->SetData('Title', 'DisablePostCount'.' '.T('Settings'));
            $Conf = new ConfigurationModule($Sender);
            $Conf->Initialize(array(
                'DisablePostCount.IDs' => array(
                    'Control' => 'textbox',
                    'LabelCode' => 'List the DiscussionIDs you wish to disable post count in, comma separated.',
                ))
            );
            $Conf->RenderAll();
        }
        public function Setup() {
            $this->Structure();
        }
        public function Structure() {
            GDN::Structure()->Table('User')
            ->Column('CustomCount', 'int(11)', 0)
            ->Set();
        }   
    
        public function CommentModel_BeforeNotification_Handler($Sender, $Args) {
    
        $ExcludeIDs = array_map('trim', explode(',', C('DisablePostCount.IDs')));
    
    if (!in_array(val('DiscussionID', $Args['Comment']), $ExcludeIDs)) {
    $UserID = val('InsertUserID', $Args['Comment']);
    $Count = Gdn::UserModel()->GetID($UserID)->CustomCount;
    Gdn::UserModel()->SetField($UserID, 'CustomCount', $Count + 1);
    
            }
        }
    
      public function CommentModel_DeleteComment_Handler($Sender, $Args) {
    
        $ExcludeIDs = array_map('trim', explode(',', C('DisablePostCount.IDs')));
    
    if (!in_array(val('DiscussionID', $Args['Comment']), $ExcludeIDs)) {
    $UserID = val('InsertUserID', $Args['Comment']);
    $Count = Gdn::UserModel()->GetID($UserID)->CustomCount;
    Gdn::UserModel()->SetField($UserID, 'CustomCount', $Count - 1);
    
            }
        }
    } 
    
  • hgtonighthgtonight ∞ · New Moderator

    Could you post the entirety of your modified RankModel::GetHighestQualifyingRank()?

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • SkismaSkisma New
    edited May 2015

    @hgtonight

     public function GetHighestQualifyingRank($User) {
            $Points = $User->Points;
            $Posts = $User->CountDiscussions + $User->CustomCount;
            $StartDate = strtotime($User->DateInserted);
    
            $Ranks = $this->Get();
    
            $HighestRank = NULL;
            foreach($Ranks as $Rank) {
              // skip disabled ranks
              if(!$Rank->Enabled) {
                continue;
              }
    
              $TargetDate = time() - $Rank->AgeReq;
              if($Points >= $Rank->PointReq && $Posts >= $Rank->PostReq && $StartDate <= $TargetDate) {
                $HighestRank = $Rank;
              }
              else {
                // Don't continue if we do not qualify
                break;
              }
            }
    
            return $HighestRank;
          }
    
  • hgtonighthgtonight ∞ · New Moderator

    WAIT.

    I know what is happening. Your plugin and Yaga are executing on the same event hook. One is firing before the other and you are expecting a resolution of the other way around.

    Unfortunately, there is no way to pre-empt an application hook with a plugin hook without customizing the bootstrap sequence.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • R_JR_J Ex-Fanboy Munich Admin

    They are fired in alphabetical order. Try to rename your plugin to something beginning with "z"


  • @R_J Ok, I've renamed the file and also have added the z anywhere in the code prior to the word "disable". The file name currently looks like this: class.zdisablepostcount.plugin.php

    I tested this out and it is still doing the same thing. What would be another option? Is it difficult to modify the bootstrap sequence @hgtonight mentioned?

  • R_JR_J Ex-Fanboy Munich Admin

    Try it with an upper case Z, also


  • hgtonighthgtonight ∞ · New Moderator
    edited June 2015

    @R_J said:
    They are fired in alphabetical order. Try to rename your plugin to something beginning with "z"

    This is not true in this case.

    The PHP function get_declared_classes() returns a list of declared classes. This is what is used to register plugin hooks. While the documentation/spec is not clear, the order is based on when the class was declared.

    Since application (and theme) hooks are included via the bootstrap before the plugin manager starts (which eventually registers the plugin hooks), there is no way to preempt an application hook unless you make an application with an alphabetically earlier name.

    You can hook into the Gdn_PluginManager_AfterStart_Handler() and potentially "sort" the order by manually un-registering and re-registering the appropriate class. I do not suggest doing this, but here is an example:

    public function gdn_pluginManager_afterStart_handler($sender) {
        $sender->UnRegisterPlugin('YagaHooks');
        $sender->RegisterPlugin('YagaHooks');
    }
    

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

    R_J
  • R_JR_J Ex-Fanboy Munich Admin

    I was facing the problem twice that a plugin of mine wrote the output "too late" to the screen because another plugin used the same hook. So I renamed the plugin to something starting with a letter that comes earlier in the alphabet then starting letter of the interfering plugin.

    It worked in both cases.


  • hgtonighthgtonight ∞ · New Moderator

    @R_J said:
    I was facing the problem twice that a plugin of mine wrote the output "too late" to the screen because another plugin used the same hook. So I renamed the plugin to something starting with a letter that comes earlier in the alphabet then starting letter of the interfering plugin.

    It worked in both cases.

    Sorry, I should have said "that is not true in this case". I will edit it.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • R_JR_J Ex-Fanboy Munich Admin

    örks! I didn't see you were talking about applications and plugins! I only thought of plugins... :anguished:


  • SkismaSkisma New
    edited June 2015

    @hgtonight said:
    I do not suggest doing this, but here is an example:

        public function gdn_pluginManager_afterStart_handler($sender) {
            $sender->UnRegisterPlugin('YagaHooks');
            $sender->RegisterPlugin('YagaHooks');
    }
    

    I imagine this is could fix the issue I'm having, but cause other problems?

  • hgtonighthgtonight ∞ · New Moderator

    @Skisma said:
    I imagine this is could fix the issue I'm having, but cause other problems?

    Mostly inefficiencies. You are forcing the plugin manager to parse the yaga hooks file twice every request.

    Like I said, I don't suggest you doing it, but it should work.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @hgtonight Ok well I'll add it in and make note of that, just in case. Would I add this to class.rankmodel.php or class.discountedcount.php?

  • @hgtonight After thinking about it for a minute I realized that it made sense to add it to class.discountedcount.php since this is what actually awards the rank to the user. I added the code and tested and it didn't work.

    I then tried adding it to class.rankmodel.php and after testing it, it didn't work either. This, however, isn't the strange thing. After testing this I noticed the text box has now been stretched a bunch. Also there are some other odd changes. This makes no sense to me because I haven't messed with the css at all today. There should be no way that by me modifying some YAGA files, the style has changed. Any ideas what could have happened here?

    You can see what I'm talking about here: http://forgehaven.com/forums/discussion/9/welcome-to-forge-haven#latest

    Here is the textbox

    Here you can see the notifications and a random backslash below the popular tags

  • hgtonighthgtonight ∞ · New Moderator

    That hook I wrote can be placed in any hooks file (plugin, theme hooks, application hooks).

    I am not sure what is causing your weird display issues.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • R_JR_J Ex-Fanboy Munich Admin

    I never knew what was the problem here, but if it has caused because a plugin and YAGA use the same event and the plugin should be executed before YAGA, then it wouldn't make sense to unregister YAGA from the plugin because when the plugin is executed, YAGA has already been there first, nor? O.o:confused:

    What about adding a hook inside YAGA and using that from within the plugin? I cannot imagine that there is a wider use for such a FireEvent so it should be a custom line of code in Skismas installation which has to be maintained on each YAGA update


Sign In or Register to comment.