Overview

Packages

  • None
  • Yaga

Classes

  • ActedModel
  • ActionController
  • ActionModel
  • AwardCombo
  • BadgeAwardModel
  • BadgeController
  • BadgeModel
  • BadgesController
  • BadgesModule
  • BestController
  • BestFilterModule
  • CakeDayPost
  • CommentCount
  • CommentMarathon
  • DiscussionBodyLength
  • DiscussionCategory
  • DiscussionCount
  • DiscussionPageCount
  • HasMentioned
  • HolidayVisit
  • LeaderBoardModule
  • LengthOfService
  • ManualAward
  • NecroPost
  • NewbieComment
  • PhotoExists
  • PostCount
  • PostReactions
  • QnAAnserCount
  • RankController
  • RankModel
  • ReactController
  • ReactionCount
  • ReactionModel
  • ReflexComment
  • RulesController
  • SocialConnection
  • Yaga
  • YagaController
  • YagaHooks

Interfaces

  • YagaRule
  • Overview
  • Package
  • Class
  • Tree
  • Todo
  • Download
  1: <?php if(!defined('APPLICATION')) exit();
  2: /* Copyright 2013-2014 Zachary Doll */
  3: 
  4: /**
  5:  * Describe the user content that has been acted upon
  6:  *
  7:  * Events:
  8:  *
  9:  * @package Yaga
 10:  * @since 1.0
 11:  */
 12: class ActedModel extends Gdn_Model {
 13: 
 14:   /**
 15:    * How long in seconds this table should be cached. Defaults to 10 minutes
 16:    * @var int
 17:    */
 18:   protected $_Expiry = 600;
 19: 
 20:   /**
 21:    * Convenience function to save some typing. Gets the basic 'best' query set
 22:    * up in an SQL driver and returns it
 23:    * @param string $Table Discussion or Comment
 24:    * @return Gdn_SQLDriver
 25:    */
 26:   private function _BaseSQL($Table = 'Discussion') {
 27:     switch($Table) {
 28:       case 'Comment':
 29:         $SQL = Gdn::SQL()->Select('c.*')
 30:                 ->From('Comment c')
 31:                 ->Where('c.Score is not null')
 32:                 ->OrderBy('c.Score', 'DESC');
 33:         break;
 34:       default:
 35:       case 'Discussion':
 36:         $SQL = Gdn::SQL()->Select('d.*')
 37:                 ->From('Discussion d')
 38:                 ->Where('d.Score is not null')
 39:                 ->OrderBy('d.Score', 'DESC');
 40:         break;
 41:     }
 42:     return $SQL;
 43:   }
 44: 
 45:   /**
 46:    * Returns a list of all posts by a specific user that has received at least
 47:    * one of the specified actions.
 48:    * 
 49:    * @param int $UserID
 50:    * @param int $ActionID
 51:    * @param int $Limit
 52:    * @param int $Offset
 53:    * @return array
 54:    */
 55:   public function Get($UserID, $ActionID, $Limit = NULL, $Offset = 0) {
 56:     $CacheKey = "yaga.profile.reactions.{$UserID}.{$ActionID}";
 57:     $Content = Gdn::Cache()->Get($CacheKey);
 58: 
 59:     if($Content == Gdn_Cache::CACHEOP_FAILURE) {
 60: 
 61:       // Get matching Discussions
 62:       $Discussions = $this->_BaseSQL('Discussion')
 63:                       ->Join('Reaction r', 'd.DiscussionID = r.ParentID')
 64:                       ->Where('d.InsertUserID', $UserID)
 65:                       ->Where('r.ActionID', $ActionID)
 66:                       ->Where('r.ParentType', 'discussion')
 67:                       ->OrderBy('r.DateInserted', 'DESC')
 68:                       ->Get()->Result(DATASET_TYPE_ARRAY);
 69: 
 70:       // Get matching Comments
 71:       $Comments = $this->_BaseSQL('Comment')
 72:                       ->Join('Reaction r', 'c.CommentID = r.ParentID')
 73:                       ->Where('c.InsertUserID', $UserID)
 74:                       ->Where('r.ActionID', $ActionID)
 75:                       ->Where('r.ParentType', 'comment')
 76:                       ->OrderBy('r.DateInserted', 'DESC')
 77:                       ->Get()->Result(DATASET_TYPE_ARRAY);
 78: 
 79:       $this->JoinCategory($Comments);
 80: 
 81:       // Interleave
 82:       $Content = $this->Union('DateInserted', array(
 83:           'Discussion' => $Discussions,
 84:           'Comment' => $Comments
 85:       ));
 86:       $this->Prepare($Content);
 87: 
 88:       // Add result to cache
 89:       Gdn::Cache()->Store($CacheKey, $Content, array(
 90:           Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry
 91:       ));
 92:     }
 93: 
 94:     $this->Security($Content);
 95:     $this->Condense($Content, $Limit, $Offset);
 96: 
 97:     return $Content;
 98:   }
 99:   
100:   /**
101:    * Returns a list of all posts of which a specific user has taken the
102:    * specified action.
103:    *
104:    * @param int $UserID
105:    * @param int $ActionID
106:    * @param int $Limit
107:    * @param int $Offset
108:    * @return array
109:    */
110:   public function GetTaken($UserID, $ActionID, $Limit = NULL, $Offset = 0) {
111:     $CacheKey = "yaga.profile.actions.{$UserID}.{$ActionID}";
112:     $Content = Gdn::Cache()->Get($CacheKey);
113: 
114:     if($Content == Gdn_Cache::CACHEOP_FAILURE) {
115: 
116:       // Get matching Discussions
117:       $Discussions = $this->_BaseSQL('Discussion')
118:                       ->Join('Reaction r', 'd.DiscussionID = r.ParentID')
119:                       ->Where('r.InsertUserID', $UserID)
120:                       ->Where('r.ActionID', $ActionID)
121:                       ->Where('r.ParentType', 'discussion')
122:                       ->OrderBy('r.DateInserted', 'DESC')
123:                       ->Get()->Result(DATASET_TYPE_ARRAY);
124: 
125:       // Get matching Comments
126:       $Comments = $this->_BaseSQL('Comment')
127:                       ->Join('Reaction r', 'c.CommentID = r.ParentID')
128:                       ->Where('r.InsertUserID', $UserID)
129:                       ->Where('r.ActionID', $ActionID)
130:                       ->Where('r.ParentType', 'comment')
131:                       ->OrderBy('r.DateInserted', 'DESC')
132:                       ->Get()->Result(DATASET_TYPE_ARRAY);
133: 
134:       $this->JoinCategory($Comments);
135: 
136:       // Interleave
137:       $Content = $this->Union('DateInserted', array(
138:           'Discussion' => $Discussions,
139:           'Comment' => $Comments
140:       ));
141:       $this->Prepare($Content);
142: 
143:       // Add result to cache
144:       Gdn::Cache()->Store($CacheKey, $Content, array(
145:           Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry
146:       ));
147:     }
148: 
149:     $this->Security($Content);
150:     $this->Condense($Content, $Limit, $Offset);
151: 
152:     return $Content;
153:   }
154: 
155:   /**
156:    * Returns a list of all posts that has received at least one of the
157:    * specified actions.
158:    * 
159:    * @param int $ActionID
160:    * @param int $Limit
161:    * @param int $Offset
162:    * @return array
163:    */
164:   public function GetAction($ActionID, $Limit = NULL, $Offset = 0) {
165:     $CacheKey = "yaga.best.actions.{$ActionID}";
166:     $Content = Gdn::Cache()->Get($CacheKey);
167: 
168:     if($Content == Gdn_Cache::CACHEOP_FAILURE) {
169: 
170:       // Get matching Discussions
171:       $Discussions = $this->_BaseSQL('Discussion')
172:                       ->Join('Reaction r', 'd.DiscussionID = r.ParentID')
173:                       ->Where('r.ActionID', $ActionID)
174:                       ->Where('r.ParentType', 'discussion')
175:                       ->OrderBy('r.DateInserted', 'DESC')
176:                       ->Get()->Result(DATASET_TYPE_ARRAY);
177: 
178:       // Get matching Comments
179:       $Comments = $this->_BaseSQL('Comment')
180:                       ->Join('Reaction r', 'c.CommentID = r.ParentID')
181:                       ->Where('r.ActionID', $ActionID)
182:                       ->Where('r.ParentType', 'comment')
183:                       ->OrderBy('r.DateInserted', 'DESC')
184:                       ->Get()->Result(DATASET_TYPE_ARRAY);
185: 
186:       $this->JoinCategory($Comments);
187: 
188:       // Interleave
189:       $Content = $this->Union('DateInserted', array(
190:           'Discussion' => $Discussions,
191:           'Comment' => $Comments
192:       ));
193:       $this->Prepare($Content);
194: 
195:       // Add result to cache
196:       Gdn::Cache()->Store($CacheKey, $Content, array(
197:           Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry
198:       ));
199:     }
200: 
201:     $this->Security($Content);
202:     $this->Condense($Content, $Limit, $Offset);
203: 
204:     return $Content;
205:   }
206: 
207:   /**
208:    * Returns a list of all posts by a specific user ordered by highest score
209:    * 
210:    * @param int $UserID
211:    * @param int $Limit
212:    * @param int $Offset
213:    * @return array
214:    */
215:   public function GetBest($UserID = NULL, $Limit = NULL, $Offset = 0) {
216:     $CacheKey = "yaga.profile.best.{$UserID}";
217:     $Content = Gdn::Cache()->Get($CacheKey);
218: 
219:     if($Content == Gdn_Cache::CACHEOP_FAILURE) {
220:       $SQL = $this->_BaseSQL('Discussion');
221:       if(!is_null($UserID)) {
222:         $SQL = $SQL->Where('d.InsertUserID', $UserID);
223:       }
224:       $Discussions = $SQL->Get()->Result(DATASET_TYPE_ARRAY);
225: 
226:       $SQL = $this->_BaseSQL('Comment');
227:       if(!is_null($UserID)) {
228:         $SQL = $SQL->Where('c.InsertUserID', $UserID);
229:       }
230:       $Comments = $SQL->Get()->Result(DATASET_TYPE_ARRAY);
231: 
232:       $this->JoinCategory($Comments);
233: 
234:       // Interleave
235:       $Content = $this->Union('Score', array(
236:           'Discussion' => $Discussions,
237:           'Comment' => $Comments
238:       ));
239:       $this->Prepare($Content);
240: 
241:       Gdn::Cache()->Store($CacheKey, $Content, array(
242:           Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry
243:       ));
244:     }
245: 
246:     $this->Security($Content);
247:     $this->Condense($Content, $Limit, $Offset);
248: 
249:     return $Content;
250:   }
251: 
252:   /**
253:    * Returns a list of all recent scored posts ordered by highest score
254:    * 
255:    * @param string $Timespan strtotime compatible time
256:    * @param int $Limit
257:    * @param int $Offset
258:    * @return array
259:    */
260:   public function GetRecent($Timespan = 'week', $Limit = NULL, $Offset = 0) {
261:     $CacheKey = "yaga.best.last.{$Timespan}";
262:     $Content = Gdn::Cache()->Get($CacheKey);
263: 
264:     if($Content == Gdn_Cache::CACHEOP_FAILURE) {
265:       $TargetDate = date('Y-m-d H:i:s', strtotime("1 {$Timespan} ago"));
266: 
267:       $SQL = $this->_BaseSQL('Discussion');
268:       $Discussions = $SQL->Where('d.DateUpdated >', $TargetDate)->Get()->Result(DATASET_TYPE_ARRAY);
269: 
270:       $SQL = $this->_BaseSQL('Comment');
271:       $Comments = $SQL->Where('c.DateUpdated >', $TargetDate)->Get()->Result(DATASET_TYPE_ARRAY);
272: 
273:       $this->JoinCategory($Comments);
274: 
275:       // Interleave
276:       $Content = $this->Union('Score', array(
277:           'Discussion' => $Discussions,
278:           'Comment' => $Comments
279:       ));
280:       $this->Prepare($Content);
281: 
282:       Gdn::Cache()->Store($CacheKey, $Content, array(
283:           Gdn_Cache::FEATURE_EXPIRY => $this->_Expiry
284:       ));
285:     }
286: 
287:     $this->Security($Content);
288:     $this->Condense($Content, $Limit, $Offset);
289: 
290:     return $Content;
291:   }
292: 
293:   /**
294:    * Attach CategoryID to Comments
295:    *
296:    * @param array $Comments
297:    */
298:   protected function JoinCategory(&$Comments) {
299:     $DiscussionIDs = array();
300: 
301:     foreach($Comments as &$Comment) {
302:       $DiscussionIDs[$Comment['DiscussionID']] = TRUE;
303:     }
304:     $DiscussionIDs = array_keys($DiscussionIDs);
305: 
306:     $Discussions = Gdn::SQL()->Select('d.*')
307:                     ->From('Discussion d')
308:                     ->WhereIn('DiscussionID', $DiscussionIDs)
309:                     ->Get()->Result(DATASET_TYPE_ARRAY);
310: 
311:     $DiscussionsByID = array();
312:     foreach($Discussions as $Discussion) {
313:       $DiscussionsByID[$Discussion['DiscussionID']] = $Discussion;
314:     }
315:     unset($Discussions);
316: 
317:     foreach($Comments as &$Comment) {
318:       $Comment['Discussion'] = $DiscussionsByID[$Comment['DiscussionID']];
319:       $Comment['CategoryID'] = GetValueR('Discussion.CategoryID', $Comment);
320:     }
321:   }
322: 
323:   /**
324:    * Interleave two or more result arrays by a common field
325:    *
326:    * @param string $Field
327:    * @param array $Sections Array of result arrays
328:    * @return array
329:    */
330:   protected function Union($Field, $Sections) {
331:     if(!is_array($Sections))
332:       return;
333: 
334:     $Interleaved = array();
335:     foreach($Sections as $SectionType => $Section) {
336:       if(!is_array($Section))
337:         continue;
338: 
339:       foreach($Section as $Item) {
340:         $ItemField = GetValue($Field, $Item);
341:         $Interleaved[$ItemField] = array_merge($Item, array('ItemType' => $SectionType));
342: 
343:         ksort($Interleaved);
344:       }
345:     }
346: 
347:     $Interleaved = array_reverse($Interleaved);
348:     return $Interleaved;
349:   }
350: 
351:   /**
352:    * Pre-process content into a uniform format for output
353:    *
354:    * @param Array $Content By reference
355:    */
356:   protected function Prepare(&$Content) {
357: 
358:     foreach($Content as &$ContentItem) {
359:       $ContentType = GetValue('ItemType', $ContentItem);
360: 
361:       $Replacement = array();
362:       $Fields = array('DiscussionID', 'CategoryID', 'DateInserted', 'DateUpdated', 'InsertUserID', 'Body', 'Format', 'ItemType');
363: 
364:       switch(strtolower($ContentType)) {
365:         case 'comment':
366:           $Fields = array_merge($Fields, array('CommentID'));
367: 
368:           // Comment specific
369:           $Replacement['Name'] = GetValueR('Discussion.Name', $ContentItem);
370:           break;
371: 
372:         case 'discussion':
373:           $Fields = array_merge($Fields, array('Name', 'Type'));
374:           break;
375:       }
376: 
377:       $Fields = array_fill_keys($Fields, TRUE);
378:       $Common = array_intersect_key($ContentItem, $Fields);
379:       $Replacement = array_merge($Replacement, $Common);
380:       $ContentItem = $Replacement;
381: 
382:       // Attach User
383:       $UserID = GetValue('InsertUserID', $ContentItem);
384:       $User = Gdn::UserModel()->GetID($UserID);
385:       $ContentItem['Author'] = $User;
386:     }
387:   }
388: 
389:   /**
390:    * Strip out content that this user is not allowed to see
391:    *
392:    * @param array $Content Content array, by reference
393:    */
394:   protected function Security(&$Content) {
395:     if(!is_array($Content))
396:       return;
397:     $Content = array_filter($Content, array($this, 'SecurityFilter'));
398:   }
399: 
400:   /**
401:    * Checks the view permission on an item
402:    * 
403:    * @param array $ContentItem
404:    * @return boolean Whether or not the user can see the content item
405:    */
406:   protected function SecurityFilter($ContentItem) {
407:     $CategoryID = GetValue('CategoryID', $ContentItem, NULL);
408:     if(is_null($CategoryID) || $CategoryID === FALSE) {
409:       return FALSE;
410:     }
411: 
412:     $Category = CategoryModel::Categories($CategoryID);
413:     $CanView = GetValue('PermsDiscussionsView', $Category);
414:     if(!$CanView) {
415:       return FALSE;
416:     }
417: 
418:     return TRUE;
419:   }
420: 
421:   /**
422:    * Condense an interleaved content list down to the required size
423:    *
424:    * @param array $Content
425:    * @param int $Limit
426:    * @param int $Offset
427:    */
428:   protected function Condense(&$Content, $Limit, $Offset) {
429:     $Content = array_slice($Content, $Offset, $Limit);
430:   }
431: 
432: }
433: 
Yaga API documentation generated by ApiGen 2.8.0