PageRenderTime 191ms CodeModel.GetById 49ms RepoModel.GetById 0ms app.codeStats 0ms

/app/Article.php

https://gitlab.com/forby/Trace
PHP | 358 lines | 193 code | 50 blank | 115 comment | 7 complexity | 6fdbededc33b03c99a76d8ecfa0d1580 MD5 | raw file
  1. <?php namespace App;
  2. use Auth;
  3. use App\Article;
  4. use Carbon\Carbon;
  5. use Conner\Likeable\LikeableTrait;
  6. use Illuminate\Database\Eloquent\Model;
  7. use Illuminate\Database\Eloquent\SoftDeletes;
  8. use AlgoliaSearch\Laravel\AlgoliaEloquentTrait;
  9. use Cviebrock\EloquentSluggable\SluggableTrait;
  10. use Cviebrock\EloquentSluggable\SluggableInterface;
  11. class Article extends Model implements SluggableInterface {
  12. use LikeableTrait, SluggableTrait, SoftDeletes, AlgoliaEloquentTrait;
  13. protected $fillable =
  14. [
  15. 'title',
  16. 'overview',
  17. 'example',
  18. 'advice',
  19. 'published',
  20. 'featured',
  21. 'user_id',
  22. 'category_id'
  23. ];
  24. protected $sluggable = array(
  25. 'build_from' => 'title',
  26. 'save_to' => 'slug',
  27. 'on_update' => true
  28. );
  29. /**
  30. * Make sure these return as dates
  31. * @var array
  32. */
  33. protected $dates = ['deleted_at'];
  34. /**
  35. * Attributes for Algolia Search
  36. *
  37. * @var array
  38. */
  39. public $algoliaSettings = [
  40. 'attributesToIndex' => [
  41. 'username',
  42. 'title',
  43. 'overview',
  44. 'example',
  45. 'advice'
  46. ]
  47. ];
  48. public function getAlgoliaRecord()
  49. {
  50. // Inject username into search record
  51. return array_merge($this->toArray(), [
  52. 'username' => $this->user->name,
  53. 'url' => '/article/' . $this->slug
  54. ]);
  55. }
  56. /**
  57. * User relationship
  58. * One user can have many articles
  59. */
  60. public function user()
  61. {
  62. return $this->belongsTo('App\User')->withTrashed();
  63. }
  64. /**
  65. * Category relationship
  66. * One category can have many articles
  67. */
  68. public function category()
  69. {
  70. return $this->belongsTo('App\Category');
  71. }
  72. /**
  73. * Tag relationship
  74. * Tags and articles can have many of each other
  75. */
  76. public function tags()
  77. {
  78. return $this->belongsToMany('App\Tag')->withTimestamps();
  79. }
  80. /**
  81. * Comment relationship
  82. * Articles can have many comments
  83. */
  84. public function comments()
  85. {
  86. // Order the comments with most recent
  87. return $this->hasMany('App\Comment')->orderBy('created_at', 'DESC');
  88. }
  89. /**
  90. * Get class for article if it's a draft
  91. */
  92. public function getDraftClassAttribute()
  93. {
  94. if ( ! $this->published ) {
  95. return ' draft';
  96. }
  97. return '';
  98. }
  99. /**
  100. * Get amount of comments this article has
  101. */
  102. public function getCommentCountAttribute()
  103. {
  104. return $this->comments()->count();
  105. }
  106. /**
  107. * Get the popularity count for the article
  108. * Based on count of bumps and comments
  109. */
  110. public function getPopularityAttribute()
  111. {
  112. return $this->comment_count + $this->likeCount;
  113. }
  114. /**
  115. * Has this article been featured?
  116. */
  117. public function getWasFeaturedAttribute()
  118. {
  119. return ( $this->featured_on !== '0000-00-00 00:00:00' );
  120. }
  121. /**
  122. * Get all classes related to the feature status
  123. */
  124. public function getFeatureClassesAttribute()
  125. {
  126. $classes = ['star'];
  127. if ( $this->wasFeatured ) {
  128. array_push( $classes, 'hasbeen');
  129. }
  130. if ( $this->featured ) {
  131. array_push( $classes, 'featured');
  132. } else {
  133. array_push( $classes, 'unfeatured');
  134. }
  135. return implode(' ', $classes);
  136. }
  137. /**
  138. * Set this article as featured
  139. */
  140. public function feature()
  141. {
  142. // set featured attribute
  143. $this->featured = true;
  144. // set the featured date
  145. $this->featured_on = Carbon::now();
  146. // save
  147. $this->save();
  148. }
  149. /**
  150. * Set this article as unfeatured
  151. */
  152. public function unFeature()
  153. {
  154. // set featured attribute
  155. $this->featured = false;
  156. // save
  157. $this->save();
  158. }
  159. /**
  160. * Toggle the featured status on/off
  161. */
  162. public function toggleFeatured() {
  163. if ( $this->featured == true ) {
  164. $this->unfeature();
  165. return false;
  166. } else {
  167. $this->feature();
  168. return true;
  169. }
  170. }
  171. /**
  172. * Query articles that are featured
  173. */
  174. public function scopeFeatured( $query )
  175. {
  176. return $query->where('featured', true);
  177. }
  178. /**
  179. * Query articles that have been featured before
  180. */
  181. public function scopeWasFeatured( $query )
  182. {
  183. return $query->where('featured_on', '!=', '0000-00-00 00:00:00');
  184. }
  185. /**
  186. * Get list of articles sorted by popularity
  187. * Get the top 20 super bumped articles
  188. */
  189. public static function getTopArticles()
  190. {
  191. // return Article::published()->get()->sortByDesc( function( $model )
  192. // {
  193. // return $model->popularity;
  194. // });
  195. return Article::superBumped()->take(20)->get();
  196. }
  197. /**
  198. * Get the total number of likes on Trace
  199. */
  200. public static function getTotalBumps()
  201. {
  202. return Article::published()->has('likes')->count();
  203. }
  204. /**
  205. * Get property of super bumped status
  206. */
  207. public function getSuperBumpedAttribute()
  208. {
  209. // This doesn't seem efficient...
  210. // Get the collection of super bumped articles
  211. $super_bumps = Article::superBumped()->take(20)->get();
  212. // Is this article in the super bumps collection?
  213. return $super_bumps->contains( $this );
  214. }
  215. /**
  216. * Query articles that have been super-bumped
  217. * And join in the likeable count if it's not 0
  218. */
  219. public function scopeSuperBumped( $query )
  220. {
  221. return $query
  222. ->published()
  223. ->where('created_at', '>', Carbon::now()->subYear())
  224. ->join('likeable_like_counters', function( $join ) {
  225. $join->on('articles.id', '=', 'likeable_like_counters.likable_id')
  226. ->where('likeable_like_counters.count', '>', 0);
  227. })
  228. ->select('likeable_like_counters.count as like_count', 'articles.*')
  229. ->orderBy('like_count', 'desc')
  230. ->orderBy('created_at', 'desc');
  231. }
  232. /**
  233. * Query Articles commented on by a user
  234. */
  235. public function scopeWhereCommented( $query, $user_id )
  236. {
  237. return $query->whereHas('comments', function( $q ) use ( $user_id ) {
  238. $q->where('user_id', $user_id);
  239. });
  240. }
  241. /**
  242. * Collect all articles that have been commented on by a user
  243. */
  244. public static function commented( $user_id )
  245. {
  246. return Article::published()->whereCommented( $user_id )
  247. ->get()
  248. ->sortByDesc( function( $article ) {
  249. return $article->comments()->first()->created_at;
  250. });
  251. }
  252. /**
  253. * Get a string appropriate for count of others
  254. */
  255. private function peopleString( $count )
  256. {
  257. return ( $count === 1 ) ? ' other' : ' others';
  258. }
  259. /**
  260. * Get the count and string of
  261. * others that have bumped this article
  262. */
  263. public function getOthersBumpedAttribute() {
  264. $count = $this->likeCount;
  265. $others = ( $this->liked() ) ? $count-1 : $count;
  266. return $others . $this->peopleString( $others );
  267. }
  268. /**
  269. * Only get published articles - query scope
  270. * @param query $query
  271. */
  272. public function scopePublished( $query )
  273. {
  274. $query
  275. ->where('published', true) // published
  276. ->whereNull('deleted_at'); // not deleted
  277. }
  278. /**
  279. * Only get unpublished articles
  280. */
  281. public function scopeUnpublished( $query )
  282. {
  283. $query->where('published', false);
  284. }
  285. /**
  286. * return list for $this->tag_list
  287. * @return Array
  288. */
  289. public function getTagListAttribute()
  290. {
  291. return $this->tags->lists('id')->all();
  292. }
  293. /**
  294. * Simple return for the created_at
  295. */
  296. public function getDateAttribute()
  297. {
  298. return $this->created_at;
  299. }
  300. /**
  301. * Return a human-readable difference
  302. * for the date attribute
  303. */
  304. public function getDateDiffAttribute()
  305. {
  306. return $this->created_at->diffForHumans();
  307. }
  308. }