Cms.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. namespace addons\cms\model;
  3. use addons\cms\library\Service;
  4. use think\facade\Db;
  5. use think\Model;
  6. class Cms extends Model
  7. {
  8. protected $autoWriteTimestamp = true;
  9. protected $ext_table = '_data';
  10. protected $name = 'cms_field';
  11. protected static $config = [];
  12. protected static function init()
  13. {
  14. self::$config = get_addon_config('cms');
  15. }
  16. protected function currentLang()
  17. {
  18. return cms_current_lang();
  19. }
  20. protected function langFields()
  21. {
  22. return ['title', 'keywords', 'description', 'tags', 'content'];
  23. }
  24. protected function getLangRow($tableName, $id, $currentLang, $defaultLang, $strictLang = false)
  25. {
  26. $extTable = $tableName . $this->ext_table;
  27. $columns = array_map('strtolower', array_keys(Db::name($extTable)->getFields()));
  28. if (!in_array('did', $columns, true)) {
  29. return [null, $columns];
  30. }
  31. $query = Db::name($extTable)->where(['did' => $id]);
  32. if (in_array('lang', $columns, true)) {
  33. $langRow = (clone $query)->where(['lang' => $currentLang])->find();
  34. if (!$langRow && !$strictLang && $currentLang !== $defaultLang) {
  35. $langRow = (clone $query)->where(['lang' => $defaultLang])->find();
  36. }
  37. } else {
  38. $langRow = $query->find();
  39. }
  40. return [$langRow, $columns];
  41. }
  42. protected function mergeLangData($modeId, array $row, array $langRow = null, $currentLang = '', $defaultLang = '', array $extColumns = [])
  43. {
  44. $currentLang = strtolower((string) $currentLang);
  45. $defaultLang = strtolower((string) $defaultLang);
  46. $extColumns = array_map('strtolower', $extColumns);
  47. if ($langRow) {
  48. foreach ($langRow as $field => $value) {
  49. $fieldLower = strtolower((string) $field);
  50. if (!in_array($fieldLower, $extColumns, true) || in_array($fieldLower, ['did', 'lang'], true)) {
  51. continue;
  52. }
  53. // 附表独有字段,直接并入结果(如 title1、title2、自定义副标题等)
  54. if (!array_key_exists($field, $row)) {
  55. $row[$field] = $value;
  56. continue;
  57. }
  58. // 同名字段:附表非空优先,空值回退主表,保证多语言字段覆盖主表默认值
  59. if ($value !== null && $value !== '') {
  60. $row[$field] = $value;
  61. }
  62. }
  63. // 再做一次附表自定义字段兜底,避免后续格式化过程中丢失
  64. foreach ($langRow as $field => $value) {
  65. $fieldLower = strtolower((string) $field);
  66. if (in_array($fieldLower, ['did', 'lang'], true)) {
  67. continue;
  68. }
  69. if (preg_match('/^(title\d+|subtitle\d*|desc\d+|description\d+|button(_text)?\d*|link\d+|image\d+|video\d+)$/i', $field)) {
  70. $row[$field] = $value;
  71. }
  72. }
  73. $row['lang'] = $currentLang ?: ($langRow['lang'] ?? ($row['lang'] ?? ''));
  74. } else {
  75. $row['lang'] = $currentLang ?: ($row['lang'] ?? '');
  76. }
  77. return Service::dealModelShowData(cms_cache('ModelField')[$modeId], $row);
  78. }
  79. public function getList($modeId, $where, $moreifo, $field = '*', $order = '', $limit = 10, $page = null, $simple = false, $config = [])
  80. {
  81. $url_mode = self::$config['site_url_mode'];
  82. $config['query'] = array_merge($config['query'] ?? [], request()->get());
  83. $config['list_rows'] = $limit;
  84. $tableName = cms_cache('Model')[$modeId]['tablename'] ?? '';
  85. if (empty($tableName)) {
  86. return [];
  87. }
  88. $defaultLang = cms_default_lang();
  89. $currentLang = $this->currentLang();
  90. $strictLang = !empty($config['strict_lang']);
  91. $cmsModel = Db::name($tableName)->where($where)->order($order)->field($field);
  92. if ($page) {
  93. $result = $cmsModel->paginate($config, $simple);
  94. $items = $result->items();
  95. } else {
  96. list($offset, $length) = $this->parseLimit($limit);
  97. $items = $cmsModel->limit($offset, $length)->select()->toArray();
  98. $result = $items;
  99. }
  100. if (!empty($items)) {
  101. $Category = cms_cache('Category');
  102. foreach ($items as $key => $vo) {
  103. if (getModel($modeId, 'type') == 2 && $moreifo) {
  104. [$langRow, $extColumns] = $this->getLangRow($tableName, $vo['id'], $currentLang, $defaultLang, $strictLang);
  105. if ($strictLang && !$langRow) {
  106. unset($items[$key]);
  107. continue;
  108. }
  109. $vo = $this->mergeLangData($modeId, $vo, $langRow ?: null, $currentLang, $defaultLang, $extColumns);
  110. } else {
  111. $vo = Service::dealModelShowData(cms_cache('ModelField')[$modeId], $vo);
  112. }
  113. $cat = $url_mode == 1 ? $vo['catid'] : ($Category[$vo['catid']]['catdir'] ?? getCategory($vo['catid'], 'catdir'));
  114. $vo['url'] = buildContentUrl($cat, $vo['id'], $vo['url']);
  115. $items[$key] = $vo;
  116. }
  117. if ($page) {
  118. foreach ($items as $idx => $item) {
  119. $result[$idx] = $item;
  120. }
  121. } else {
  122. $result = $items;
  123. }
  124. }
  125. return $result;
  126. }
  127. public function getContent($modeId, $where, $moreifo = false, $field = '*', $order = '', $cacheKey = false, $cacheExpire = null)
  128. {
  129. $url_mode = self::$config['site_url_mode'];
  130. $tableName = cms_cache('Model')[$modeId]['tablename'] ?? '';
  131. if (empty($tableName)) {
  132. return [];
  133. }
  134. $defaultLang = cms_default_lang();
  135. $currentLang = $this->currentLang();
  136. $dataInfo = Db::name($tableName)
  137. ->field($field)
  138. ->cache($cacheKey, $cacheExpire, 'cms')
  139. ->where($where)
  140. ->order($order)
  141. ->find();
  142. if (!empty($dataInfo)) {
  143. if (getModel($modeId, 'type') == 2 && $moreifo) {
  144. [$langRow, $extColumns] = $this->getLangRow($tableName, $dataInfo['id'], $currentLang, $defaultLang);
  145. $dataInfo = $this->mergeLangData($modeId, $dataInfo, $langRow ?: null, $currentLang, $defaultLang, $extColumns);
  146. } else {
  147. $dataInfo = Service::dealModelShowData(cms_cache('ModelField')[$modeId], $dataInfo);
  148. }
  149. $Category = cms_cache('Category');
  150. $cat = $url_mode == 1 ? $dataInfo['catid'] : ($Category[$dataInfo['catid']]['catdir'] ?? getCategory($dataInfo['catid'], 'catdir'));
  151. $dataInfo['url'] = buildContentUrl($cat, $dataInfo['id'], $dataInfo['url']);
  152. }
  153. return $dataInfo;
  154. }
  155. protected function parseLimit($limit): array
  156. {
  157. if (is_string($limit) && strpos($limit, ',') !== false) {
  158. return array_map('intval', explode(',', $limit));
  159. }
  160. return [0, (int) $limit];
  161. }
  162. }