PageRenderTime 69ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/common/models/Post.php

https://gitlab.com/makkooz/nikestreetbeat
PHP | 467 lines | 267 code | 57 blank | 143 comment | 22 complexity | 639711fe91ca2921ae875f7c3753d75f MD5 | raw file
  1. <?php
  2. /**
  3. * @link http://www.writesdown.com/
  4. * @copyright Copyright (c) 2015 WritesDown
  5. * @license http://www.writesdown.com/license/
  6. */
  7. namespace common\models;
  8. use common\components\Json;
  9. use Yii;
  10. use yii\behaviors\SluggableBehavior;
  11. use yii\db\ActiveRecord;
  12. use yii\helpers\ArrayHelper;
  13. use yii\helpers\Html;
  14. /**
  15. * This is the model class for table "{{%post}}".
  16. *
  17. * @property integer $id
  18. * @property integer $author
  19. * @property integer $type
  20. * @property string $title
  21. * @property string $excerpt
  22. * @property string $content
  23. * @property string $date
  24. * @property string $modified
  25. * @property string $status
  26. * @property string $password
  27. * @property string $slug
  28. * @property string $comment_status
  29. * @property integer $comment_count
  30. * @property string $url
  31. *
  32. * @property Media[] $media
  33. * @property PostType $postType
  34. * @property User $postAuthor
  35. * @property PostComment[] $postComments
  36. * @property PostMeta[] $postMeta
  37. * @property TermRelationship[] $termRelationships
  38. * @property Term[] $terms
  39. *
  40. * @author Agiel K. Saputra <13nightevil@gmail.com>
  41. * @since 0.1.0
  42. */
  43. class Post extends ActiveRecord
  44. {
  45. public $username;
  46. const COMMENT_STATUS_OPEN = 'open';
  47. const COMMENT_STATUS_CLOSE = 'close';
  48. const STATUS_PUBLISH = 'publish';
  49. const STATUS_PRIVATE = 'private';
  50. const STATUS_DRAFT = 'draft';
  51. const STATUS_TRASH = 'trash';
  52. const STATUS_REVIEW = 'review';
  53. /**
  54. * @inheritdoc
  55. */
  56. public static function tableName()
  57. {
  58. return '{{%post}}';
  59. }
  60. /**
  61. * @inheritdoc
  62. */
  63. public function behaviors()
  64. {
  65. return [
  66. [
  67. 'class' => SluggableBehavior::className(),
  68. 'attribute' => 'title',
  69. 'attributes' => [ActiveRecord::EVENT_BEFORE_INSERT => ['slug']],
  70. ],
  71. ];
  72. }
  73. /**
  74. * @inheritdoc
  75. */
  76. public function rules()
  77. {
  78. return [
  79. ['title', 'required'],
  80. [['author', 'type', 'comment_count'], 'integer'],
  81. [['title', 'excerpt', 'content'], 'string'],
  82. [['date', 'modified', 'author'], 'safe'],
  83. [['status', 'comment_status'], 'string', 'max' => 20],
  84. [['password', 'slug'], 'string', 'max' => 255],
  85. ['comment_status', 'in', 'range' => [self::COMMENT_STATUS_OPEN, self::COMMENT_STATUS_CLOSE]],
  86. ['comment_status', 'default', 'value' => self::COMMENT_STATUS_CLOSE],
  87. ['comment_count', 'default', 'value' => 0],
  88. [
  89. 'status',
  90. 'in',
  91. 'range' => [
  92. self::STATUS_PUBLISH,
  93. self::STATUS_DRAFT,
  94. self::STATUS_PRIVATE,
  95. self::STATUS_REVIEW,
  96. self::STATUS_TRASH,
  97. ],
  98. ],
  99. ['status', 'default', 'value' => self::STATUS_PUBLISH],
  100. [['title', 'slug'], 'unique'],
  101. ];
  102. }
  103. /**
  104. * @inheritdoc
  105. */
  106. public function attributeLabels()
  107. {
  108. return [
  109. 'id' => Yii::t('writesdown', 'ID'),
  110. 'author' => Yii::t('writesdown', 'Author'),
  111. 'type' => Yii::t('writesdown', 'Type'),
  112. 'title' => Yii::t('writesdown', 'Title'),
  113. 'excerpt' => Yii::t('writesdown', 'Excerpt'),
  114. 'content' => Yii::t('writesdown', 'Content'),
  115. 'date' => Yii::t('writesdown', 'Date'),
  116. 'modified' => Yii::t('writesdown', 'Modified'),
  117. 'status' => Yii::t('writesdown', 'Status'),
  118. 'password' => Yii::t('writesdown', 'Password'),
  119. 'slug' => Yii::t('writesdown', 'Slug'),
  120. 'comment_status' => Yii::t('writesdown', 'Comment Status'),
  121. 'comment_count' => Yii::t('writesdown', 'Comment Count'),
  122. 'username' => Yii::t('writesdown', 'Author'),
  123. ];
  124. }
  125. /**
  126. * @return \yii\db\ActiveQuery
  127. */
  128. public function getMedia()
  129. {
  130. return $this->hasMany(Media::className(), ['post_id' => 'id']);
  131. }
  132. /**
  133. * @return \yii\db\ActiveQuery
  134. */
  135. public function getPostType()
  136. {
  137. return $this->hasOne(PostType::className(), ['id' => 'type']);
  138. }
  139. /**
  140. * @return \yii\db\ActiveQuery
  141. */
  142. public function getPostAuthor()
  143. {
  144. return $this->hasOne(User::className(), ['id' => 'author']);
  145. }
  146. /**
  147. * @return \yii\db\ActiveQuery
  148. */
  149. public function getPostComments()
  150. {
  151. return $this->hasMany(PostComment::className(), ['post_id' => 'id']);
  152. }
  153. /**
  154. * @return \yii\db\ActiveQuery
  155. */
  156. public function getPostMeta()
  157. {
  158. return $this->hasMany(PostMeta::className(), ['post_id' => 'id']);
  159. }
  160. /**
  161. * @return \yii\db\ActiveQuery
  162. */
  163. public function getTermRelationships()
  164. {
  165. return $this->hasMany(TermRelationship::className(), ['post_id' => 'id']);
  166. }
  167. /**
  168. * @return \yii\db\ActiveQuery
  169. */
  170. public function getTerms()
  171. {
  172. return $this
  173. ->hasMany(Term::className(), ['id' => 'term_id'])
  174. ->viaTable('{{%term_relationship}}', ['post_id' => 'id']);
  175. }
  176. /**
  177. * Get post status as array.
  178. *
  179. * @return array
  180. */
  181. public function getPostStatuses()
  182. {
  183. return [
  184. self::STATUS_PUBLISH => Yii::t('writesdown', 'Publish'),
  185. self::STATUS_DRAFT => Yii::t('writesdown', 'Draft'),
  186. self::STATUS_PRIVATE => Yii::t('writesdown', 'Private'),
  187. self::STATUS_TRASH => Yii::t('writesdown', 'Trash'),
  188. self::STATUS_REVIEW => Yii::t('writesdown', 'Review'),
  189. ];
  190. }
  191. /**
  192. * Get comment status as array
  193. */
  194. public function getCommentStatuses()
  195. {
  196. return [
  197. self::COMMENT_STATUS_OPEN => Yii::t('writesdown', 'Open'),
  198. self::COMMENT_STATUS_CLOSE => Yii::t('writesdown', 'Close'),
  199. ];
  200. }
  201. /**
  202. * Get permalink of current post.
  203. *
  204. * @return string
  205. */
  206. public function getUrl()
  207. {
  208. return Yii::$app->urlManagerFront->createAbsoluteUrl(['/post/view', 'id' => $this->id]);
  209. }
  210. /**
  211. * Get meta for current post.
  212. *
  213. * @param string $name
  214. * @return mixed|null
  215. */
  216. public function getMeta($name)
  217. {
  218. /* @var $model \common\models\PostMeta */
  219. $model = PostMeta::findOne(['name' => $name, 'post_id' => $this->id]);
  220. if ($model) {
  221. if (Json::isJson($model->value)) {
  222. return Json::decode($model->value);
  223. }
  224. return $model->value;
  225. }
  226. return null;
  227. }
  228. /**
  229. * Add new meta data for current post.
  230. *
  231. * @param string $name
  232. * @param string|array $value
  233. * @return bool
  234. */
  235. public function setMeta($name, $value)
  236. {
  237. if (is_array($value) || is_object($value)) {
  238. $value = Json::encode($value);
  239. }
  240. if ($this->getMeta($name) !== null) {
  241. return $this->upMeta($name, $value);
  242. }
  243. $model = new PostMeta([
  244. 'post_id' => $this->id,
  245. 'name' => $name,
  246. 'value' => $value,
  247. ]);
  248. return $model->save();
  249. }
  250. /**
  251. * Update meta data for current post.
  252. *
  253. * @param string $name
  254. * @param string|array $value
  255. * @return bool
  256. */
  257. public function upMeta($name, $value)
  258. {
  259. /* @var $model \common\models\PostMeta */
  260. $model = PostMeta::findOne(['name' => $name, 'post_id' => $this->id]);
  261. if (is_array($value) || is_object($value)) {
  262. $value = Json::encode($value);
  263. }
  264. $model->value = $value;
  265. return $model->save();
  266. }
  267. /**
  268. * @param bool $sameType
  269. * @param bool $sameTerm
  270. * @return array|null|Post
  271. */
  272. public function getNextPost($sameType = true, $sameTerm = false)
  273. {
  274. /* @var $query \yii\db\ActiveQuery */
  275. $query = static::find()
  276. ->from(['post' => $this->tableName()])
  277. ->andWhere(['>', 'post.id', $this->id])
  278. ->andWhere(['status' => 'publish'])
  279. ->orderBy(['post.id' => SORT_ASC]);
  280. if ($sameType) {
  281. $query->andWhere(['type' => $this->type]);
  282. }
  283. if ($sameTerm) {
  284. $query->innerJoinWith([
  285. 'terms' => function ($query) {
  286. /* @var $query \yii\db\ActiveQuery */
  287. $query->from(['term' => Term::tableName()])->andWhere([
  288. 'IN',
  289. 'term.id',
  290. implode(',', ArrayHelper::getColumn($this->terms, 'id')),
  291. ]);
  292. },
  293. ]);
  294. }
  295. return $query->one();
  296. }
  297. /**
  298. * @param bool $sameType
  299. * @param bool $sameTerm
  300. * @param string $title
  301. * @param array $options
  302. * @return string
  303. */
  304. public function getNextPostLink($title = '{title}', $sameType = true, $sameTerm = false, $options = [])
  305. {
  306. if ($nextPost = $this->getNextPost($sameType, $sameTerm)) {
  307. $title = preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($nextPost) {
  308. $attribute = $matches[1];
  309. return $nextPost->{$attribute};
  310. }, $title);
  311. return Html::a($title, $nextPost->url, $options);
  312. }
  313. return '';
  314. }
  315. /**
  316. * @param bool $sameType
  317. * @param bool $sameTerm
  318. * @return array|null|Post
  319. */
  320. public function getPrevPost($sameType = true, $sameTerm = false)
  321. {
  322. /* @var $query \yii\db\ActiveQuery */
  323. $query = static::find()
  324. ->from(['post' => $this->tableName()])
  325. ->andWhere(['<', 'post.id', $this->id])
  326. ->andWhere(['status' => 'publish'])
  327. ->orderBy(['post.id' => SORT_DESC]);
  328. if ($sameType) {
  329. $query->andWhere(['type' => $this->type]);
  330. }
  331. if ($sameTerm) {
  332. $query->innerJoinWith([
  333. 'terms' => function ($query) {
  334. /* @var $query \yii\db\ActiveQuery */
  335. $query->from(['term' => Term::tableName()])->andWhere([
  336. 'IN',
  337. 'term.id',
  338. implode(',', ArrayHelper::getColumn($this->terms, 'id')),
  339. ]);
  340. },
  341. ]);
  342. }
  343. return $query->one();
  344. }
  345. /**
  346. * @param bool $sameType
  347. * @param bool $sameTerm
  348. * @param string $title
  349. * @param array $options
  350. * @return string
  351. */
  352. public function getPrevPostLink($title = '{title}', $sameType = true, $sameTerm = false, $options = [])
  353. {
  354. if ($prevPost = $this->getPrevPost($sameType, $sameTerm)) {
  355. $title = preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($prevPost) {
  356. $attribute = $matches[1];
  357. return $prevPost->{$attribute};
  358. }, $title);
  359. return Html::a($title, $prevPost->url, $options);
  360. }
  361. return '';
  362. }
  363. /**
  364. * Generate excerpt of post model.
  365. *
  366. * @param int $limit
  367. * @return string
  368. */
  369. public function getExcerpt($limit = 55)
  370. {
  371. $excerpt = preg_replace('/\s{3,}/', ' ', strip_tags($this->content));
  372. $words = preg_split("/[\n\r\t ]+/", $excerpt, $limit + 1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
  373. if (count($words) > $limit) {
  374. end($words);
  375. $lastWord = prev($words);
  376. $excerpt = substr($excerpt, 0, $lastWord[1] + strlen($lastWord[0]));
  377. }
  378. return $excerpt;
  379. }
  380. /**
  381. * Get permission to access model by current user.
  382. * @return bool
  383. */
  384. public function getPermission()
  385. {
  386. if (!$this->postType
  387. || !Yii::$app->user->can($this->postType->permission)
  388. || (!Yii::$app->user->can('editor') && Yii::$app->user->id !== $this->author)
  389. || (!Yii::$app->user->can('author') && $this->status === self::STATUS_REVIEW)
  390. ) {
  391. return false;
  392. }
  393. return true;
  394. }
  395. /**
  396. * @inheritdoc
  397. */
  398. public function beforeSave($insert)
  399. {
  400. if (parent::beforeSave($insert)) {
  401. if ($this->isNewRecord) {
  402. $this->author = Yii::$app->user->id;
  403. }
  404. $this->modified = date('Y-m-d H:i:s');
  405. $this->excerpt = $this->getExcerpt();
  406. return true;
  407. }
  408. return false;
  409. }
  410. }