/** * Award a badge to a user and record some activity * * @param int $BadgeID * @param int $UserID This is the user that should get the award * @param int $InsertUserID This is the user that gave the award * @param string $Reason This is the reason the giver gave with the award */ public function Award($BadgeID, $UserID, $InsertUserID = NULL, $Reason = '') { $Badge = Yaga::BadgeModel()->GetByID($BadgeID); if (!empty($Badge)) { if (!$this->Exists($UserID, $BadgeID)) { $this->SQL->Insert('BadgeAward', array('BadgeID' => $BadgeID, 'UserID' => $UserID, 'InsertUserID' => $InsertUserID, 'Reason' => $Reason, 'DateInserted' => date(DATE_ISO8601))); // Record the points for this badge UserModel::GivePoints($UserID, $Badge->AwardValue, 'Badge'); // Increment the user's badge count $this->SQL->Update('User')->Set('CountBadges', 'CountBadges + 1', FALSE)->Where('UserID', $UserID)->Put(); if (is_null($InsertUserID)) { $InsertUserID = Gdn::Session()->UserID; } // Record some activity $ActivityModel = new ActivityModel(); $Activity = array('ActivityType' => 'BadgeAward', 'ActivityUserID' => $UserID, 'RegardingUserID' => $InsertUserID, 'Photo' => $Badge->Photo, 'RecordType' => 'Badge', 'RecordID' => $BadgeID, 'Route' => '/badges/detail/' . $Badge->BadgeID . '/' . Gdn_Format::Url($Badge->Name), 'HeadlineFormat' => T('Yaga.Badge.EarnedHeadlineFormat'), 'Data' => array('Name' => $Badge->Name), 'Story' => $Badge->Description); // Create a public record $ActivityModel->Queue($Activity, FALSE); // TODO: enable the grouped notifications after issue #1776 is resolved , array('GroupBy' => 'Route')); // Notify the user of the award $Activity['NotifyUserID'] = $UserID; $ActivityModel->Queue($Activity, 'BadgeAward', array('Force' => TRUE)); // Actually save the activity $ActivityModel->SaveQueue(); $this->EventArguments['UserID'] = $UserID; $this->FireEvent('AfterBadgeAward'); } } }
public function Award($Sender, $User, $Criteria) { $Args = $Sender->EventArguments; // Check to see if the submitted action is a target $Prop = 'ActionID_' . $Sender->EventArguments['ActionID']; if (property_exists($Criteria, $Prop)) { $Value = $Criteria->{$Prop}; if ($Value <= 0 || $Value == FALSE) { return FALSE; } } else { return FALSE; } // Get the reaction counts for this parent item $ReactionModel = Yaga::ReactionModel(); $Reactions = $ReactionModel->GetList($Args['ParentID'], $Args['ParentType']); // Squash the dataset into an array $Counts = array(); foreach ($Reactions as $Reaction) { $Counts['ActionID_' . $Reaction->ActionID] = $Reaction->Count; } // Actually check for the reaction counts foreach ($Criteria as $ActionID => $Target) { if ($Counts[$ActionID] < $Target) { return FALSE; } } // The owner should be awarded return $Args['ParentUserID']; }
/** * Retrieves the user's badgelist upon construction of the module object. * * @param string $Sender */ public function __construct($Sender = '') { parent::__construct($Sender); // default to the user object on the controller/the currently logged in user if (property_exists($Sender, 'User') && $Sender->User) { $UserID = $Sender->User->UserID; } else { $UserID = Gdn::Session()->UserID; } if (Gdn::Session()->UserID == $UserID) { $this->Title = T('Yaga.Badges.Mine'); } else { $this->Title = T('Yaga.Badges'); } $BadgeAwardModel = Yaga::BadgeAwardModel(); $this->Data = $BadgeAwardModel->GetByUser($UserID); }
public function Award($Sender, $User, $Criteria) { $UserID = $Sender->EventArguments['UserID']; $Target = $Criteria->Target; $BadgeAwardModel = Yaga::BadgeAwardModel(); $TargetDate = strtotime($Criteria->Duration . ' ' . $Criteria->Period . ' ago'); $Badges = $BadgeAwardModel->GetByUser($UserID); $Types = array(); foreach ($Badges as $Badge) { if (strtotime($Badge['DateInserted']) >= $TargetDate) { $Types[$Badge['RuleClass']] = TRUE; } } if (count($Types) >= $Target) { return $UserID; } else { return FALSE; } }
/** * Get the latest promoted content * * @param int $ID Filter on a specific action ID * @param int $Page What page of content should be shown */ public function Action($ID = NULL, $Page = 0) { if (is_null($ID) || !is_numeric($ID)) { $this->Index($Page); return; } $ActionModel = Yaga::ActionModel(); $Action = $ActionModel->GetByID($ID); if (!$Action) { $this->Index($Page); return; } list($Offset, $Limit) = $this->_TranslatePage($Page); $this->Title(sprintf(T('Yaga.BestContent.Action'), $Action->Name)); $this->_Content = $this->ActedModel->GetAction($ID, $Limit, $Offset); $this->_BuildPager($Offset, $Limit, '/best/action/' . $ID . '/%1$s/'); $this->SetData('ActiveFilter', $ID); $this->Render('index'); }
/** * Renders the reaction record for a specific item * * @param int $ID * @param string $Type 'discussion', 'activity', or 'comment' */ function RenderReactionRecord($ID, $Type) { $Reactions = Yaga::ReactionModel()->GetRecord($ID, $Type); $Limit = C('Yaga.Reactions.RecordLimit'); $ReactionCount = count($Reactions); $i = 0; foreach ($Reactions as $Reaction) { $i++; // Limit the record if there are a lot of reactions if ($i <= $Limit || $Limit <= 0) { $User = Gdn::UserModel()->GetID($Reaction->UserID); $DateTitle = sprintf(T('Yaga.Reactions.RecordFormat'), $User->Name, $Reaction->Name, Gdn_Format::Date($Reaction->DateInserted, '%B %e, %Y')); $String = UserPhoto($User, array('Size' => 'Small', 'title' => $DateTitle)); $String .= '<span class="ReactSprite Reaction-' . $Reaction->ActionID . ' ' . $Reaction->CssClass . '"></span>'; $Wrapttributes = array('class' => 'UserReactionWrap', 'data-userid' => $User->UserID, 'title' => $DateTitle); echo Wrap($String, 'span', $Wrapttributes); } if ($Limit > 0 && $i >= $ReactionCount && $ReactionCount > $Limit) { echo Plural($ReactionCount - $Limit, 'Yaga.Reactions.RecordLimit.Single', 'Yaga.Reactions.RecordLimit.Plural'); } } }
/** * Creates a transport file for easily transferring Yaga configurations across * installs * * @param array An array containing the config areas to transfer * @param string Where to save the transport file * @return mixed False on failure, the path to the transport file on success */ protected function _ExportData($Include = array(), $Path = NULL) { $StartTime = microtime(TRUE); $Info = new stdClass(); $Info->Version = C('Yaga.Version', '?.?'); $Info->StartDate = date('Y-m-d H:i:s'); if (is_null($Path)) { $Path = PATH_UPLOADS . DS . 'export' . date('Y-m-d-His') . '.yaga.zip'; } $FH = new ZipArchive(); $Images = array(); $Hashes = array(); if ($FH->open($Path, ZipArchive::CREATE) !== TRUE) { $this->Form->AddError(sprintf(T('Yaga.Error.ArchiveCreate'), $FH->getStatusString())); return FALSE; } // Add configuration items $Info->Config = 'configs.yaga'; $Configs = Gdn::Config('Yaga', array()); unset($Configs['Version']); $ConfigData = serialize($Configs); $FH->addFromString('configs.yaga', $ConfigData); $Hashes[] = md5($ConfigData); // Add actions if ($Include['Action']) { $Info->Action = 'actions.yaga'; $Actions = Yaga::ActionModel()->Get('Sort', 'asc'); $this->SetData('ActionCount', count($Actions)); $ActionData = serialize($Actions); $FH->addFromString('actions.yaga', $ActionData); $Hashes[] = md5($ActionData); } // Add ranks and associated image if ($Include['Rank']) { $Info->Rank = 'ranks.yaga'; $Ranks = Yaga::RankModel()->Get('Level', 'asc'); $this->SetData('RankCount', count($Ranks)); $RankData = serialize($Ranks); $FH->addFromString('ranks.yaga', $RankData); array_push($Images, C('Yaga.Ranks.Photo'), NULL); $Hashes[] = md5($RankData); } // Add badges and associated images if ($Include['Badge']) { $Info->Badge = 'badges.yaga'; $Badges = Yaga::BadgeModel()->Get(); $this->SetData('BadgeCount', count($Badges)); $BadgeData = serialize($Badges); $FH->addFromString('badges.yaga', $BadgeData); $Hashes[] = md5($BadgeData); foreach ($Badges as $Badge) { array_push($Images, $Badge->Photo); } } // Add in any images $FilteredImages = array_filter($Images); $ImageCount = count($FilteredImages); $this->SetData('ImageCount', $ImageCount); if ($ImageCount > 0) { $FH->addEmptyDir('images'); } foreach ($FilteredImages as $Image) { if ($FH->addFile('.' . $Image, 'images/' . $Image) === FALSE) { $this->Form->AddError(sprintf(T('Yaga.Error.AddFile'), $FH->getStatusString())); //return FALSE; } $Hashes[] = md5_file('.' . $Image); } // Save all the hashes sort($Hashes); $Info->MD5 = md5(implode(',', $Hashes)); $Info->EndDate = date('Y-m-d H:i:s'); $EndTime = microtime(TRUE); $TotalTime = $EndTime - $StartTime; $m = floor($TotalTime / 60); $s = $TotalTime - $m * 60; $Info->ElapsedTime = sprintf('%02d:%02.2f', $m, $s); $FH->setArchiveComment(serialize($Info)); if ($FH->close()) { return $Path; } else { $this->Form->AddError(sprintf(T('Yaga.Error.ArchiveSave'), $FH->getStatusString())); return FALSE; } }
/** * Load up the action list. * * @param string $Sender */ public function __construct($Sender = '') { parent::__construct($Sender); $ActionModel = Yaga::ActionModel(); $this->Data = $ActionModel->Get(); }
/** * Delete all of the Yaga related information for a specific user. * * @param int $UserID The ID of the user to delete. * @param array $Options An array of options: * - DeleteMethod: One of delete, wipe, or NULL * @param array $Data * * @since 1.0 */ protected function DeleteUserData($UserID, $Options = array(), &$Data = NULL) { $SQL = Gdn::SQL(); $DeleteMethod = GetValue('DeleteMethod', $Options, 'delete'); if ($DeleteMethod == 'delete') { // Remove neutral/negative reactions $Actions = Yaga::ActionModel()->GetWhere(array('AwardValue <' => 1))->Result(); foreach ($Actions as $Negative) { Gdn::UserModel()->GetDelete('Reaction', array('InsertUserID' => $UserID, 'ActionID' => $Negative->ActionID), $Data); } } else { if ($DeleteMethod == 'wipe') { // Completely remove reactions Gdn::UserModel()->GetDelete('Reaction', array('InsertUserID' => $UserID), $Data); } else { // Leave reactions } } // Remove the reactions they have received Gdn::UserModel()->GetDelete('Reaction', array('ParentAuthorID' => $UserID), $Data); // Remove their badges Gdn::UserModel()->GetDelete('BadgeAward', array('UserID' => $UserID), $Data); // Blank the user's yaga information $SQL->Update('User')->Set(array('CountBadges' => 0, 'RankID' => NULL, 'RankProgression' => 0))->Where('UserID', $UserID)->Put(); // Trigger a system wide point recount // TODO: Look into point re-calculation }
/** * Sets a users reaction against another user's content. A user can only react * in one way to each unique piece of content. This function makes sure to * enforce this rule * * Events: AfterReactionSave * * @param int $ID * @param string $Type activity, comment, discussion * @param int $AuthorID * @param int $UserID * @param int $ActionID * @return DataSet */ public function Set($ID, $Type, $AuthorID, $UserID, $ActionID) { // clear the cache unset(self::$_Reactions[$Type . $ID]); $EventArgs = array('ParentID' => $ID, 'ParentType' => $Type, 'ParentUserID' => $AuthorID, 'InsertUserID' => $UserID, 'ActionID' => $ActionID); $ActionModel = Yaga::ActionModel(); $NewAction = $ActionModel->GetByID($ActionID); $Points = $Score = $NewAction->AwardValue; $CurrentReaction = $this->GetByUser($ID, $Type, $UserID); if ($CurrentReaction) { $OldAction = $ActionModel->GetByID($CurrentReaction->ActionID); if ($ActionID == $CurrentReaction->ActionID) { // remove the record $Reaction = $this->SQL->Delete('Reaction', array('ParentID' => $ID, 'ParentType' => $Type, 'InsertUserID' => $UserID, 'ActionID' => $ActionID)); $EventArgs['Exists'] = FALSE; $Score = 0; $Points = -1 * $OldAction->AwardValue; } else { // update the record $Reaction = $this->SQL->Update('Reaction')->Set('ActionID', $ActionID)->Set('DateInserted', date(DATE_ISO8601))->Where('ParentID', $ID)->Where('ParentType', $Type)->Where('InsertUserID', $UserID)->Put(); $EventArgs['Exists'] = TRUE; $Points = -1 * ($OldAction->AwardValue - $Points); } } else { // insert a record $Reaction = $this->SQL->Insert('Reaction', array('ActionID' => $ActionID, 'ParentID' => $ID, 'ParentType' => $Type, 'ParentAuthorID' => $AuthorID, 'InsertUserID' => $UserID, 'DateInserted' => date(DATE_ISO8601))); $EventArgs['Exists'] = TRUE; } // Update the parent item score $this->SetUserScore($ID, $Type, $UserID, $Score); // Give the user points commesurate with reaction activity UserModel::GivePoints($AuthorID, $Points, 'Reaction'); $this->FireEvent('AfterReactionSave', $EventArgs); return $Reaction; }
/** * Get a reference to the rank model * @return RankModel */ public static function RankModel() { if (is_null(self::$_RankModel)) { self::$_RankModel = new RankModel(); } return self::$_RankModel; }