国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1144 lines
43KB

  1. <?php if(!defined('DEDEINC')) exit("Request Error!");
  2. /**
  3. *
  4. * 本类用于指定一个 MySQL 的数据表
  5. * 自动生成列出、修改、删除、增加等操作
  6. *
  7. * 2011-11-08 [完善]对LURD类进行如下完善
  8. * 1.增加单条记录管理功能,指定$lurd->singleManage=TRUE,增加单条记录的管理页面;
  9. * 2.修改LURD默认管理页面的体验;
  10. * 3.模板页面支持~self~指向当前页地址;
  11. * 4.lurd支持get模式,便于单条记录的管理;
  12. * 2010-11-17 [修复]启用request类默认数据处理问题
  13. * 2010-11-17 [修复]如果存在UNIQUE表字段分析错误的问题
  14. * 2010-11-17 [增加]增加检索条件匹配方法
  15. * 2010-11-16 [增加]如果表字段存在注释,则列表项的title中则直接显示注释信息
  16. * 2010-11-14 [修复]数据表存在前缀,模板名称解析问题,同时可以对Lurd单独设定模板
  17. *
  18. *
  19. * @version $Id: lurd.class.php 7 14:07 2011/11/8 IT柏拉图,tianya $
  20. * @package DedeCMS.Libraries
  21. * @copyright Copyright (c) 2007 - 2018, DesDev, Inc.
  22. * @copyright Copyright (c) 2020, DedeBIZ.COM
  23. * @license https://www.dedebiz.com/license/v6
  24. * @link https://www.dedebiz.com
  25. */
  26. require_once(DEDEINC.'/datalistcp.class.php');
  27. /***********************************
  28. @ class lurd
  29. ***********************************/
  30. class Lurd extends DataListCP
  31. {
  32. // 固定属性
  33. var $dateTypes = array('DATE', 'DATETIME', 'TIMESTAMP', 'TIME', 'YEAR');
  34. var $floatTypes = array('FLOAT', 'DOUBLE', 'DECIMAL');
  35. var $intTypes = array('TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT');
  36. var $charTypes = array('VARCHAR', 'CHAR', 'TINYTEXT');
  37. var $textTypes = array('TEXT', 'MEDIUMTEXT', 'LONGTEXT');
  38. var $binTypes = array('TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB', 'BINARY', 'VARBINARY');
  39. var $emTypes = array('ENUM', 'SET');
  40. // 普通属性
  41. var $tableName = '';
  42. var $templateDir = '';
  43. var $lurdTempdir = '';
  44. var $tplName = '';
  45. var $appName = '';
  46. var $primaryKey = '';
  47. var $autoField = '';
  48. var $orderQuery = '';
  49. // 所的字段及属性数组
  50. var $fields = array();
  51. // 当这个值为TRUE,每次都会生成新模板,用于调试模式
  52. var $isDebug = FALSE;
  53. // 文本内容安全级别
  54. // 0 为不处理, 1 为禁止不安全HTML内容(javascript等),2完全禁止HTML内容,并替换部份不安全字符串(如:eval(、union、CONCAT(、--、等)
  55. var $stringSafe = 1;
  56. // 这个变量用于存放连结表的参数
  57. // 可以通过 $lurd->AddLinkTable($tablelurd, linkfields, mylinkid, linkid); 联结一个表
  58. var $linkTables = array();
  59. // 联结表的指定字段(如果后一个表的字段和前一个重名, 前者会被替换)
  60. var $addFields = array();
  61. // 查询条件
  62. var $searchParameters = array();
  63. // 单条记录管理,修改/删除
  64. var $singleManage = TRUE;
  65. //构造函数,指定要操作的表名
  66. function __construct($tablename, $templatedir='', $lurdtempdir='')
  67. {
  68. global $dsql;
  69. $prefix = "#@__";
  70. $this->tplName = str_replace($prefix, '', $tablename);
  71. $this->tableName = str_replace($prefix, $GLOBALS['cfg_dbprefix'], $tablename);
  72. $this->templateDir = $templatedir;
  73. $this->lurdTempdir = empty($lurdtempdir) ? $this->templateDir.'/lurd' : $lurdtempdir;
  74. parent::__construct();
  75. $this->AnalyseTable();
  76. $ct = isset($GLOBALS['ct'])? $GLOBALS['ct'] : request('ct', '');
  77. if(!empty($ct))
  78. {
  79. $this->SetParameter('ct', $ct);
  80. }
  81. $this->SetParameter('ac', 'list');
  82. }
  83. //监听器,根据指定的ac(ac)调用相应处理方法
  84. function ListenAll($listfield = '', $wherequery = '', $orderquery ='')
  85. {
  86. global $action;
  87. $action = !empty($action)? $action : request('action');
  88. switch($action)
  89. {
  90. case 'add' :
  91. $this->AddData();
  92. break;
  93. case 'edit':
  94. $this->EditData();
  95. break;
  96. case 'del':
  97. $this->DelData();
  98. break;
  99. case 'saveadd':
  100. $this->SaveAddData();
  101. break;
  102. case 'saveedit':
  103. $this->SaveEditData();
  104. break;
  105. default:
  106. $this->ListData($listfield, $wherequery, $orderquery);
  107. break;
  108. }
  109. }
  110. // 指定主键
  111. // 在数据表没有主键的情况下,必须指定一个字段为主键字段,否则系统用所有数据的md5值作为主键
  112. function AddPriKey($fieldname)
  113. {
  114. $this->primaryKey = $fieldname;
  115. }
  116. // 指定应用的名称
  117. function AddAppName($appname)
  118. {
  119. $this->appName = $appname;
  120. }
  121. //设置用于排序的SQL,如 order by id desc
  122. function SetOrderQuery($query)
  123. {
  124. $this->orderQuery = $query;
  125. }
  126. //强制指定字段为其它类型
  127. function BindType($fieldname, $ftype, $format='')
  128. {
  129. //'type' =>'','length' =>'0','unsigned'=>FALSE,'autokey'=>FALSE,
  130. //'null'=>FALSE,default'=>'','em'=>'','format'=>'','listtemplate'=>'','edittemplate'=>''
  131. $typesArr = array_merge($this->dateTypes, $this->floatTypes, $this->intTypes, $this->charTypes, $this->textTypes, $this->binTypes, $this->emTypes);
  132. if( isset($this->fields[$fieldname]) && in_array(strtoupper($ftype), $typesArr) )
  133. {
  134. $this->fields[$fieldname]['type'] = $ftype;
  135. $this->fields[$fieldname]['format'] = $format;
  136. }
  137. }
  138. //强制指定字模板(列表list和编辑edit、增加add模板里用)
  139. function BindTemplate($fieldname, $tmptype='list', $temp='')
  140. {
  141. if( isset($this->fields[$fieldname]) )
  142. {
  143. $this->fields[$fieldname][$tmptype.'template'] = $temp;
  144. }
  145. }
  146. // 列出数据
  147. /*********************************
  148. * $listfield = '' 指定要列出的字段(默认为'*') ,只需填写当前表
  149. 联结表出的字段在 AddLinkTable 指定, 因此不需要 表名.字段名 方式识别
  150. * $wherequery = '' 查询query,如果联结了其它表,需用 表名.字段名 识别字段
  151. * $orderquery = '' 排序query,如果联结了其它表,需用 表名.字段名 识别字段
  152. **********************************/
  153. function ListData($listfield = '*', $wherequery = '', $orderquery ='', $Suff = '_list.htm')
  154. {
  155. $listdd = '';
  156. if(trim($listfield)=='') $listfield = '*';
  157. $template = $this->templateDir.'/'.$this->tplName.$Suff;
  158. //生成列表模板
  159. if( !file_exists($template) || $this->isDebug )
  160. {
  161. $this->MakeListTemplate($listfield);
  162. }
  163. // 获取检索条件
  164. if( $wherequery == '' )
  165. {
  166. $wherequery = $this->GetSearchQuery();
  167. }
  168. //是否有联结其它的表
  169. $islink = count($this->linkTables) > 0 ? TRUE : FALSE;
  170. //主表索引字段(Select * From 部份)
  171. $listfields = explode(',', $listfield);
  172. foreach($listfields as $v)
  173. {
  174. $v = trim($v);
  175. if( !isset($this->fields[$v]) && $v != '*' ) continue;
  176. if($islink) {
  177. $listdd .= ($listdd=='' ? "{$this->tableName}.{$v}" : ", {$this->tableName}.{$v} ");
  178. }
  179. else {
  180. if($v=='*') $listdd .= ' * ';
  181. else $listdd .= ($listdd=='' ? "`$v`" : ",`$v`");
  182. }
  183. }
  184. if($listdd=='') $listdd = " * ";
  185. //联结表索引字段
  186. if($islink)
  187. {
  188. $joinQuery = '';
  189. foreach($this->linkTables as $k=>$linkTable)
  190. {
  191. $k++;
  192. $linkTableName = $linkTable[0]->tableName;
  193. $joinQuery .= " LEFT JOIN `{$linkTableName}` ON {$linkTableName}.{$linkTable[2]} = {$this->tableName}.{$linkTable[1]} ";
  194. foreach($this->addFields as $f=>$v)
  195. {
  196. if($v['table'] != $linkTableName) continue;
  197. $listdd .= ", {$linkTableName}.{$f} ";
  198. }
  199. }
  200. $query = "SELECT $listdd FROM `{$this->tableName}` $joinQuery $wherequery $orderquery ";
  201. }
  202. else
  203. {
  204. $query = "SELECT $listdd FROM `{$this->tableName}` $wherequery $orderquery ";
  205. }
  206. $this->SaveCurUrl();
  207. $this->SetTemplate($template);
  208. $this->SetSource($query);
  209. $this->Display();
  210. }
  211. //记录列表网址到cookie,方便返回时调用
  212. function SaveCurUrl()
  213. {
  214. setcookie('LURD_GOBACK_URL', $this->GetCurFullUrl(), time()+3600, '/');
  215. }
  216. function GetCurFullUrl()
  217. {
  218. if(!empty($_SERVER["REQUEST_URI"]))
  219. {
  220. $scriptName = $_SERVER["REQUEST_URI"];
  221. $nowurl = $scriptName;
  222. }
  223. else
  224. {
  225. $scriptName = $_SERVER["PHP_SELF"];
  226. $nowurl = empty($_SERVER["QUERY_STRING"]) ? $scriptName : $scriptName."?".$_SERVER["QUERY_STRING"];
  227. }
  228. return $nowurl;
  229. }
  230. //生成全部模板
  231. function MakeAllTemplate($listfield = '')
  232. {
  233. $this->MakeListTemplate($listfield);
  234. $this->MakeAddEditTemplate('add');
  235. $this->MakeAddEditTemplate('edit');
  236. }
  237. //生成列表模板
  238. function MakeListTemplate($listfield = '')
  239. {
  240. $templateTemplate = $this->lurdTempdir.'/lurd-list.htm';
  241. $template = $this->templateDir.'/'.$this->tplName.'_list.htm';
  242. $tempstr = '';
  243. $fp = fopen($templateTemplate, 'r');
  244. while( !feof($fp) ) $tempstr .= fread($fp, 1024);
  245. fclose($fp);
  246. $tempItems = array('appname'=>'', 'totalitem'=>'', 'titleitem'=>'', 'fielditem'=>'');
  247. $tempItems['appname'] = empty($this->appName) ? "管理数据表: ".$this->tableName : $this->appName;
  248. //设置选择项
  249. $tempItems['totalitem'] = 1;
  250. $tempItems['self'] = $_SERVER["PHP_SELF"];
  251. $titleitem = " <td class='nowrap'>选择</td>\r\n";
  252. if( !preg_match("/,/", $this->primaryKey) )
  253. {
  254. $fielditem = " <td class='nowrap'><input type=\"checkbox\" name=\"{$this->primaryKey}[]\" value=\"{dede:field name='{$this->primaryKey}' /}\" /></td>\r\n";
  255. }
  256. else
  257. {
  258. $prikeys = explode(',', $this->primaryKey);
  259. $prikeyValue = '<'.'?php echo md5("key"';
  260. foreach($prikeys as $v)
  261. {
  262. $prikeyValue .= '.$fields["'.$v.'"]';
  263. }
  264. $prikeyValue .= '); ?'.'>';
  265. $fielditem = " <td class='nowrap'><input type=\"checkbox\" name=\"primarykey[]\" value=\"{$prikeyValue}\" /></td>\r\n";
  266. }
  267. //使用手工指定列出字段
  268. if(!empty($listfield) && $listfield != '*' )
  269. {
  270. $listfields = explode(',', $listfield);
  271. $tempItems['totalitem'] = count($listfields) + 1;
  272. foreach($listfields as $k)
  273. {
  274. $k = trim($k);
  275. if( !isset($this->fields[$k]) ) continue;
  276. $v = $this->fields[$k];
  277. $title = !empty($v['comment'])? $v['comment'] : $k;
  278. $titleitem .= " <td class='nowrap'>$title</td>\r\n";
  279. if( !empty($v['listtemplate']) )
  280. {
  281. $fielditem .= " <td class='nowrap'>{$v['listtemplate']}</td>\r\n";
  282. }
  283. else
  284. {
  285. $dofunc = $dtype = $fformat = '';
  286. $dtype = !empty($v['type']) ? $v['type'] : 'check';
  287. if(isset($v['format']))
  288. {
  289. $fformat = $v['format'];
  290. }
  291. if(isset($v['dofunc']))
  292. {
  293. $dofunc = $v['dofunc'];
  294. }
  295. if(isset($v['type']))
  296. {
  297. $this->fields[$k]['type'] = $v['type'];
  298. }
  299. if( in_array($v['type'], $this->floatTypes) )
  300. {
  301. $dtype = 'float';
  302. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
  303. }
  304. if( in_array($v['type'], $this->dateTypes) )
  305. {
  306. $dtype = 'date';
  307. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
  308. }
  309. $fielditem .= " <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
  310. }
  311. }//End foreach
  312. }
  313. //自动处理
  314. else
  315. {
  316. foreach($this->fields as $k=>$v)
  317. {
  318. if(in_array($v['type'], $this->binTypes) )
  319. {
  320. continue;
  321. }
  322. $tempItems['totalitem']++;
  323. $title = !empty($v['comment'])? $v['comment'] : $k;
  324. $titleitem .= " <td class='nowrap'>$title</td>\r\n";
  325. $dofunc = $dtype = $fformat = '';
  326. if(isset($v['format']))
  327. {
  328. $fformat = $v['format'];
  329. }
  330. if( in_array($v['type'], $this->floatTypes) )
  331. {
  332. $dtype = 'float';
  333. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
  334. }
  335. if( in_array($v['type'], $this->dateTypes) )
  336. {
  337. $dtype = 'date';
  338. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
  339. }
  340. $fielditem .= " <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
  341. }
  342. }
  343. //是否有联结其它的表
  344. $islink = count($this->linkTables) > 0 ? TRUE : FALSE;
  345. //附加表的字段
  346. if($islink)
  347. {
  348. foreach($this->addFields as $k=>$v)
  349. {
  350. if(in_array($v['type'], $this->binTypes) )
  351. {
  352. continue;
  353. }
  354. $tempItems['totalitem']++;
  355. $titleitem .= " <td class='nowrap'>$k</td>\r\n";
  356. $dofunc = $dtype = $fformat = '';
  357. if( in_array($v['type'], $this->floatTypes) )
  358. {
  359. $dtype = 'float';
  360. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
  361. }
  362. if( in_array($v['type'], $this->dateTypes) )
  363. {
  364. $dtype = 'date';
  365. $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
  366. }
  367. $fielditem .= " <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
  368. }
  369. }
  370. if($this->singleManage)
  371. {
  372. $tempItems['totalitem']++;
  373. $titleitem .= " <td class='nowrap'>管理</td>\r\n";
  374. $currentUrl = $this->GetCurUrl();
  375. $fielditem .= " <td class='nowrap'>
  376. <a href=\"{$currentUrl}?{$this->primaryKey}={dede:field name='{$this->primaryKey}' /}&ac=edit&get=yes\">修改</a>
  377. | <a href=\"{$currentUrl}?{$this->primaryKey}={dede:field name='{$this->primaryKey}' /}&ac=del&get=yes\">删除</a> </td>\r\n";
  378. }
  379. $tempItems['titleitem'] = $titleitem;
  380. $tempItems['fielditem'] = $fielditem;
  381. foreach($tempItems as $k => $v)
  382. {
  383. $tempstr = str_replace("~$k~", $v, $tempstr);
  384. }
  385. $fp = fopen($template, 'w');
  386. fwrite($fp, $tempstr);
  387. fclose($fp);
  388. }
  389. //生成发布或编辑模板
  390. function MakeAddEditTemplate($getTemplets='add')
  391. {
  392. $templateTemplate = $this->lurdTempdir."/lurd-{$getTemplets}.htm";
  393. $template = $this->templateDir.'/'.$this->tplName."_{$getTemplets}.htm";
  394. $tempstr = '';
  395. $fp = fopen($templateTemplate, 'r');
  396. while( !feof($fp) ) $tempstr .= fread($fp, 1024);
  397. fclose($fp);
  398. $tempItems = array('appname'=>'', 'fields'=>'', 'primarykey'=>'');
  399. $tempItems['appname'] = empty($this->appName) ? "在 {$this->tableName} ".($getTemplets=='add' ? '添加数据' : '编辑数据' ) : $this->appName;
  400. $tempItems['fields'] = '';
  401. $tempItems['self'] = $_SERVER["PHP_SELF"];
  402. if( !preg_match("/,/", $this->primaryKey) )
  403. {
  404. $tempItems['primarykey'] = " <input type=\"hidden\" name=\"{$this->primaryKey}\" value=\"{dede:field name='{$this->primaryKey}' /}\" />\r\n";
  405. }
  406. else
  407. {
  408. $prikeys = explode(',', $this->primaryKey);
  409. $prikeyValue = '<'.'?php echo md5("key"';
  410. foreach($prikeys as $v)
  411. {
  412. $prikeyValue .= '.$fields["'.$v.'"]';
  413. }
  414. $prikeyValue .= '); ?'.'>';
  415. $tempItems['primarykey'] = " <input type=\"hidden\" name=\"primarykey[]\" value=\"{$prikeyValue}\" />\r\n";
  416. }
  417. $fielditem = '';
  418. foreach($this->fields as $k=>$v)
  419. {
  420. $aeform = $dtype = $defaultvalue = $fformat = '';
  421. $title = !empty($v['comment'])? $v['comment'] : $k;
  422. //在指定了字段模板情况下不使用自动生成
  423. if(isset($this->fields[$k][$getTemplets.'template']))
  424. {
  425. $fielditem .= $this->fields[$k][$getTemplets.'template'];
  426. continue;
  427. }
  428. //排除自动递增键
  429. if($k==$this->autoField)
  430. {
  431. continue;
  432. }
  433. //编辑时,排除主键
  434. if($k==$this->primaryKey && $getTemplets=='edit')
  435. {
  436. continue;
  437. }
  438. //格式化选项(编辑时用)
  439. if(isset($this->fields[$k]['format']))
  440. {
  441. $fformat = $this->fields[$k]['format'];
  442. }
  443. //获得字段默认值(编辑时从数据库获取)
  444. if($getTemplets=='edit')
  445. {
  446. if( in_array($this->fields[$k]['type'], $this->binTypes) ) $dfvalue = '';
  447. else $dfvalue = "{dede:field name='$k' /}";
  448. }
  449. else
  450. {
  451. $dfvalue = $this->fields[$k]['default'];
  452. }
  453. //小数类型
  454. if( in_array($this->fields[$k]['type'], $this->floatTypes) )
  455. {
  456. if($getTemplets=='edit')
  457. {
  458. $dfvalue = "{dede:field name='$k' function=\"Lurd::FormatFloat(@me, '$fformat')\" /}";
  459. }
  460. else if($this->fields[$k]['default']=='')
  461. {
  462. $dfvalue = 0;
  463. }
  464. $aeform = "<input type='input' name='{$k}' class='txtnumber' value='$dfvalue' />";
  465. }
  466. //整数类型
  467. if( in_array($this->fields[$k]['type'], $this->intTypes) )
  468. {
  469. $aeform = "<input type='input' name='{$k}' class='txtnumber' value='$dfvalue' />";
  470. }
  471. //时间类型
  472. else if( in_array($this->fields[$k]['type'], $this->dateTypes))
  473. {
  474. if(empty($fformat)) $fformat = 'Y-m-d H:i:s';
  475. if($getTemplets=='edit')
  476. {
  477. $dfvalue = "{dede:field name='$k' function=\"MyDate(@me, '$fformat')\" /}";
  478. }
  479. else if(empty($this->fields[$k]['default']))
  480. {
  481. $dfvalue = "{dede:var.a function=\"MyDate(time(), '$fformat')\" /}";
  482. }
  483. $aeform = "<input type='input' name='{$k}' class='txtdate' value='$dfvalue' />";
  484. }
  485. //长文本类型
  486. else if( in_array($this->fields[$k]['type'], $this->textTypes))
  487. {
  488. $aeform = "<textarea name='$k' class='txtarea'>{$dfvalue}</textarea>";
  489. }
  490. //二进制类型
  491. else if( in_array($this->fields[$k]['type'], $this->textTypes))
  492. {
  493. $aeform = "<input type='file' name='$k' size='45' />";
  494. }
  495. //SET类型
  496. else if( $this->fields[$k]['type']=='SET' )
  497. {
  498. $ems = explode(',', $this->fields[$k]['em']);
  499. if($getTemplets=='edit')
  500. {
  501. $aeform .= '<'.'?php $enumItems = explode(\',\', $fields[\''.$k.'\']); ?'.'>';
  502. }
  503. foreach($ems as $em)
  504. {
  505. if($getTemplets=='add')
  506. {
  507. $aeform .= "<input type='checkbox' name='{$k}[]' value='$em' />$em \r\n";
  508. }
  509. else
  510. {
  511. $aeform .= "<input type='checkbox' name='{$k}[]' value='$em' {dede:if in_array('$em', \$enumItems)}checked{/dede:if} />$em \r\n";
  512. }
  513. }
  514. }
  515. //ENUM类型
  516. else if( $this->fields[$k]['type']=='ENUM' )
  517. {
  518. $ems = explode(',', $this->fields[$k]['em']);
  519. foreach($ems as $em)
  520. {
  521. if($getTemplets=='edit') {
  522. $aeform .= "<input type='radio' name='$k' value='$em' {dede:if \$fields['$k']}=='$em'}checked{/dede:if} />$em \r\n";
  523. }
  524. else {
  525. $aeform .= "<input type='radio' name='$k' value='$em' />$em \r\n";
  526. }
  527. }
  528. }
  529. else
  530. {
  531. $aeform = "<input type='input' name='{$k}' class='txt' value='$dfvalue' />";
  532. }
  533. $fielditem .= " <tr>\r\n<td height='28' align='center' bgcolor='#FFFFFF'>{$title}</td>\r\n<td bgcolor='#FFFFFF'>{$aeform}</td>\r\n</tr>\r\n";
  534. }
  535. $tempItems['fields'] = $fielditem;
  536. foreach($tempItems as $k=>$v)
  537. {
  538. $tempstr = str_replace("~$k~", $v, $tempstr);
  539. }
  540. $fp = fopen($template, 'w');
  541. fwrite($fp, $tempstr);
  542. fclose($fp);
  543. }
  544. // 读取数据
  545. function EditData()
  546. {
  547. $template = $this->templateDir.'/'.$this->tplName.'_edit.htm';
  548. //生成列表模板
  549. if( !file_exists($template) || $this->isDebug )
  550. {
  551. $this->MakeAddEditTemplate('edit');
  552. }
  553. $whereQuery = '';
  554. $GLOBALS[$this->primaryKey] = isset($GLOBALS[$this->primaryKey])? $GLOBALS[$this->primaryKey] : request($this->primaryKey);
  555. if(empty($GLOBALS['primarykey'][0]) && empty($GLOBALS[$this->primaryKey][0]))
  556. {
  557. ShowMsg('请选择要修改的记录!', '-1');
  558. exit();
  559. }
  560. if(preg_match("/,/", $this->primaryKey))
  561. {
  562. $whereQuery = "WHERE md5(CONCAT('key', `".str_replace(',', '`,`', $this->primaryKey)."`) = '{$GLOBALS['primarykey'][0]}' ";
  563. }
  564. else
  565. {
  566. $pkey = (request('get') == 'yes')? request($this->primaryKey) : $GLOBALS[$this->primaryKey][0];
  567. $whereQuery = "WHERE `{$this->primaryKey}` = '".$GLOBALS[$this->primaryKey][0]."' ";
  568. }
  569. //列出数据
  570. $query = "SELECT * FROM `{$this->tableName}` $whereQuery ";
  571. $this->SetTemplate($template);
  572. $this->SetSource($query);
  573. $this->Display();
  574. }
  575. // 新增数据
  576. function AddData()
  577. {
  578. $template = $this->templateDir.'/'.$this->tplName.'_add.htm';
  579. //生成列表模板
  580. if( !file_exists($template) || $this->isDebug )
  581. {
  582. $this->MakeAddEditTemplate('add');
  583. }
  584. //生成发布表单数据
  585. $this->SetTemplate($template);
  586. $this->Display();
  587. exit();
  588. }
  589. // 保存新增数据
  590. function SaveAddData($isturn=TRUE)
  591. {
  592. $allfield = $allvalue = '';
  593. foreach($this->fields as $k=>$v)
  594. {
  595. //自动递增键不处理
  596. if($k==$this->autoField)
  597. {
  598. continue;
  599. }
  600. $allfield .= ($allfield=='' ? "`$k`" : ' , '."`$k`");
  601. $v = $this->GetData($k);
  602. $allvalue .= ($allvalue=='' ? "'$v'" : ' , '."'$v'");
  603. }
  604. $inQuery = "INSERT INTO `$this->tableName`($allfield) VALUES($allvalue); ";
  605. $rs = $this->dsql->ExecuteNoneQuery($inQuery);
  606. //只返回结果
  607. if(!$isturn)
  608. {
  609. return $rs;
  610. }
  611. //完全处理模式
  612. $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
  613. if(!$rs)
  614. {
  615. $this->dsql->SaveErrorLog($inQuery);
  616. ShowMsg('保存数据失败,请检查数据库错误日志!', $gourl);
  617. exit();
  618. }
  619. else
  620. {
  621. ShowMsg('成功保存一组数据!', $gourl);
  622. exit();
  623. }
  624. }
  625. // 保存编辑数据
  626. function SaveEditData($isturn=TRUE)
  627. {
  628. $editfield = '';
  629. foreach($this->fields as $k=>$v)
  630. {
  631. //自动递增键不处理
  632. $GLOBALS[$k] = isset($GLOBALS[$k])? $GLOBALS[$k] : $GLOBALS['request']->forms[$k];
  633. if($k==$this->autoField || !isset($GLOBALS[$k]))
  634. {
  635. continue;
  636. }
  637. $v = $this->GetData($k);
  638. $editfield .= ($editfield=='' ? " `$k`='$v' " : ",\n `$k`='$v' ");
  639. }
  640. //获得主键值
  641. if(preg_match("#,#", $this->primaryKey))
  642. {
  643. $keyvalue = (isset($GLOBALS['primarykey']) ? $GLOBALS['primarykey'] : '');
  644. }
  645. else
  646. {
  647. $keyvalue = $this->GetData($this->primaryKey);
  648. }
  649. $keyvalue = preg_replace("#[^0-9a-z]#i", "", $keyvalue);
  650. if( !preg_match("#,#", $this->primaryKey) )
  651. {
  652. $inQuery = " UPDATE `$this->tableName` SET $editfield WHERE `{$this->primaryKey}`='{$keyvalue}' ";
  653. }
  654. else
  655. {
  656. $inQuery = " UPDATE `$this->tableName` SET $editfield WHERE md5('key', `".str_replace(',','`,`',$this->primaryKey)."`='{$keyvalue}' ";
  657. }
  658. $rs = $this->dsql->ExecuteNoneQuery($inQuery);
  659. //只返回结果
  660. if(!$isturn)
  661. {
  662. return $rs;
  663. }
  664. //完全处理模式
  665. $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
  666. if(!$rs)
  667. {
  668. $this->dsql->SaveErrorLog($inQuery);
  669. ShowMsg('保存数据失败,请检查数据库错误日志!', $gourl);
  670. exit();
  671. }
  672. else
  673. {
  674. ShowMsg('成功保存一组数据!', $gourl);
  675. exit();
  676. }
  677. }
  678. //获得当前网址
  679. function GetCurUrl()
  680. {
  681. if(!empty($_SERVER["REQUEST_URI"]))
  682. {
  683. $nowurl = $_SERVER["REQUEST_URI"];
  684. $nowurls = explode("?",$nowurl);
  685. $nowurl = $nowurls[0];
  686. }
  687. else
  688. {
  689. $nowurl = $_SERVER["PHP_SELF"];
  690. }
  691. return $nowurl;
  692. }
  693. // 删除数据
  694. function DelData($isturn=TRUE)
  695. {
  696. $GLOBALS[$this->primaryKey] = isset($GLOBALS[$this->primaryKey])? $GLOBALS[$this->primaryKey] : request($this->primaryKey);
  697. if(preg_match("#,#", $this->primaryKey))
  698. {
  699. $keyArr = (isset($GLOBALS['primarykey']) ? $GLOBALS['primarykey'] : '');
  700. }
  701. else
  702. {
  703. $keyArr = isset($GLOBALS[$this->primaryKey]) ? $GLOBALS[$this->primaryKey] : '';
  704. }
  705. if(!is_array($keyArr))
  706. {
  707. ShowMsg('没指定要删除的记录!', '-1');
  708. exit();
  709. }
  710. else
  711. {
  712. $isid = !preg_match("#,#", $this->primaryKey) ? TRUE : FALSE;
  713. $i = 0;
  714. foreach($keyArr as $v)
  715. {
  716. $v = preg_replace("#[^0-9a-z]#i", '', $v);
  717. if(empty($v)) continue;
  718. $i++;
  719. if($isid)
  720. {
  721. $this->dsql->ExecuteNoneQuery("DELETE FROM `{$this->tableName}` WHERE `$this->primaryKey`='$v' ");
  722. }
  723. else
  724. {
  725. $this->dsql->ExecuteNoneQuery("DELETE FROM `{$this->tableName}` WHERE md5('key', `".str_replace(',','`,`',$this->primaryKey)."`='$v' ");
  726. }
  727. }
  728. if($isturn)
  729. {
  730. $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
  731. ShowMsg('成功删除指定的记录!', $gourl);
  732. exit();
  733. }
  734. else
  735. {
  736. return $i;
  737. }
  738. }
  739. }
  740. //联结其它表(用于数据查询的情况)
  741. //$tablelurd 目标表lurd对象, $linkfields select的字段
  742. //$mylinkid 当前表用于联结的字段
  743. //$linkid 目标表用于联结的字段
  744. function AddLinkTable(&$tablelurd, $mylinkid, $linkid, $linkfields='*')
  745. {
  746. if(trim($linkfields)=='') $linkfields = '*';
  747. $this->linkTables[] = array($tablelurd, $mylinkid, $linkid, $linkfields);
  748. //记录附加表的字段信息
  749. if($linkfields != '*')
  750. {
  751. $fs = explode(',', $linkfields);
  752. foreach($fs as $f)
  753. {
  754. $f = trim($f);
  755. if(isset($tablelurd->fields[$f]))
  756. {
  757. $this->addFields[$f] = $tablelurd->fields[$f];
  758. $this->addFields[$f]['table'] = $tablelurd->tableName;
  759. }
  760. }
  761. }
  762. else
  763. {
  764. foreach($tablelurd->fields as $k=>$v)
  765. {
  766. $this->addFields[$k] = $v;
  767. $this->addFields[$k]['table'] = $tablelurd->tableName;
  768. }
  769. }
  770. }
  771. //分析表结构
  772. function AnalyseTable()
  773. {
  774. if($this->tableName == '')
  775. {
  776. exit(" No Input Table! ");
  777. }
  778. $this->dsql->Execute('ana', " SHOW CREATE TABLE `{$this->tableName}`; ");
  779. $row = $this->dsql->GetArray('ana', MYSQL_NUM);
  780. if(!is_array($row))
  781. {
  782. exit(" Analyse Table `$tablename` Error! ");
  783. }
  784. // 先去掉内容中的注释
  785. // $row[1] = preg_replace('#COMMENT \'(.*?)\'#i', '', $row[1]);
  786. // echo $row[1];exit;
  787. $flines = explode("\n", $row[1]);
  788. $parArray = array('date', 'float', 'int', 'char', 'text', 'bin', 'em');
  789. $prikeyTmp = '';
  790. for($i=1; $i < count($flines)-1; $i++ )
  791. {
  792. $line = trim($flines[$i]);
  793. $lines = explode(' ', str_replace('`', '', $line));
  794. if( $lines[0] == 'KEY' ) continue;
  795. if( $lines[0] == 'UNIQUE' ) continue;
  796. if( $lines[0] == 'PRIMARY' )
  797. {
  798. $this->primaryKey = preg_replace("/[\(\)]|,$/", '', $lines[count($lines)-1]);
  799. continue;
  800. }
  801. //字段名称、类型
  802. $this->fields[$lines[0]] = array('type' => '', 'length' => '', 'unsigned' => FALSE, 'autokey' => FALSE, 'null' => TRUE, 'default' => '', 'em' => '', 'comment' => '');
  803. $this->fields[$lines[0]]['type'] = strtoupper(preg_replace("/\(.*$|,/", '', $lines[1]));
  804. $this->fields[$lines[0]]['length'] = preg_replace("/^.*\(|\)/", '', $lines[1]);
  805. if(preg_match("#[^0-9]#", $this->fields[$lines[0]]['length']))
  806. {
  807. if($this->fields[$lines[0]]['type'] == 'SET'
  808. || $this->fields[$lines[0]]['type'] == 'ENUM')
  809. {
  810. $this->fields[$lines[0]]['em'] = preg_replace("/'/", '', $this->fields[$lines[0]]['length']);
  811. }
  812. $this->fields[$lines[0]]['length'] = 0;
  813. }
  814. //把特定类型的数据加入数组中
  815. foreach($parArray as $v)
  816. {
  817. $tmpstr = "if(in_array(\$this->fields[\$lines[0]]['type'], \$this->{$v}Types))
  818. {
  819. \$this->{$v}Fields[] = \$lines[0];
  820. }";
  821. eval($tmpstr);
  822. }
  823. if( !in_array($this->fields[$lines[0]]['type'], $this->textTypes)
  824. && !in_array($this->fields[$lines[0]]['type'], $this->binTypes) )
  825. {
  826. $prikeyTmp .= ($prikeyTmp=='' ? $lines[0] : ','.$lines[0]);
  827. }
  828. //分析其它属性
  829. // echo $line;exit;
  830. if(preg_match("#unsigned#i", $line))
  831. {
  832. $this->fields[$lines[0]]['unsigned'] = TRUE;
  833. }
  834. if(preg_match("#auto_increment#i", $line))
  835. {
  836. $this->fields[$lines[0]]['autokey'] = TRUE;
  837. $this->autoField = $lines[0];
  838. }
  839. if(preg_match("#NOT NULL#i", $line))
  840. {
  841. $this->fields[$lines[0]]['null'] = FALSE;
  842. }
  843. if(preg_match("#default#i", $line))
  844. {
  845. preg_match("#default '(.*?)'#i", $line, $dfmatchs);
  846. $this->fields[$lines[0]]['default'] = isset($dfmatchs[1])? $dfmatchs[1] : NULL;
  847. }
  848. if(preg_match("#comment#i", $line))
  849. {
  850. preg_match("#comment '(.*?)'#i", $line, $cmmatchs);
  851. $this->fields[$lines[0]]['comment'] = isset($cmmatchs[1])? $cmmatchs[1] : NULL;
  852. }
  853. }//end for
  854. if( $this->primaryKey=='' )
  855. {
  856. $this->primaryKey = $prikeyTmp;
  857. }
  858. }
  859. /**
  860. * 增加搜索条件
  861. * @parem $fieldname 字段名称
  862. * @parem $fieldvalue 传入的 value 值必须先经过转义
  863. * @parem $condition 条件 >、<、=、<> 、like、%like%、%like、like%
  864. * @parem $linkmode AND 或 OR
  865. */
  866. function AddSearchParameter($fieldname, $fieldvalue, $condition, $linkmode='AND')
  867. {
  868. $c = count($this->searchParameters);
  869. //对于指定了多个字段,使用 CONCAT 进行联结(通常是like操作)
  870. if( preg_match('/,/', $fieldname) )
  871. {
  872. $fs = explode(',', $fieldname);
  873. $fieldname = "CONCAT(";
  874. $ft = '';
  875. foreach($fs as $f)
  876. {
  877. $f = trim($f);
  878. $ft .= ($ft=='' ? "`{$f}`" : ",`{$f}`");
  879. }
  880. $fieldname .= "{$ft}) ";
  881. }
  882. $this->searchParameters[$c]['field'] = $fieldname;
  883. $this->searchParameters[$c]['value'] = $fieldvalue;
  884. $this->searchParameters[$c]['condition'] = $condition;
  885. $this->searchParameters[$c]['mode'] = $linkmode;
  886. }
  887. // 获取搜索条件
  888. function GetSearchQuery()
  889. {
  890. $wquery = '';
  891. if( count( $this->searchParameters ) == 0 )
  892. {
  893. return '';
  894. }
  895. else
  896. {
  897. foreach($this->searchParameters as $k=>$v)
  898. {
  899. if( preg_match("/like/i", $v['condition']) )
  900. {
  901. $v['value'] = preg_replace("/like/i", $v['value'], $v['condition']);
  902. }
  903. $v['condition'] = preg_replace("/%/", '', $v['condition']);
  904. if( $wquery=='' )
  905. {
  906. if(!preg_match("/\./", $v['field'])) $v['field'] = "{$v['field']}";
  907. $wquery .= "WHERE ".$v['field']." {$v['condition']} '{$v['value']}' ";
  908. }
  909. else
  910. {
  911. if(!preg_match("/\./", $v['field'])) $v['field'] = "{$v['field']}";
  912. $wquery .= $v['mode']." ".$v['field']." {$v['condition']} '{$v['value']}' ";
  913. }
  914. }
  915. }
  916. return $wquery ;
  917. }
  918. //把从表单传递回来的数值进行处理
  919. function GetData($fname)
  920. {
  921. $reValue = '';
  922. $ftype = $this->fields[$fname]['type'];
  923. $GLOBALS[$fname] = isset($GLOBALS[$fname])? $GLOBALS[$fname] : @$GLOBALS['request']->forms[$fname];
  924. //二进制单独处理
  925. if( in_array($ftype, $this->binTypes) )
  926. {
  927. return $this->GetBinData($fname);
  928. }
  929. //没有这个变量返回默认值
  930. else if( !isset($GLOBALS[$fname]) )
  931. {
  932. if( isset($this->fields[$fname]['default']) )
  933. {
  934. return $this->fields[$fname]['default'];
  935. }
  936. else
  937. {
  938. if(in_array($ftype, $this->intTypes) || in_array($ftype, $this->floatTypes)) {
  939. return 0;
  940. }
  941. else if(in_array($ftype, $this->charTypes) || in_array($ftype, $this->textTypes)) {
  942. return '';
  943. }
  944. else {
  945. return 'NULL';
  946. }
  947. }
  948. }
  949. //处理整数
  950. else if( preg_match("#YEAR|INT#", $ftype) )
  951. {
  952. // $temp = isset($GLOBALS[$fname][0])? $GLOBALS[$fname][0] : 0;
  953. $negTag = is_int($GLOBALS[$fname]) && $GLOBALS[$fname]< 0 ? '-' : $GLOBALS[$fname];
  954. $reValue = preg_replace("#[^0-9]#", '', $GLOBALS[$fname]);
  955. $reValue = empty($reValue) ? 0 : intval($reValue);
  956. if($negTag=='-' && !$this->fields[$fname]['unsigned']
  957. && $reValue != 0 && $ftype != 'YEAR')
  958. {
  959. $reValue = intval('-'.$reValue);
  960. }
  961. }
  962. //处理小数类型
  963. else if(in_array($ftype, $this->floatTypes))
  964. {
  965. $negTag = $GLOBALS[$fname][0];
  966. $reValue = preg_replace("#[^0-9\.]|^\.#", '', $GLOBALS[$fname]);
  967. $reValue = empty($reValue) ? 0 : doubleval($reValue);
  968. if($negTag=='-' && !$this->fields[$fname]['unsigned'] && $reValue != 0)
  969. {
  970. $reValue = intval('-'.$reValue);
  971. }
  972. }
  973. //字符串类型
  974. else if(in_array($ftype, $this->charTypes))
  975. {
  976. $reValue = cn_substrR($this->StringSafe($GLOBALS[$fname]), $this->fields[$fname]['length']);
  977. }
  978. //文本类型
  979. else if(in_array($ftype, $this->textTypes))
  980. {
  981. $reValue = $this->StringSafe($GLOBALS[$fname]);
  982. }
  983. //SET类型
  984. else if($ftype=='SET')
  985. {
  986. $sysSetArr = explode(',', $this->fields[$fname]['em']);
  987. if( !is_array($GLOBALS[$fname]) )
  988. {
  989. $setArr[] = $GLOBALS[$fname];
  990. }
  991. else
  992. {
  993. $setArr = $GLOBALS[$fname];
  994. }
  995. $reValues = array();
  996. foreach($setArr as $a)
  997. {
  998. if(in_array($a, $sysSetArr)) $reValues[] = $a;
  999. }
  1000. $reValue = count($reValues)==0 ? 'NULL' : join(',', $reValues);
  1001. }
  1002. //枚举类型
  1003. else if($ftype=='ENUM')
  1004. {
  1005. $sysEnumArr = explode(',', $this->fields[$fname]['em']);
  1006. if(in_array($GLOBALS[$fname], $sysEnumArr)) $reValue = $GLOBALS[$fname];
  1007. else $reValue = 'NULL';
  1008. }
  1009. //时间日期类型
  1010. else if(in_array($ftype, $this->dateTypes))
  1011. {
  1012. if($ftype=='TIMESTAMP')
  1013. {
  1014. $reValue = GetMkTime($GLOBALS[$fname]);
  1015. }
  1016. else
  1017. {
  1018. $reValue = preg_replace("#[^0-9 :-]#", '', $GLOBALS[$fname]);
  1019. }
  1020. }
  1021. return $reValue;
  1022. }
  1023. //对请求的字符串进行安全处理
  1024. function StringSafe($str, $safestep=-1)
  1025. {
  1026. $safestep = ($safestep > -1) ? $safestep : $this->stringSafe;
  1027. //过滤危险的HTML(默认级别)
  1028. if($safestep == 1)
  1029. {
  1030. $str = preg_replace("#script:#i", "script:", $str);
  1031. $str = preg_replace("#<[\/]{0,1}(link|meta|ifr|fra|scr)[^>]*>#isU", '', $str);
  1032. $str = preg_replace("#[\r\n\t ]{1,}#", ' ', $str);
  1033. return $str;
  1034. }
  1035. //完全禁止HTML
  1036. //并转换一些不安全字符串(如:eval(、union、CONCAT(、--、等)
  1037. else if($this->stringSafe == 2)
  1038. {
  1039. $str = addslashes(dede_htmlspecialchars(stripslashes($str)));
  1040. $str = preg_replace("#eval#i", 'eval', $str);
  1041. $str = preg_replace("#union#i", 'union', $str);
  1042. $str = preg_replace("#concat#i", 'concat', $str);
  1043. $str = preg_replace("#--#", '--', $str);
  1044. $str = preg_replace("#[\r\n\t ]{1,}#", ' ', $str);
  1045. return $str;
  1046. }
  1047. //不作安全处理
  1048. else
  1049. {
  1050. return $str;
  1051. }
  1052. }
  1053. //保存二进制文件数据
  1054. //为了安全起见,对二进制数据保存使用base64编码后存入
  1055. function GetBinData($fname)
  1056. {
  1057. $lurdtmp = DEDEDATA.'/lurdtmp';
  1058. if(!isset($_FILES[$fname]['tmp_name']) || !is_uploaded_file($_FILES[$fname]['tmp_name']))
  1059. {
  1060. return '';
  1061. }
  1062. else
  1063. {
  1064. $tmpfile = $lurdtmp.'/'.md5( time() . Sql::ExecTime() . mt_rand(1000, 5000) ).'.tmp';
  1065. $rs = move_uploaded_file($_FILES[$fname]['tmp_name'], $tmpfile);
  1066. if(!$rs) return '';
  1067. $fp = fopen($tmpfile, 'r');
  1068. $data = base64_encode(fread($fp, filesize($tmpfile)));
  1069. fclose($fp);
  1070. return $data;
  1071. }
  1072. }
  1073. //格式化浮点数字
  1074. function FormatFloat($fvalue, $ftype='')
  1075. {
  1076. if($ftype=='') $ftype='%0.4f';
  1077. return sprintf($ftype, $fvalue);
  1078. }
  1079. //获得默认时间格式
  1080. function GetDateTimeDf($ftype)
  1081. {
  1082. if($ftype=='DATE') return 'Y-m-d';
  1083. else if($ftype=='TIME') return 'H:i:s';
  1084. else if($ftype=='YEAR') return 'Y';
  1085. else return 'Y-m-d H:i:s';
  1086. }
  1087. //格式化日期
  1088. function FormatDate($fvalue, $ftype, $fformat='')
  1089. {
  1090. if($ftype=='INT' || $ftype='TIMESTAMP' ) return MyDate($fvalue, $fformat);
  1091. else return $fvalue;
  1092. }
  1093. }
  1094. ?>