Просмотр файла app/Models/Story.php

Размер файла: 5.8Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace App\Models;
  6.  
  7. use App\Services\Str;
  8. use App\Services\View;
  9. use MotorORM\Builder;
  10. use MotorORM\Collection;
  11.  
  12. /**
  13. * Class Story
  14. *
  15. * @property int $id
  16. * @property int $user_id
  17. * @property string $slug
  18. * @property bool $active
  19. * @property string $title
  20. * @property string $text
  21. * @property int $rating
  22. * @property int $reads
  23. * @property bool $locked
  24. * @property int $created_at
  25. *
  26. * @method $this active()
  27. *
  28. * @property-read User $user
  29. * @property-read Poll $poll
  30. * @property-read Favorite $favorite
  31. * @property-read Collection<Tag> $tags
  32. * @property-read Collection<File> $files
  33. * @property-read Collection<Comment> $comments
  34. * @property-read Collection<Read> $storyReads
  35. * @property-read Collection<Poll> $polls
  36. * @property-read Collection<Favorite> $favorites
  37. */
  38. class Story extends Model
  39. {
  40. /**
  41. * Table name
  42. */
  43. protected string $table = 'stories.csv';
  44.  
  45. /**
  46. * Директория загрузки файлов
  47. */
  48. public string $uploadPath = '/uploads/stories';
  49.  
  50. /**
  51. * The attributes that should be cast.
  52. */
  53. protected array $casts = [
  54. 'active' => 'bool',
  55. 'rating' => 'int',
  56. 'reads' => 'int',
  57. 'locked' => 'bool',
  58. ];
  59.  
  60. /**
  61. * Возвращает связь пользователя
  62. *
  63. * @return Builder
  64. */
  65. public function user(): Builder
  66. {
  67. return $this->hasOne(User::class, 'id', 'user_id');
  68. }
  69.  
  70. /**
  71. * Возвращает связь голосования пользователя
  72. *
  73. * @return Builder
  74. */
  75. public function poll(): Builder
  76. {
  77. return $this->hasOne(Poll::class, 'entity_id')
  78. ->where('user_id', getUser('id'))
  79. ->where('entity_name', 'story');
  80. }
  81.  
  82. /**
  83. * Возвращает связь голосований
  84. *
  85. * @return Builder
  86. */
  87. public function polls(): Builder
  88. {
  89. return $this->hasMany(Poll::class, 'entity_id')
  90. ->where('entity_name', 'story');
  91. }
  92.  
  93. /**
  94. * Возвращает связь просмотров
  95. *
  96. * @return Builder
  97. */
  98. public function storyReads(): Builder
  99. {
  100. return $this->hasMany(Read::class);
  101. }
  102.  
  103. /**
  104. * Возвращает связь файлов
  105. *
  106. * @return Builder
  107. */
  108. public function files(): Builder
  109. {
  110. return $this->hasMany(File::class);
  111. }
  112.  
  113. /**
  114. * Возвращает связь комментариев
  115. *
  116. * @return Builder
  117. */
  118. public function comments(): Builder
  119. {
  120. return $this->hasMany(Comment::class);
  121. }
  122.  
  123. /**
  124. * Возвращает связь избранного пользователя
  125. *
  126. * @return Builder
  127. */
  128. public function favorite(): Builder
  129. {
  130. return $this->hasOne(Favorite::class, 'story_id')
  131. ->where('user_id', getUser('id'));
  132. }
  133.  
  134. /**
  135. * Возвращает связь с избранным
  136. *
  137. * @return Builder
  138. */
  139. public function favorites(): Builder
  140. {
  141. return $this->hasMany(Favorite::class);
  142. }
  143.  
  144. /**
  145. * Возвращает связь с тегами
  146. *
  147. * @return Builder
  148. */
  149. public function tags(): Builder
  150. {
  151. return $this->hasMany(Tag::class);
  152. }
  153.  
  154. public function scopeActive(Builder $query): Builder
  155. {
  156. return $query->where('active', true);
  157. }
  158.  
  159. /**
  160. * Delete story
  161. *
  162. * @return int
  163. */
  164. public function delete(): int
  165. {
  166. // delete files
  167. foreach ($this->files as $file) {
  168. $file->delete();
  169. }
  170.  
  171. // delete comments
  172. foreach ($this->comments as $comment) {
  173. $comment->delete();
  174. }
  175.  
  176. // delete reads
  177. foreach ($this->storyReads as $read) {
  178. $read->delete();
  179. }
  180.  
  181. // delete polls
  182. foreach ($this->polls as $poll) {
  183. $poll->delete();
  184. }
  185.  
  186. // delete favorites
  187. foreach ($this->favorites as $favorite) {
  188. $favorite->delete();
  189. }
  190.  
  191. // delete tags
  192. foreach ($this->tags as $tag) {
  193. $tag->delete();
  194. }
  195.  
  196. return parent::delete();
  197. }
  198.  
  199. /**
  200. * Возвращает сокращенный текст статьи
  201. *
  202. * @param int $words
  203. *
  204. * @return string
  205. */
  206. public function shortText(int $words = 100): string
  207. {
  208. $more = app(View::class)->fetch('app/_more', ['link' => $this->getLink()]);
  209.  
  210. if (str_contains($this->text, '[cut]')) {
  211. return bbCode(current(explode('[cut]', $this->text))) . $more;
  212. }
  213.  
  214. if (Str::wordCount($this->text) > $words) {
  215. return bbCodeTruncate($this->text, $words) . $more;
  216. }
  217.  
  218. return bbCode($this->text);
  219. }
  220.  
  221. /**
  222. * Get format rating
  223. *
  224. * @return string Форматированное число
  225. */
  226. public function getRating(): string
  227. {
  228. if ($this->rating > 0) {
  229. $rating = '<span style="color:#00aa00">+' . $this->rating . '</span>';
  230. } elseif ($this->rating < 0) {
  231. $rating = '<span style="color:#ff0000">' . $this->rating . '</span>';
  232. } else {
  233. $rating = '<span>0</span>';
  234. }
  235.  
  236. return $rating;
  237. }
  238.  
  239. /**
  240. * Get tags
  241. *
  242. * @return string
  243. */
  244. public function getTags(): string
  245. {
  246. $tagList = [];
  247. foreach ($this->tags as $tag) {
  248. $tagList[] = '<a href="/tags/' . urlencode(escape($tag->tag)) . '">' . escape($tag->tag) . '</a>';
  249. }
  250.  
  251. return implode(', ', $tagList);
  252. }
  253.  
  254. /**
  255. * Get link
  256. *
  257. * @return string
  258. */
  259. public function getLink(): string
  260. {
  261. return route('story-view', ['slug' => sprintf('%s-%d', $this->slug, $this->id)]);
  262. }
  263. }