/** * This checks the cache for current rule set that can be triggered for a user * by another user. It loads all rules and selects only those that return true * on its `Interacts()` method. * * @return array Rules that are currently available to use that are interactive. */ public static function GetInteractionRules() { $Rules = Gdn::Cache()->Get('Yaga.Badges.InteractionRules'); if ($Rules === Gdn_Cache::CACHEOP_FAILURE) { $AllRules = RulesController::GetRules(); $TempRules = array(); foreach ($AllRules as $ClassName => $Name) { $Rule = new $ClassName(); if ($Rule->Interacts()) { $TempRules[$ClassName] = $Name; } } if (empty($TempRules)) { $Rules = serialize(FALSE); } else { $Rules = serialize($TempRules); } Gdn::Cache()->Store('Yaga.Badges.InteractionRules', $Rules, array(Gdn_Cache::FEATURE_EXPIRY => C('Yaga.Rules.CacheExpire', 86400))); } return unserialize($Rules); }
/** * Edit an existing badge or add a new one * * @param int $BadgeID * @throws ForbiddenException if no proper rules are found */ public function Edit($BadgeID = NULL) { $this->Permission('Yaga.Badges.Manage'); $this->AddSideMenu('badge/settings'); $this->Form->SetModel($this->BadgeModel); // Only allow editing if some rules exist if (!RulesController::GetRules()) { throw new Gdn_UserException(T('Yaga.Error.NoRules')); } $Edit = FALSE; if ($BadgeID) { $this->Title(T('Yaga.Badge.Edit')); $this->Badge = $this->BadgeModel->GetByID($BadgeID); $this->Form->AddHidden('BadgeID', $BadgeID); $Edit = TRUE; } else { $this->Title(T('Yaga.Badge.Add')); } if ($this->Form->IsPostBack() == FALSE) { if (property_exists($this, 'Badge')) { // Manually merge the criteria into the badge object $Criteria = (array) unserialize($this->Badge->RuleCriteria); $BadgeArray = (array) $this->Badge; $Data = array_merge($BadgeArray, $Criteria); $this->Form->SetData($Data); } } else { // Handle the photo upload $Upload = new Gdn_Upload(); $TmpImage = $Upload->ValidateUpload('PhotoUpload', FALSE); if ($TmpImage) { // Generate the target image name $TargetImage = $Upload->GenerateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Save the uploaded image $Parts = $Upload->SaveAs($TmpImage, 'yaga' . DS . $ImageBaseName); $RelativeUrl = StringBeginsWith($Parts['Url'], Gdn_Url::WebRoot(TRUE), TRUE, TRUE); $this->Form->SetFormValue('Photo', $RelativeUrl); } else { if (!$Edit) { // Use default photo from config if this is a new badge $this->Form->SetFormValue('Photo', C('Yaga.Badges.DefaultPhoto')); } } // Find the rule criteria $FormValues = $this->Form->FormValues(); $Criteria = array(); foreach ($FormValues as $Key => $Value) { if (substr($Key, 0, 7) == '_Rules/') { $RealKey = substr($Key, 7); $Criteria[$RealKey] = $Value; } } // Validate the criteria $RuleClass = new $FormValues['RuleClass'](); $Rule = new $RuleClass(); $Rule->Validate($Criteria, $this->Form); $SerializedCriteria = serialize($Criteria); $this->Form->SetFormValue('RuleCriteria', $SerializedCriteria); if ($this->Form->Save()) { if ($Edit) { $this->InformMessage(T('Yaga.Badge.Updated')); } else { $this->InformMessage(T('Yaga.Badge.Added')); } Redirect('/badge/settings'); } } $this->Render('edit'); }
<?php if (!defined('APPLICATION')) { exit; } /* Copyright 2013 Zachary Doll */ // Gnab the rules so we can render the first criteria form by default $Rules = RulesController::GetRules(); $RuleClass = key($Rules); // Use the defined rule class if we are editing if (property_exists($this, 'Badge')) { $RuleClass = $this->Badge->RuleClass; } $Rule = new $RuleClass(); echo Wrap($this->Title(), 'h1'); echo $this->Form->Open(array('enctype' => 'multipart/form-data', 'class' => 'Badge')); echo $this->Form->Errors(); ?> <ul> <li> <?php echo $this->Form->Label('Photo', 'PhotoUpload'); $Photo = $this->Form->GetValue('Photo'); if ($Photo) { echo Img($Photo); echo '<br />' . Anchor(T('Delete Photo'), CombinePaths(array('badge/deletephoto', $this->Badge->BadgeID, Gdn::Session()->TransientKey())), 'SmallButton Danger PopConfirm'); } echo $this->Form->Input('PhotoUpload', 'file'); ?> </li> <li>
/** * This is the dispatcher to check badge awards * * @param mixed $Sender The sending object * @param string $Handler The event handler to check associated rules for awards * (e.g. BadgeAwardModel_AfterBadgeAward_Handler or Base_AfterConnection) */ private function _AwardBadges($Sender, $Handler) { $Session = Gdn::Session(); if (!C('Yaga.Badges.Enabled') || !$Session->IsValid()) { return; } // Let's us use __FUNCTION__ in the original hook $Hook = str_ireplace('_Handler', '', $Handler); $UserID = $Session->UserID; $User = $Session->User; $BadgeAwardModel = Yaga::BadgeAwardModel(); $Badges = $BadgeAwardModel->GetUnobtained($UserID); $InteractionRules = RulesController::GetInteractionRules(); $Rules = array(); foreach ($Badges as $Badge) { // The badge award needs to be processed if ($Badge->Enabled && $Badge->UserID != $UserID || array_key_exists($Badge->RuleClass, $InteractionRules)) { // Create a rule object if needed $Class = $Badge->RuleClass; if (!in_array($Class, $Rules)) { $Rule = new $Class(); $Rules[$Class] = $Rule; } $Rule = $Rules[$Class]; // Only check awards for rules that use this hook if (in_array($Hook, $Rule->Hooks())) { $Criteria = (object) unserialize($Badge->RuleCriteria); $Result = $Rule->Award($Sender, $User, $Criteria); if ($Result) { if (is_numeric($Result)) { $AwardedUserID = $Result; } else { $AwardedUserID = $UserID; } $BadgeAwardModel->Award($Badge->BadgeID, $AwardedUserID, $UserID); } } } } }