Article.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <?php
  2. namespace common\models;
  3. use common\behaviors\CategoryBehavior;
  4. use common\behaviors\CommentBehavior;
  5. use common\behaviors\MetaBehavior;
  6. use common\behaviors\PushBehavior;
  7. use common\behaviors\SoftDeleteBehavior;
  8. use common\behaviors\TagBehavior;
  9. use common\behaviors\VoteBehavior;
  10. use common\models\article\Base;
  11. use common\models\article\Exhibition;
  12. use common\models\query\ArticleQuery;
  13. use common\modules\attachment\behaviors\UploadBehavior;
  14. use common\modules\user\behaviors\UserBehavior;
  15. use Yii;
  16. use yii\base\InvalidParamException;
  17. use yii\behaviors\BlameableBehavior;
  18. use yii\behaviors\TimestampBehavior;
  19. /**
  20. * This is the model class for table "{{%article}}".
  21. *
  22. * @property int $id
  23. * @property int $sort
  24. * @property int $user_id
  25. * @property string $title
  26. * @property string $content
  27. * @property int $created_at
  28. * @property int $updated_at
  29. * @property int $status
  30. * @property int $category_id
  31. * @property string $category
  32. * @property string $cover
  33. * @property string $source
  34. * @property string $description
  35. * @property int $view
  36. * @property int $published_at
  37. * @property int $is_top
  38. * @property int $is_best
  39. * @property int $is_hot
  40. * @property string $module
  41. * @property string $city
  42. * @property string $address
  43. * @property string $tel
  44. * @property string $company
  45. * @property string $position
  46. * @property string $intro
  47. * @property string $chain
  48. * @property string $principal
  49. * @property boolean $isUp read-only
  50. * @property boolean $isDown read-only
  51. * @property boolean $isFavourite read-only
  52. * @property Base|Exhibition $data
  53. */
  54. class Article extends \yii\db\ActiveRecord
  55. {
  56. const STATUS_PENDING = 0;
  57. const STATUS_ACTIVE = 1;
  58. /**
  59. * {@inheritdoc}
  60. */
  61. public static function tableName()
  62. {
  63. return '{{%article}}';
  64. }
  65. /**
  66. * {@inheritdoc}
  67. */
  68. public function rules()
  69. {
  70. return [
  71. [['title', 'category_id'], 'required'],
  72. [['title'], 'trim'],
  73. [['status', 'category_id', 'view', 'is_top', 'is_hot', 'is_best', 'sort'], 'integer'],
  74. [
  75. 'published_at', 'default', 'value' => function () {
  76. return date('Y-m-d H:i:s', time());
  77. }
  78. ],
  79. [
  80. 'published_at', 'filter', 'filter' => function ($value) {
  81. return is_numeric($value) ? $value : strtotime($value);
  82. }, 'skipOnEmpty' => true
  83. ],
  84. ['status', 'default', 'value' => self::STATUS_ACTIVE],
  85. ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_PENDING]],
  86. [['category_id'], 'setCategory'],
  87. ['category_id', 'exist', 'targetClass' => Category::className(), 'targetAttribute' => 'id'],
  88. [['title', 'category', 'city', 'tel'], 'string', 'max' => 50],
  89. [['source', 'address'], 'string', 'max' => 255],
  90. [['description'], 'string'],
  91. [['category_id', 'status', 'view'], 'filter', 'filter' => 'intval'],
  92. [['module'], 'string'],
  93. [['cover', 'chain','address','company','position','intro','principal'], 'safe']
  94. ];
  95. }
  96. public function setCategory($attribute, $params)
  97. {
  98. $this->category = Category::find()->where(['id' => $this->$attribute])->select('title')->scalar();
  99. }
  100. public static function getStatusList()
  101. {
  102. return [
  103. self::STATUS_PENDING => '待审',
  104. self::STATUS_ACTIVE => '通过',
  105. ];
  106. }
  107. /**
  108. * {@inheritdoc}
  109. */
  110. public function attributeLabels()
  111. {
  112. return [
  113. 'id' => Yii::t('common', 'ID'),
  114. 'title' => '名称',
  115. 'category_id' => '分类',
  116. 'category' => '分类',
  117. 'status' => '状态',
  118. 'view' => '浏览量',
  119. 'is_top' => '置顶',
  120. 'is_hot' => '热门',
  121. 'is_best' => '精华',
  122. 'description' => '摘要',
  123. 'user_id' => '作者',
  124. 'source' => '来源连接',
  125. 'deleted_at' => '删除时间',
  126. 'favourite' => '收藏数量',
  127. 'published_at' => '发布时间',
  128. 'created_at' => Yii::t('common', 'Created At'),
  129. 'updated_at' => Yii::t('common', 'Updated At'),
  130. 'module' => '文档类型',
  131. 'city' => '城市',
  132. 'address' => '地址',
  133. 'tel' => '联系方式',
  134. 'sort' => '排序',
  135. 'company' => '单位',
  136. 'position' => '职务',
  137. 'intro' => '简介',
  138. 'chain' => '产业链',
  139. 'principal' => '负责人',
  140. // 'cover' => '封面',
  141. // 'trueView' => '浏览量',
  142. // 'tagNames' => '标签',
  143. // 'content' => '内容'
  144. ];
  145. }
  146. public function attributeHints()
  147. {
  148. return [
  149. 'tagNames' => '(空格分隔多个标签)'
  150. ];
  151. }
  152. /**
  153. * {@inheritdoc}
  154. */
  155. public function behaviors()
  156. {
  157. $behaviors = [
  158. TimestampBehavior::className(),
  159. PushBehavior::className(),
  160. [
  161. 'class' => SoftDeleteBehavior::className(),
  162. 'softDeleteAttributeValues' => [
  163. 'deleted_at' => function ($model) {
  164. return time();
  165. }
  166. ],
  167. 'restoreAttributeValues' => [
  168. 'deleted_at' => null
  169. ],
  170. 'invokeDeleteEvents' => false // 不触发删除相关事件
  171. ],
  172. CategoryBehavior::className(),
  173. [
  174. 'class' => MetaBehavior::className(),
  175. 'entity' => __CLASS__
  176. ],
  177. [
  178. 'class' => VoteBehavior::className(),
  179. 'entity' => __CLASS__
  180. ],
  181. TagBehavior::className(),
  182. [
  183. 'class' => CommentBehavior::className(),
  184. 'entity' => __CLASS__
  185. ],
  186. [
  187. 'class' => UploadBehavior::className(),
  188. 'attribute' => 'cover',
  189. 'entity' => __CLASS__
  190. ],
  191. UserBehavior::className()
  192. ];
  193. if (!Yii::$app->request->isConsoleRequest) {
  194. $behaviors[] = [
  195. 'class' => BlameableBehavior::className(),
  196. 'createdByAttribute' => 'user_id',
  197. 'updatedByAttribute' => false
  198. ];
  199. }
  200. return $behaviors;
  201. }
  202. /**
  203. * @inheritdoc
  204. * @return ArticleQuery the newly created [[ActiveQuery]] instance.
  205. */
  206. public static function find()
  207. {
  208. return Yii::createObject(ArticleQuery::className(), [get_called_class()]);
  209. }
  210. /**
  211. * @return array
  212. */
  213. public function transactions()
  214. {
  215. return [
  216. self::SCENARIO_DEFAULT => self::OP_ALL,
  217. ];
  218. }
  219. public function afterDelete()
  220. {
  221. parent::afterDelete();
  222. // 删除文章内容
  223. // $content = $this->data;
  224. // if ($content != null) {
  225. // $content->delete();
  226. // }
  227. }
  228. public function getMetaData()
  229. {
  230. $model = $this->getMetaModel();
  231. $title = $model->title ?: $this->title;
  232. $keywords = $model->keywords ?: $this->getTagNames(',');
  233. $description = $model->description ?: $this->description;
  234. return [$title, $keywords, $description];
  235. }
  236. public function getData()
  237. {
  238. $moduleClass = $this->findModuleClass($this->module);
  239. return new $moduleClass;
  240. // return $this->hasOne($moduleClass, ['id' => 'id']);
  241. }
  242. /**
  243. * 真实浏览量
  244. */
  245. public function getTrueView()
  246. {
  247. return $this->view + \Yii::$app->cache->get('article:view:' . $this->id);
  248. }
  249. /**
  250. * 增加浏览量
  251. */
  252. public function addView()
  253. {
  254. $cache = \Yii::$app->cache;
  255. $key = 'article:view:' . $this->id;
  256. $view = $cache->get($key);
  257. if ($view !== false) {
  258. if ($view >= 20) {
  259. $this->updateCounters(['view' => $view + 1]);
  260. $cache->delete($key);
  261. } else {
  262. $cache->set($key, ++$view);
  263. }
  264. } else {
  265. $cache->set($key, 1);
  266. }
  267. }
  268. /**
  269. * 当前用户是否收藏
  270. * @return bool
  271. */
  272. public function getIsFavourite()
  273. {
  274. if (!Yii::$app->user->isGuest) {
  275. $userId = Yii::$app->user->id;
  276. $favourite = Favourite::find()->where(['article_id' => $this->id, 'user_id' => $userId])->one();
  277. if ($favourite) {
  278. return true;
  279. }
  280. }
  281. return false;
  282. }
  283. public function getIsReprint()
  284. {
  285. return !empty($this->source);
  286. }
  287. public function findModuleClass()
  288. {
  289. $class = new \ReflectionClass(get_called_class());
  290. $moduleClass = $class->getNamespaceName() . '\\article\\' . ucfirst($this->module);
  291. // 找父类
  292. if (!class_exists($moduleClass)) {
  293. $parentClass = $class->getParentClass();
  294. $moduleClass = $parentClass->getNamespaceName() . '\\article\\' . ucfirst($this->module);
  295. }
  296. if (!class_exists($moduleClass)) {
  297. throw new InvalidParamException('文章类型不存在');
  298. }
  299. return $moduleClass;
  300. }
  301. public function beforeSave($insert)
  302. {
  303. if (parent::beforeSave($insert)) {
  304. if (!empty($this->chain) && is_array($this->chain)) {
  305. $this->chain = implode(',', $this->chain);
  306. }
  307. return true;
  308. } else {
  309. return false;
  310. }
  311. }
  312. }