Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.
Help with new 'DiscussionWordMention' custom rule
AaronWebstey
✭✭✭
I'm developing a simple custom YAGA rule - partially to entertain my users, and mostly to help learn the ins and outs of YAGA and Vanilla in general. I can successfully assign this rule to a badge (see ridiculous attachment), but when I can't seem to get the badge to auto-award when someone has the specified word in a discussion/comment. Can anyone see anything obvious I'm doing wrong (probably @hgtonight :S )?
<?php if(!defined('APPLICATION')) exit(); /** * This rule awards badges if a discussion body contains a given string * * @author Aaron Webstey * @since 1.0 * @package Yaga */ class DiscussionWordMention implements YagaRule{ public function Award($Sender, $User, $Criteria) { $Discussion = $Sender->EventArguments['Discussion']; $Comment = $Sender->EventArguments['Comment']; $Pos1 = strpos($Discussion->Body, $Criteria->WordToMatch); $Pos2 = strpos($Comment->Body, $Criteria->WordToMatch); if( ($Pos1 !== false) || ($Pos2 !== false) ) { return $Discussion->InsertUserID; } else { return FALSE; } } public function Form($Form) { $String = $Form->Label('Yaga.Rules.DiscussionWordMention.Criteria.Head', 'DiscussionWordMention'); $String .= $Form->Textbox('WordToMatch', array('class' => 'WideInput')); return $String; } public function Validate($Criteria, $Form) { $Validation = new Gdn_Validation(); $Validation->ApplyRules(array( array( 'Name' => 'WordToMatch', 'Validation' => array('Required') ) )); $Validation->Validate($Criteria); $Form->SetValidationResults($Validation->Results()); } public function Hooks() { return array('CommentModel_BeforeNotification'); } public function Description() { $Description = sprintf(T('Yaga.Rules.DiscussionWordMention.Desc'), C('Vanilla.Comment.MaxLength')); return Wrap($Description, 'div', array('class' => 'InfoMessage')); } public function Name() { return T('Yaga.Rules.DiscussionWordMention'); } public function Interacts() { return FALSE; } }
0
Comments
Oh, and obviously I've got the locale stuff set up properly (I think).
I would use
return array('CommentModel_AfterSaveComment', 'DiscussionModel_AfterSaveDiscussion');
for function Hooks so that you access the comment/discussion body as "early" as possible.You've been using an event that (I'd guess) is only fired when someone is mentioned in a comment. So your award would only be granted if you put "Eggselent work, @AaronWebstey!" in a comment.
function Award never returns the
$Comment->InsertUserID
. I'd suggestBut I'm not sure if this will work. Since this will be fired for each discussion and comment save. Maybe you have to check for the controller, too. @hgtonight will know that... I'd try something with
your problem is the Name underneath the photo needs to be "WordToMatch"
based on your code.
and also what r_j suggested.
you need to make sure test for Discussion and Comment
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
this needs to be WordToMatch instead of Eggselent.
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
Thanks for the help, @R_J ! I have implemented your suggestions, and no dice I get the hooks and the strtolower (duh, I should have thought of that), but I'm not sure why the ID never would have been returned by my code (it returns if either strpos was not false, I thought). Anyway, that's not important and I appreciate the help!!
I haven't tried the ControllerName bit, because I figured that can only exclude possible cases where it would be awarded. If I get it working and need to add in that bit (or if I'm wrong about this), I'll give it a shot.
Thanks again very much! Still picking through the other rules looking for ideas but if anyone has a suggestion I'll be very appreciative.
Maybe you haven't seen peregrines comments?
If I understand the inner guts of such a custom rule right, your Award function will be called on every hook (I've recommended AfterSave):
a) when a discussion is created
b) when a comment is created
So you would have to make sure that when a comment is created, there is no second reward for the discussion.
Also the hook is called
c) when a discussion is edited
d) when a comment is edited
In that cases, you wouldn't like to award someone a second time. I do not know a way to achieve that...
I guess he didn't believe me...
You can only get awarded a badge once I believe, same with PeregrineBadges
see comment - http://vanillaforums.org/discussion/comment/221756/#Comment_221756
and here is the code...
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
Yes my apologies @R_J and @peregrine ; I had not seen his comment before I posted my reply. THen I was writing another reply, and you replied again already! Thanks, I'll try that code
the odd thing is many people don't refresh their browser or click on discussions after they post.
same thing with conversations - they just wait for a notification to pop up instead of refreshing.
saves alot of time and keeps you up to date.
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
I wish I could double-awesome @peregrine 's post. Curse you for being better than me/bless you for helping!! Well OK, just the latter. I just can't wait until I've had enough time to know how to do this stuff myself without running for help.
Thanks very, very much to @peregrine and @R_J !!! Oh and @hgtonight FYI, peregrine has made this into a working rule (as minimally tested by me).
edit. rescinded so as not confuse issue then.
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
Actually, I named the badge 'Eggsellent', and left your code as you posted it:
Eggsellent.
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
Yeah, I think $Criteria->WordToMatch gives the value of the WordToMatch input on the badge config page (which is labeled 'Mentioned a word?' in my original screenshot).
Sweet rule man!
I am working on Yaga 1.1 atm which will make distribution of Custom Rules with a plugin much easier so it is great to see some new rules .
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.
I was mislead by the Award Value in the screenshot
Very nice idea to simply use FormPostValues!
@AaronWebstey welcome at the joyful world of Vanilla coding
Thanks again to everyone! You are all Eggsellent.
@hgtonight I just tested the new hook, works great!
For people who are interested, you can include a new rule from a plugin like so:
(will only work with the Yaga master branch as of now)
My themes: pure | minusbaseline - My plugins: CSSedit | HTMLedit | InfiniteScroll | BirthdayModule | [all] - PM me about customizations
VanillaSkins.com - Plugins, Themes and Graphics for Vanillaforums OS
Great to get external verification.
I just want to note that you shouldn't have to include the file directly. Assuming you know the class name, and it's file matches the auto loader requirements, you can just instantiate it in that class since the plugin folder is automatically added to the search path.
Great sample of things to come!
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.