Cms.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <?php
  2. namespace app\admin\model\cms;
  3. use addons\cms\library\FulltextSearch;
  4. use addons\cms\library\MeiliSearch;
  5. use addons\cms\library\Service;
  6. use think\facade\Config;
  7. use think\facade\Db;
  8. use think\facade\Event;
  9. use think\Model;
  10. class Cms extends Model
  11. {
  12. protected $autoWriteTimestamp = true;
  13. protected $ext_table = '_data';
  14. protected $name = 'cms_field';
  15. protected static $config = [];
  16. protected static function init()
  17. {
  18. self::$config = get_addon_config('cms');
  19. }
  20. protected function physicalTableName($tableName)
  21. {
  22. $prefix = Config::get('database.connections.mysql.prefix', '');
  23. return strpos($tableName, $prefix) === 0 ? $tableName : $prefix . $tableName;
  24. }
  25. protected function getTableColumns($tableName)
  26. {
  27. static $cache = [];
  28. $tableName = $this->physicalTableName($tableName);
  29. if (!isset($cache[$tableName])) {
  30. $columns = Db::getFields($tableName);
  31. $cache[$tableName] = array_map('strtolower', array_keys($columns));
  32. }
  33. return $cache[$tableName];
  34. }
  35. protected function hasColumn($tableName, $column)
  36. {
  37. return in_array(strtolower($column), $this->getTableColumns($tableName), true);
  38. }
  39. protected function filterDataByColumns(array $data, array $columns)
  40. {
  41. $result = [];
  42. foreach ($data as $key => $value) {
  43. if (in_array(strtolower($key), $columns, true)) {
  44. $result[$key] = $value;
  45. }
  46. }
  47. return $result;
  48. }
  49. protected function getLangWhere($extTableName, $id, $lang)
  50. {
  51. $where = ['did' => $id];
  52. if ($this->hasColumn($extTableName, 'lang')) {
  53. $where['lang'] = $lang;
  54. }
  55. return $where;
  56. }
  57. protected function isChineseLang($lang)
  58. {
  59. return in_array(strtolower((string) $lang), ['cn', 'zh', 'zh-cn'], true);
  60. }
  61. protected function getChineseTitleFromExtTable($extTableName, $id, $lang, array $dataExt, array $extColumns)
  62. {
  63. if ($this->isChineseLang($lang) && array_key_exists('title', $dataExt)) {
  64. return $dataExt['title'];
  65. }
  66. if (!in_array('lang', $extColumns, true)) {
  67. return null;
  68. }
  69. $row = Db::table($extTableName)->where('did', $id)->where('lang', 'in', ['cn', 'zh', 'zh-cn'])->orderRaw("field(lang,'cn','zh','zh-cn')")->find();
  70. return $row && array_key_exists('title', $row) ? $row['title'] : null;
  71. }
  72. protected function splitLangFields(array $data, array $dataExt = [], $lang = 'cn', array $mainColumns = [], array $extColumns = [])
  73. {
  74. $defaultLang = Db::name('lang')->where('is_default', 1)->value('mark') ?: 'cn';
  75. $langFields = ['title', 'keywords', 'description', 'tags'];
  76. foreach ($langFields as $field) {
  77. if (!array_key_exists($field, $data)) {
  78. continue;
  79. }
  80. $value = $data[$field];
  81. $mainHas = in_array(strtolower($field), $mainColumns, true);
  82. $extHas = in_array(strtolower($field), $extColumns, true);
  83. if ($extHas) {
  84. $dataExt[$field] = $value;
  85. }
  86. if (!$mainHas || $lang !== $defaultLang) {
  87. unset($data[$field]);
  88. }
  89. }
  90. return [$data, $dataExt];
  91. }
  92. public function addModelData($data, $dataExt = [], $lang = 'cn')
  93. {
  94. $catid = (int) $data['catid'];
  95. $category = Category::find($catid);
  96. $modelid = $category['modelid'];
  97. $eventResult = Event::trigger('cms_content_add', [$data, $dataExt]);
  98. if ($eventResult) {
  99. [$data, $dataExt] = array_map('array_merge', [$data, $dataExt], ...$eventResult);
  100. }
  101. $tablename = $this->physicalTableName(Models::where('id', $modelid)->value('tablename'));
  102. $extTableName = $tablename . $this->ext_table;
  103. $mainColumns = $this->getTableColumns($tablename);
  104. $extColumns = $this->getTableColumns($extTableName);
  105. Service::getAfterText($data, $dataExt);
  106. [$data, $dataExt] = $this->splitLangFields($data, $dataExt, $lang, $mainColumns, $extColumns);
  107. $data['admin_id'] = session('admin.id') ?: 0;
  108. [$data, $dataExt] = Service::dealModelPostData($modelid, $data, $dataExt);
  109. $data = $this->filterDataByColumns($data, $mainColumns);
  110. $dataExt = $this->filterDataByColumns($dataExt, $extColumns);
  111. if (!isset($data['publish_time'])) {
  112. $data['publish_time'] = request()->time();
  113. }
  114. $data['create_time'] = request()->time();
  115. $data['update_time'] = request()->time();
  116. try {
  117. $id = Db::table($tablename)->insertGetId($data);
  118. if (!empty($dataExt['tags'])) {
  119. $this->tagDispose($dataExt['tags'], $id, $catid, $modelid);
  120. }
  121. if (!empty($dataExt)) {
  122. $dataExt['did'] = $id;
  123. if (in_array('lang', $extColumns, true)) {
  124. $dataExt['lang'] = $lang;
  125. $whereExt = $this->getLangWhere($extTableName, $id, $lang);
  126. $exists = Db::table($extTableName)->where($whereExt)->find();
  127. if ($exists) {
  128. Db::table($extTableName)->where($whereExt)->update($dataExt);
  129. } else {
  130. Db::table($extTableName)->insert($dataExt);
  131. }
  132. } else {
  133. $exists = Db::table($extTableName)->where(['did' => $id])->find();
  134. if ($exists) {
  135. Db::table($extTableName)->where(['did' => $id])->update($dataExt);
  136. } else {
  137. Db::table($extTableName)->insert($dataExt);
  138. }
  139. }
  140. }
  141. } catch (\Exception $e) {
  142. throw new \Exception($e->getMessage());
  143. }
  144. $category->inc('items')->save();
  145. if (self::$config['site_weburlpush']) {
  146. hook('weburlpush', buildContentUrl($catid, $id, $data['url'] ?? '', true, true));
  147. }
  148. if (self::$config['site_searchtype'] === 'xunsearch') {
  149. FulltextSearch::update($modelid, $catid, $id, $data, $dataExt);
  150. }
  151. if (self::$config['site_searchtype'] === 'meilisearch') {
  152. MeiliSearch::update($modelid, $catid, $id, $data, $dataExt);
  153. }
  154. return $id;
  155. }
  156. public function editModelData($data, $dataExt = [], $lang = 'cn')
  157. {
  158. $catid = (int) $data['catid'];
  159. $id = (int) $data['id'];
  160. $category = Category::find($catid);
  161. $modelid = $category['modelid'];
  162. $eventResult = Event::trigger('cms_content_edit', [$data, $dataExt]);
  163. if ($eventResult) {
  164. [$data, $dataExt] = array_map('array_merge', [$data, $dataExt], ...$eventResult);
  165. }
  166. $tablename = $this->physicalTableName(Models::where('id', $modelid)->value('tablename'));
  167. $extTableName = $tablename . $this->ext_table;
  168. $mainColumns = $this->getTableColumns($tablename);
  169. $extColumns = $this->getTableColumns($extTableName);
  170. Service::getAfterText($data, $dataExt);
  171. [$data, $dataExt] = $this->splitLangFields($data, $dataExt, $lang, $mainColumns, $extColumns);
  172. $defaultLang = Db::name('lang')->where('is_default', 1)->value('mark') ?: 'cn';
  173. if (!empty($dataExt['tags'])) {
  174. $this->tagDispose($dataExt['tags'], $id, $catid, $modelid);
  175. } else {
  176. $this->tagDispose([], $id, $catid, $modelid);
  177. }
  178. [$data, $dataExt] = Service::dealModelPostData($modelid, $data, $dataExt);
  179. $data = $this->filterDataByColumns($data, $mainColumns);
  180. $dataExt = $this->filterDataByColumns($dataExt, $extColumns);
  181. if (in_array('title', $mainColumns, true) && in_array('title', $extColumns, true)) {
  182. $chineseTitle = $this->getChineseTitleFromExtTable($extTableName, $id, $lang, $dataExt, $extColumns);
  183. if ($chineseTitle !== null) {
  184. $data['title'] = $chineseTitle;
  185. }
  186. }
  187. if ($lang !== $defaultLang) {
  188. foreach (['keywords', 'description', 'tags'] as $field) {
  189. unset($data[$field]);
  190. }
  191. }
  192. if (!isset($data['update_time'])) {
  193. $data['update_time'] = request()->time();
  194. }
  195. $info = Db::table($tablename)->where('id', $id)->find();
  196. if (empty($info)) {
  197. throw new \Exception('该信息不存在!');
  198. }
  199. Db::table($tablename)->where('id', $id)->update($data);
  200. if (!empty($dataExt)) {
  201. $whereExt = $this->getLangWhere($extTableName, $id, $lang);
  202. $exists = Db::table($extTableName)->where($whereExt)->find();
  203. if ($exists) {
  204. Db::table($extTableName)->where($whereExt)->update($dataExt);
  205. } else {
  206. $dataExt['did'] = $id;
  207. if (in_array('lang', $extColumns, true)) {
  208. $dataExt['lang'] = $lang;
  209. }
  210. Db::table($extTableName)->insert($dataExt);
  211. }
  212. }
  213. if ($info['sysadd'] == 0) {
  214. CmsContent::where('catid', $catid)->where('content_id', $id)->update(['status' => $data['status']]);
  215. }
  216. if (self::$config['site_searchtype'] === 'xunsearch') {
  217. FulltextSearch::update($modelid, $catid, $id, $data, $dataExt);
  218. }
  219. if (self::$config['site_searchtype'] === 'meilisearch') {
  220. MeiliSearch::update($modelid, $catid, $id, $data, $dataExt);
  221. }
  222. }
  223. public function deleteModelData($catid, $id, $no_delete = false)
  224. {
  225. $category = Category::find($catid);
  226. if (empty($category)) {
  227. throw new \Exception('栏目不存在!');
  228. }
  229. $modelid = $category['modelid'];
  230. $model = Models::where('id', $modelid)->find();
  231. $tableName = $this->physicalTableName($model['tablename']);
  232. $data = Db::table($tableName)->where('id', $id)->find();
  233. if (empty($data)) {
  234. throw new \Exception('该信息不存在!');
  235. }
  236. if (!empty($data['tags'])) {
  237. $this->tagDispose([], $data['id'], $data['catid'], $modelid);
  238. }
  239. if ($no_delete) {
  240. Db::table($tableName)->where('id', $id)->update(['status' => -1]);
  241. } else {
  242. Db::table($tableName)->where('id', $id)->delete();
  243. if (2 == $model['type']) {
  244. Db::table($tableName . $this->ext_table)->where('did', $id)->delete();
  245. }
  246. if ($category['items']) {
  247. $category->dec('items')->save();
  248. }
  249. }
  250. if ($data['sysadd'] == 0) {
  251. CmsContent::where('catid', $data['catid'])->where('content_id', $data['id'])->delete();
  252. }
  253. if (self::$config['site_searchtype'] === 'xunsearch') {
  254. FulltextSearch::del($data['catid'], $id);
  255. }
  256. if (self::$config['site_searchtype'] === 'meilisearch') {
  257. MeiliSearch::del($data['catid'], $id);
  258. }
  259. }
  260. private function tagDispose($tags, $id, $catid, $modelid)
  261. {
  262. if (!empty($tags)) {
  263. $keyword = strpos($tags, ',') === false ? explode(' ', $tags) : explode(',', $tags);
  264. $keyword = array_unique($keyword);
  265. if ('add' == request()->action()) {
  266. (new Tags)->addTag($keyword, $id, $catid);
  267. } else {
  268. (new Tags)->updata($keyword, $id, $catid);
  269. }
  270. } else {
  271. (new Tags)->deleteAll($id, $catid);
  272. }
  273. }
  274. }