Fields.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace app\admin\model\cms;
  3. use addons\cms\library\Alter;
  4. use addons\cms\library\Service;
  5. use app\common\model\Config;
  6. use think\Db;
  7. use think\Exception;
  8. use think\exception\PDOException;
  9. use think\Model;
  10. class Fields extends Model
  11. {
  12. // 表名
  13. protected $name = 'cms_fields';
  14. // 自动写入时间戳字段
  15. protected $autoWriteTimestamp = 'int';
  16. // 定义时间戳字段名
  17. protected $createTime = 'createtime';
  18. protected $updateTime = 'updatetime';
  19. // 追加属性
  20. protected $append = [
  21. 'status_text',
  22. 'content_list',
  23. ];
  24. protected $type = [
  25. 'setting' => 'json',
  26. ];
  27. protected static $listField = ['select', 'selects', 'checkbox', 'radio', 'array', 'selectpage', 'selectpages'];
  28. public function setError($error)
  29. {
  30. $this->error = $error;
  31. }
  32. protected static function init()
  33. {
  34. $beforeUpdateCallback = function ($row) {
  35. if (!preg_match("/^([a-zA-Z0-9_]+)$/i", $row['name'])) {
  36. throw new Exception("字段只支持字母数字下划线");
  37. }
  38. if (is_numeric(substr($row['name'], 0, 1))) {
  39. throw new Exception("字段不能以数字开始");
  40. }
  41. if ($row['source'] == 'model') {
  42. $tableFields = \think\Db::name('cms_archives')->getTableFields();
  43. if (in_array(strtolower($row['name']), $tableFields)) {
  44. throw new Exception("字段已经在主表存在了");
  45. }
  46. if (in_array($row['name'], ['id', 'content'])) {
  47. throw new Exception("字段已经存在");
  48. }
  49. } elseif (in_array($row['source'], ['channel', 'page', 'special', 'block'])) {
  50. //栏目、单页、专题、区块需过滤主表字段
  51. $tableFields = \think\Db::name('cms_' . $row['source'])->getTableFields();
  52. $customFieldList = Service::getCustomFields($row['source'], 0);
  53. $tableFields = array_diff($tableFields, array_map(function ($field) {
  54. return $field['name'];
  55. }, collection($customFieldList)->toArray()));
  56. if (in_array(strtolower($row['name']), $tableFields)) {
  57. throw new Exception("字段已经在表中存在了");
  58. }
  59. } elseif ($row['source'] == 'diyform') {
  60. $tableFields = ['id', 'user_id', 'createtime', 'updatetime', 'memo', 'status'];
  61. if (in_array(strtolower($row['name']), $tableFields)) {
  62. throw new Exception("字段已经存在");
  63. }
  64. } else {
  65. $tableFields = ['id', 'user_id', 'createtime', 'updatetime'];
  66. if (in_array(strtolower($row['name']), $tableFields)) {
  67. throw new Exception("字段为保留字段,请使用其它字段");
  68. }
  69. }
  70. };
  71. $afterInsertCallback = function ($row) {
  72. //为了避免引起更新的事件回调,这里采用直接执行SQL的写法
  73. Db::name('cms_fields')->update(['id' => $row['id'], 'weigh' => $row['id']]);
  74. Fields::refreshTable($row, 'insert');
  75. };
  76. $afterUpdateCallback = function ($row) {
  77. Fields::refreshTable($row, 'update');
  78. };
  79. self::beforeInsert($beforeUpdateCallback);
  80. self::beforeUpdate($beforeUpdateCallback);
  81. self::afterInsert($afterInsertCallback);
  82. self::afterUpdate($afterUpdateCallback);
  83. self::afterDelete(function ($row) {
  84. Fields::refreshTable($row, 'delete');
  85. });
  86. }
  87. public function getContentListAttr($value, $data)
  88. {
  89. return in_array($data['type'], self::$listField) ? Config::decode($data['content']) : $data['content'];
  90. }
  91. public static function refreshTable($row, $action = 'insert')
  92. {
  93. $model = null;
  94. if (in_array($row['source'], ['model', 'diyform'])) {
  95. $model = $row['source'] == 'model' ? Modelx::get($row['source_id']) : Diyform::get($row['source_id']);
  96. if (!$model) {
  97. throw new Exception("未找到指定模型");
  98. }
  99. $table = $model['table'];
  100. } elseif (in_array($row['source'], ['channel', 'page', 'special', 'block'])) {
  101. $table = "cms_" . $row['source'];
  102. } else {
  103. throw new Exception("未找到指定模型");
  104. }
  105. $alter = Alter::instance();
  106. if (isset($row['oldname']) && $row['oldname'] != $row['name']) {
  107. $alter->setOldname($row['oldname']);
  108. }
  109. $alter
  110. ->setTable($table)
  111. ->setName($row['name'])
  112. ->setLength($row['length'])
  113. ->setContent($row['content'])
  114. ->setDecimals($row['decimals'])
  115. ->setDefaultvalue($row['defaultvalue'])
  116. ->setComment($row['title'])
  117. ->setType($row['type']);
  118. if ($action == 'insert') {
  119. $sql = $alter->getAddSql();
  120. } elseif ($action == 'update') {
  121. $sql = $alter->getModifySql();
  122. } elseif ($action == 'delete') {
  123. $sql = $alter->getDropSql();
  124. } else {
  125. throw new Exception("操作类型错误");
  126. }
  127. //变更模型数据
  128. if ($model) {
  129. $fields = Fields::where('source', $row['source'])->where('source_id', $row['source_id'])->field('name')->column('name');
  130. $model->fields = implode(',', $fields);
  131. $model->save();
  132. }
  133. try {
  134. db()->execute($sql);
  135. } catch (PDOException $e) {
  136. throw new Exception($e->getMessage());
  137. }
  138. }
  139. public function getStatusList()
  140. {
  141. return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
  142. }
  143. public function getStatusTextAttr($value, $data)
  144. {
  145. $value = $value ? $value : $data['status'];
  146. $list = $this->getStatusList();
  147. return isset($list[$value]) ? $list[$value] : '';
  148. }
  149. }