Archives.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <?php
  2. namespace app\admin\model\cms;
  3. use addons\cms\library\FulltextSearch;
  4. use addons\cms\library\IntCode;
  5. use addons\cms\library\Service;
  6. use app\common\model\User;
  7. use think\Model;
  8. use traits\model\SoftDelete;
  9. class Archives extends Model
  10. {
  11. use SoftDelete;
  12. // 表名
  13. protected $name = 'cms_archives';
  14. // 自动写入时间戳字段
  15. protected $autoWriteTimestamp = 'int';
  16. // 定义时间戳字段名
  17. protected $createTime = 'createtime';
  18. protected $updateTime = 'updatetime';
  19. protected $deleteTime = 'deletetime';
  20. // 追加属性
  21. protected $append = [
  22. 'flag_text',
  23. 'status_text',
  24. 'publishtime_text',
  25. 'url',
  26. 'fullurl',
  27. 'style_bold',
  28. 'style_color',
  29. ];
  30. protected static $config = [];
  31. /**
  32. * 获取加密后的ID
  33. * @param $value
  34. * @param $data
  35. * @return string
  36. */
  37. public function getEidAttr($value, $data)
  38. {
  39. $value = $data['id'];
  40. if (self::$config['archiveshashids']) {
  41. $value = IntCode::encode($value);
  42. }
  43. return $value;
  44. }
  45. public function getUrlAttr($value, $data)
  46. {
  47. return $this->buildUrl($value, $data);
  48. }
  49. public function getFullurlAttr($value, $data)
  50. {
  51. return $this->buildUrl($value, $data, true);
  52. }
  53. private function buildUrl($value, $data, $domain = false)
  54. {
  55. $diyname = isset($data['diyname']) && $data['diyname'] ? $data['diyname'] : $data['id'];
  56. $catename = isset($this->channel) && $this->channel ? $this->channel->diyname : 'all';
  57. $cateid = isset($this->channel) && $this->channel ? $this->channel->id : 0;
  58. $time = $data['publishtime'] ?? time();
  59. $vars = [
  60. ':id' => $data['id'],
  61. ':eid' => $this->getEidAttr($data['id'], $data),
  62. ':diyname' => $diyname,
  63. ':channel' => $data['channel_id'],
  64. ':catename' => $catename,
  65. ':cateid' => $cateid,
  66. ':year' => date("Y", $time),
  67. ':month' => date("m", $time),
  68. ':day' => date("d", $time),
  69. ];
  70. return addon_url('cms/archives/index', $vars, static::$config['urlsuffix'], true);
  71. }
  72. public function getOriginData()
  73. {
  74. return $this->origin;
  75. }
  76. /**
  77. * 批量设置数据
  78. * @param $data
  79. * @return $this
  80. */
  81. public function setData($data)
  82. {
  83. if (is_object($data)) {
  84. $data = get_object_vars($data);
  85. }
  86. $this->data = array_merge($this->data, $data);
  87. return $this;
  88. }
  89. protected static function init()
  90. {
  91. self::$config = $config = get_addon_config('cms');
  92. self::beforeInsert(function ($row) {
  93. if (!isset($row['admin_id']) || !$row['admin_id']) {
  94. $admin_id = session('admin.id');
  95. $row['admin_id'] = $admin_id ? $admin_id : 0;
  96. }
  97. });
  98. self::afterInsert(function ($row) {
  99. $pk = $row->getPk();
  100. $channel = Channel::get($row['channel_id']);
  101. $row->getQuery()->where($pk, $row[$pk])->update(['model_id' => $channel ? $channel['model_id'] : 0]);
  102. });
  103. self::beforeWrite(function ($row) {
  104. //在更新之前对数组进行处理
  105. foreach ($row->getData() as $k => $value) {
  106. if (is_array($value) && is_array(reset($value))) {
  107. $value = json_encode(self::getArrayData($value), JSON_UNESCAPED_UNICODE);
  108. } else {
  109. $value = is_array($value) ? implode(',', $value) : $value;
  110. }
  111. $row->setAttr($k, $value);
  112. }
  113. $changedData = $row->getChangedData();
  114. if (isset($changedData['flag'])) {
  115. $row['weigh'] = in_array('top', explode(',', $changedData['flag']))
  116. ? ($row['weigh'] == 0 ? 9999 : $row['weigh'])
  117. : ($row['weigh'] == 9999 ? 0 : $row['weigh']);
  118. }
  119. if (isset($row['content']) && !self::$config['realtimereplacelink']) {
  120. $row['content'] = Service::autolinks($row['content']);
  121. }
  122. });
  123. self::afterWrite(function ($row) use ($config) {
  124. if (isset($row['channel_id'])) {
  125. //在更新成功后刷新副表、TAGS表数据、栏目表
  126. $channel = Channel::get($row->channel_id);
  127. if ($channel) {
  128. $model = Modelx::get($channel['model_id']);
  129. if ($model) {
  130. $values = array_intersect_key($row->getData(), array_flip($model->fields));
  131. $values['id'] = $row['id'];
  132. if (isset($row['content'])) {
  133. $values['content'] = $row['content'];
  134. }
  135. //更新副表
  136. $addonTbl = \think\Db::name($model['table']);
  137. if ($addonTbl->find($row['id'])) {
  138. $addonTbl->update($values);
  139. } else {
  140. $addonTbl->insert($values, true);
  141. }
  142. }
  143. }
  144. }
  145. if (isset($row['tags'])) {
  146. \addons\cms\model\Tag::refresh($row['tags'], $row['id']);
  147. }
  148. $changedData = $row->getChangedData();
  149. if (isset($changedData['status']) && $changedData['status'] == 'normal') {
  150. if (isset($row['user_id']) && isset($config['score']['postarchives'])) {
  151. //增加积分
  152. User::score($config['score']['postarchives'], $row['user_id'], '发布文章');
  153. }
  154. //推送到熊掌号和百度站长
  155. if ($config['baidupush']) {
  156. $urls = [$row->fullurl];
  157. \think\Hook::listen("baidupush", $urls);
  158. }
  159. }
  160. if (isset($changedData['channel_id']) || isset($changedData['channel_ids'])) {
  161. //有更新栏目和副栏目需要刷新统计数据
  162. $refreshIds = [];
  163. $originData = $row->getOriginData();
  164. if (isset($changedData['channel_id'])) {
  165. $refreshIds = array_merge($refreshIds, [$originData['channel_id'] ?? 0, $changedData['channel_id']]);
  166. }
  167. if (isset($changedData['channel_ids'])) {
  168. $refreshIds = array_merge($refreshIds, explode(',', $originData['channel_ids'] ?? ''), explode(',', $changedData['channel_ids']));
  169. }
  170. $refreshIds = array_filter(array_unique($refreshIds));
  171. Channel::refreshItems($refreshIds);
  172. }
  173. if ($config['searchtype'] == 'xunsearch') {
  174. //更新全文搜索
  175. FulltextSearch::update($row->id);
  176. }
  177. });
  178. self::afterDelete(function ($row) use ($config) {
  179. $data = Archives::withTrashed()->find($row['id']);
  180. if ($data) {
  181. if ($row['status'] == 'normal' && isset($config['score']['postarchives'])) {
  182. User::score(-$config['score']['postarchives'], $row['user_id'], '删除文章');
  183. }
  184. if ($config['searchtype'] == 'xunsearch') {
  185. FulltextSearch::del($row);
  186. }
  187. } else {
  188. //删除相关TAG
  189. \addons\cms\model\Tag::refresh('', $row['id']);
  190. }
  191. //删除评论
  192. Comment::deleteByType('archives', $row['id'], !$data);
  193. //刷新统计数据
  194. $refreshIds = array_merge([$row['channel_id']], explode(',', $row['channel_ids']));
  195. $refreshIds = array_filter(array_unique($refreshIds));
  196. Channel::refreshItems($refreshIds);
  197. });
  198. }
  199. public function getFlagList()
  200. {
  201. $config = get_addon_config('cms');
  202. return $config['flagtype'];
  203. }
  204. public function getStatusList()
  205. {
  206. return ['normal' => __('Status Normal'), 'hidden' => __('Status Hidden'), 'rejected' => __('Status rejected'), 'pulloff' => __('Status pulloff')];
  207. }
  208. public function getIshomeList()
  209. {
  210. return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
  211. }
  212. public function getStyleBoldAttr($value, $data)
  213. {
  214. return in_array('b', explode('|', $data['style']));
  215. }
  216. public function getStyleColorAttr($value, $data)
  217. {
  218. $result = preg_match("/(#([0-9a-z]{6}))/i", $data['style'], $matches);
  219. return $result ? $matches[1] : '';
  220. }
  221. public function getFlagTextAttr($value, $data)
  222. {
  223. $value = $value ? $value : $data['flag'];
  224. $valueArr = $value ? explode(',', $value) : [];
  225. $list = $this->getFlagList();
  226. return implode(',', array_intersect_key($list, array_flip($valueArr)));
  227. }
  228. public function getStatusTextAttr($value, $data)
  229. {
  230. $value = $value ? $value : $data['status'];
  231. $list = $this->getStatusList();
  232. return isset($list[$value]) ? $list[$value] : '';
  233. }
  234. public function getPublishtimeTextAttr($value, $data)
  235. {
  236. $value = $value ? $value : $data['publishtime'];
  237. return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
  238. }
  239. protected function setPublishtimeAttr($value)
  240. {
  241. return $value && !is_numeric($value) ? strtotime($value) : ($value ? $value : null);
  242. }
  243. protected function setCreatetimeAttr($value)
  244. {
  245. return $value && !is_numeric($value) ? strtotime($value) : ($value ? $value : null);
  246. }
  247. protected function setKeywordsAttr($value)
  248. {
  249. return str_replace(["&nbsp;", "\r\n", "\r", "\n"], "", strip_tags($value));
  250. }
  251. protected function setDescriptionAttr($value)
  252. {
  253. return str_replace(["&nbsp;", "\r\n", "\r", "\n"], "", strip_tags($value));
  254. }
  255. public static function getArrayData($data)
  256. {
  257. if (!isset($data['value'])) {
  258. $result = [];
  259. foreach ($data as $index => $datum) {
  260. $result['field'][$index] = $datum['key'];
  261. $result['value'][$index] = $datum['value'];
  262. }
  263. $data = $result;
  264. }
  265. $fieldarr = $valuearr = [];
  266. $field = isset($data['field']) ? $data['field'] : (isset($data['key']) ? $data['key'] : []);
  267. $value = isset($data['value']) ? $data['value'] : [];
  268. foreach ($field as $m => $n) {
  269. if ($n != '') {
  270. $fieldarr[] = $field[$m];
  271. $valuearr[] = $value[$m];
  272. }
  273. }
  274. return $fieldarr ? array_combine($fieldarr, $valuearr) : [];
  275. }
  276. public function channel()
  277. {
  278. return $this->belongsTo('Channel', 'channel_id', '', [], 'LEFT')->setEagerlyType(0);
  279. }
  280. public function special()
  281. {
  282. return $this->belongsTo('Special', 'special_id', '', [], 'LEFT')->setEagerlyType(0);
  283. }
  284. /**
  285. * 关联模型
  286. */
  287. public function model()
  288. {
  289. return $this->belongsTo("Modelx", 'model_id')->setEagerlyType(1);
  290. }
  291. /**
  292. * 关联模型
  293. */
  294. public function user()
  295. {
  296. return $this->belongsTo("\\app\\common\\model\\User", 'user_id', 'id', [], 'LEFT')->setEagerlyType(1);
  297. }
  298. /**
  299. * 关联模型
  300. */
  301. public function admin()
  302. {
  303. return $this->belongsTo("\\app\\admin\\model\\Admin", 'admin_id', 'id', [], 'LEFT')->setEagerlyType(1);
  304. }
  305. }