国内流行的内容管理系统(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.

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