PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/class.xdstable.inc

https://github.com/jcplat/console-seolan
PHP | 1096 lines | 948 code | 60 blank | 88 comment | 186 complexity | 3aa0d5120c4201877aa3d7a327819cb6 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /// Gestion d'une source de donnees de type 'table SQL'
  3. class XDSTable extends XDataSource {
  4. public $desc = array();
  5. public $orddesc = array();
  6. public $published_fields_in_admin=2;
  7. public $sendacopytofields=array();
  8. function __construct($boid=0) {
  9. XLogs::debug(get_class($this).'::construct: start '.$boid);
  10. $p= new XParam(array(),array());
  11. parent::__construct($boid);
  12. $this->title=XDataSource::$_boid[$boid]->MTXT;
  13. if(!isset(XDataSource::$_boid[$boid]))
  14. XShell::quit($boid.' unknown table ');
  15. else {
  16. $this->translatable = XDataSource::$_boid[$boid]->TRANSLATABLE;
  17. $this->log = XDataSource::$_boid[$boid]->LOG;
  18. $this->autotranslate = XDataSource::$_boid[$boid]->AUTO_TRANSLATE;
  19. }
  20. $this->_getDesc();
  21. XLabels::loadLabels('xdatasource');
  22. $verb='xdatasource('.$this->boid.')';
  23. XAudit::plusplus($verb);
  24. XLogs::debug(get_class($this).'::construct: end '.$boid.', '.$this->title);
  25. }
  26. /// Initialise les options de la source
  27. public function initOptions() {
  28. parent::initOptions();
  29. $group=XLabels::getSysLabel('xdstable','oidstruct');
  30. $this->_options->setOpt(XLabels::getSysLabel('xdstable','oidstruct1'),'oidstruct1','field',array('table'=>$this->base,'compulsory'=>false),null,$group);
  31. $this->_options->setOpt(XLabels::getSysLabel('xdstable','oidstruct2'),'oidstruct2','field',array('table'=>$this->base,'compulsory'=>false),null,$group);
  32. $this->_options->setOpt(XLabels::getSysLabel('xdstable','oidstruct3'),'oidstruct3','field',array('table'=>$this->base,'compulsory'=>false),null,$group);
  33. $this->_options->setGroupComment(XLabels::getSysLabel('xdstable','oidstructcomment'),'oidstruct1');
  34. }
  35. /// Vide la table
  36. public function clear($rq=NULL) {
  37. if(empty($rq) || is_array($rq)) updateQuery('truncate '.$this->base);
  38. else updateQuery('delete from '.$this->base.' where '.$rq);
  39. return array('message'=>XLabels::getSysLabel('xdatasource.update_ok'));
  40. }
  41. function make_cond($def, $v) {
  42. $cond='';
  43. if (!is_array($v)) {
  44. throw new Exception('Parameter must be an array with an operator (index 0) and values (index 1)');
  45. }
  46. $op=$v[0];
  47. if(is_array($op)){
  48. $opfield=$op[0];
  49. $opmultiple=$op[1];
  50. }else{
  51. $opfield=$op;
  52. $opmultiple='or';
  53. }
  54. $k=$def->get_field();
  55. if(count($v)>2) {
  56. array_shift($v);
  57. foreach($v as $v1=>&$v2) {
  58. if($cond!='') $cond.=' '.$opmultiple.' ';
  59. $cond.=$this->make_cond($def,array($v[0],$v1));
  60. }
  61. return '('.$cond.')';
  62. }
  63. if(is_array($v[1])) {
  64. foreach($v[1] as $v1=>$v2) {
  65. if($cond!='') $cond.=' '.$opmultiple.' ';
  66. $cond.=$this->make_cond($def,array($v[0],$v2));
  67. }
  68. return '('.$cond.')';
  69. }
  70. // dans le cas ou le parametre d'un link n'est pas un link on rajoute la table en tete
  71. if($def->isObjectLink() && !empty($v[1]) && ($v[1]!='NULL') && !Kernel::isAKoid($v[1]) && strstr($v[1],'%')==false) {
  72. $v[1]=$def->get_target().':'.$v[1];
  73. }
  74. // traitement sur oid vide
  75. if($def->get_fgender()=='Oid' && $opfield=='=' && ($v[1]=='NULL' || empty($v[1])))
  76. $cond=' ('.$this->base.'.'.$k.'="" or '.$this->base.'.'.$k.' is NULL) ';
  77. // traitement sur oid non vide
  78. elseif($def->get_fgender()=='Oid' && $opfield=='!=' && ($v[1]=='NULL' || empty($v[1])))
  79. $cond=' ('.$this->base.'.'.$k.'!="" and '.$this->base.'.'.$k.' is not NULL) ';
  80. // traitement des valeurs multiples et operateur =
  81. elseif($def->get_multivalued() && $def->get_fgender()=='Oid' && $v[0]=='=')
  82. $cond=' ('.$this->base.'.'.$k.'="'.$v[1].'" or INSTR('.$this->base.'.'.$k.',"||'.$v[1].'||")) ';
  83. // traitement des valeurs avec operateur ==
  84. elseif($def->get_fgender()=='Oid' && $v[0]=='==') {
  85. $v1=$def->get_soid_from_set($v[1]);
  86. $cond=' ('.$this->base.'.'.$k.'="'.$v1.'" or INSTR('.$this->base.'.'.$k.',"||'.$v1.'||")) ';
  87. // traitement des valeurs multiples et operateur !==
  88. } elseif($def->get_multivalued() && $def->get_fgender()=='Oid' && $v[0]=='!==') {
  89. $v1=$def->get_soid_from_set($v[1]);
  90. $cond=' (not('.$this->base.'.'.$k.'="'.$v1.'" or INSTR('.$this->base.'.'.$k.',"||'.$v1.'||"))) ';
  91. // traitement des valeurs non oid
  92. }else{
  93. if($v[1][0]=='=') $cond=' '.$this->base.'.'.$k.' '.$opfield.' '.substr($v[1],1).' ';
  94. else $cond=' '.$this->base.'.'.$k.' '.$opfield.' "'.$v[1].'"';
  95. }
  96. return $cond;
  97. }
  98. function make_simple_cond($k,$v) {
  99. $cond='';
  100. $op=$v[0];
  101. if(is_array($op)){
  102. $opfield=$op[0];
  103. $opmultiple=$op[1];
  104. }else{
  105. $opfield=$op;
  106. $opmultiple='or';
  107. }
  108. if(count($v)>2) {
  109. array_shift($v);
  110. foreach($v as $v1=>&$v2) {
  111. if($cond!='') $cond.=' '.$opmultiple.' ';
  112. $cond.=$this->make_simple_cond($k,array($op,$v2));
  113. }
  114. return '('.$cond.')';
  115. }
  116. if(is_array($v[1])) {
  117. foreach($v[1] as $v1=>$v2) {
  118. if($cond!='') $cond.=' '.$opmultiple.' ';
  119. $cond.=$this->make_simple_cond($k,array($op,$v2));
  120. }
  121. return '('.$cond.')';
  122. }
  123. return ' '.$this->base.'.'.$k.' '.$opfield.' "'.$v[1].'" ';
  124. }
  125. /// generation d'une condition utilisable sur le container
  126. function select_query($args=NULL) {
  127. $params=new XParam($args, array('cond'=>array()));
  128. $LANG_DATA = XShell::getLangData($params->get('LANG_DATA'));
  129. $cond = $args['cond'];
  130. if(empty($cond)) $cond=array();
  131. $selectedfields = @$args['selectedfields'];
  132. if(empty($selectedfields)||($selectedfields=='all')) $selectedfields=array('*');
  133. $where = @$args['where'];
  134. $tr=$this->getTranslatable();
  135. if($tr==TZR_LANG_BASEDLANG) {
  136. $txt="{$this->base}.LANG = '".$LANG_DATA."' ";
  137. } elseif($tr==TZR_LANG_FREELANG) {
  138. $txt="{$this->base}.LANG = '".$LANG_DATA."' ";
  139. } else
  140. $txt="{$this->base}.LANG = '".TZR_DEFAULT_LANG."' ";
  141. if(!empty($where)) $txt.=' AND ('.$where.') ';
  142. $pu=$this->publishedMode($params);
  143. if($pu=='public') {
  144. $txt .= " and {$this->base}.PUBLISH = '1' ";
  145. }
  146. foreach($cond as $k => $v) {
  147. $k1 = trim($k);
  148. if(!empty($this->desc[$k1])) {
  149. $def = $this->desc[$k1];
  150. $txt = $txt.' and '.$this->make_cond($def, $v);
  151. } else {
  152. $txt = $txt.' and '.$this->make_simple_cond($k1, $v);
  153. }
  154. }
  155. $jointcond = NULL;
  156. $order=@$args['order'];
  157. if(!empty($order)) {
  158. $torder=explode(',',$order);
  159. $order=array();
  160. $order=$this->makeOrder($torder,$order,$jointcond);
  161. if(!empty($order)) $txt.=' order by '.$order;
  162. }
  163. if(isset($args['groupby'])) $txt.=' group by '.$args['groupby'];
  164. if(!empty($jointcond)) $query = 'select '.$this->base.'.* from '.$this->base.' '.$jointcond.' where '.$txt;
  165. else $query = 'select '.$this->base.'.* from '.$this->base.' where '.$txt;
  166. return $query;
  167. }
  168. function random_select_query($args=NULL) {
  169. $args['order']='RAND(RAND()*20)';
  170. return $this->select_query($args);
  171. }
  172. function count_query($args=NULL) {
  173. $params=new XParam($args, array('cond'=>array()));
  174. $LANG_DATA = XShell::getLangData();
  175. $cond = $params->get('cond');
  176. $txt="LANG = '$LANG_DATA' ";
  177. foreach($cond as $k=>$v) {
  178. if(!isset($this->desc[$k])) XShell::quit('XDataSource->select_query: field '.$k.' unknown in table '.$this->base);
  179. $def=&$this->desc[$k];
  180. if($def->get_multivalued() && ($def->get_fgender() == 'Oid')
  181. && ($v[0]=='=')) {
  182. $txt=$txt." and (($k = '$v[1]') or ($k like '%||$v[1]||%'))";
  183. } else {
  184. $txt=$txt." and $k $v[0] '$v[1]' ";
  185. }
  186. }
  187. $query = 'select count(KOID) from '.$this->base.' where '.$txt;
  188. return $query;
  189. }
  190. protected function _getDesc($refresh=false) {
  191. $this->desc = array();
  192. $this->orddesc = array();
  193. $orderby=' FORDER ' ;
  194. $lang = XShell::getLangUser();
  195. if($lang!=TZR_DEFAULT_LANG) $lang_cond='(MLANG="'.$lang.'" or MLANG="'.TZR_DEFAULT_LANG.'")';
  196. else $lang_cond="MLANG='".$lang."'";
  197. $rs=selectQuery('select * from DICT,MSGS where DTAB = "'.$this->base.'" and MTAB="'.$this->base.'"'.
  198. ' and '.$lang_cond.' and DICT.FIELD=MSGS.FIELD order by FORDER');
  199. $i=0;
  200. $ors=array();
  201. while($rs && $ors=$rs->fetch()) {
  202. $field = $ors['FIELD'];
  203. if(empty($this->desc[$field]) || (!empty($this->desc[$field]) && ($ors['MLANG']==$lang))) {
  204. $o = (object) $ors;
  205. // si la table n'est pas traduisible, aucun champ ne peut etre traduisible, donc on force cette propriete
  206. if(empty($this->translatable)) $o->TRANSLATABLE=0;
  207. $this->desc[$field] = & XFieldDef::objectFactory($o);
  208. if(!in_array($field, $this->orddesc)) {
  209. $this->orddesc[$i]=$field;
  210. $i++;
  211. }
  212. }
  213. }
  214. $rs->closeCursor();
  215. }
  216. /// verification que la table des archive existe et construction si elle n'existe pas.
  217. protected function checkArchiveTable($createifneeded=true) {
  218. if(XSystem::tableExists('A_'.$this->base)) return true;
  219. updateQuery('CREATE TABLE A_'.$this->base.' AS SELECT * FROM '.$this->base);
  220. return true;
  221. }
  222. /// Insere une nouvelle table SQL
  223. static function procNewSource($ar=NULL) {
  224. global $XSHELL;
  225. global $XLANG;
  226. $error=false;
  227. $p=new XParam($ar,array('user_base'=>1,'translatable'=>0,'auto_translate'=>0,'publish'=>1,'own'=>1),'local');
  228. $bname=$p->get('bname');
  229. $btab=$p->get('btab');
  230. $user_base=$p->get('user_base');
  231. $translatable=$p->get('translatable');
  232. $auto_translate=$p->get('auto_translate');
  233. $publish=$p->get('publish');
  234. $own=$p->get('own');
  235. $bparam=$p->get('bparam');
  236. $classname=$p->get('classname');
  237. if(!empty($auto_translate)) $translate=1;
  238. if(empty($classname)) $classname='XDSTable';
  239. // Controle des donnees obligatoires
  240. if(isSQLKeyword($btab)) {
  241. $message=$btab.' is a SQL keyword';
  242. $error=true;
  243. XLogs::notice('xbaseadm',$message);
  244. } elseif (empty($bname[TZR_DEFAULT_LANG])) {
  245. $message='Table Name is compulsory in default language ! Try again ...';
  246. $error=true;
  247. XLogs::notice('xbaseadm',$message);
  248. } elseif(empty($btab)) {
  249. $message='SQL Table Name is compulsory ! Try again ...';
  250. $error=true;
  251. XLogs::notice('xbaseadm',$message);
  252. } elseif(rewriteToAscii($btab,false)!=$btab) {
  253. $message='SQL Table Name not [A-Za-z0-9_-] checked ! Try again ...';
  254. $error=true;
  255. XLogs::notice('xbaseadm',$message);
  256. } else{
  257. if(self::createTable($btab,$publish,$own)) {
  258. $boid=XDataSourceWd::getNewBoid();
  259. $xml=XOptions::rawToXML($bparam,TZR_ADMINI_CHARSET);
  260. preparedUpdateQuery('INSERT INTO BASEBASE(BOID,BNAME,BTAB,AUTO_TRANSLATE,TRANSLATABLE,BCLASS,BPARAM) '.
  261. 'values(?,?,?,?,?,?,?)', array($boid,$bname[TZR_DEFAULT_LANG],$btab,$auto_translate,
  262. $translatable,$classname,$xml));
  263. $XLANG->getCodes();
  264. for($i=0;$i<$XLANG->nbLang;$i++) {
  265. $code=$XLANG->codes[$i];
  266. $txt=$bname[$code];
  267. if($txt!="") preparedUpdateQuery('INSERT INTO AMSG(MOID,MLANG,MTXT) values (?,?,?)',array($boid,$code,$txt));
  268. }
  269. $message='New table '.$bname[TZR_DEFAULT_LANG].' ('.$btab.') created.';
  270. } else {
  271. $error=true;
  272. $message='Could not create '.$bname[TZR_DEFAULT_LANG].' ('.$btab.').';
  273. }
  274. }
  275. return array('message'=>$message,'error'=>$error);
  276. }
  277. /// Créé une table SQL et son dictionnaire
  278. static function createTable($table,$valid=true,$own=true) {
  279. if(XSystem::tableExists($table)) return false;
  280. $q='CREATE TABLE '.$table.' (KOID varchar(40) DEFAULT \'0\' NOT NULL, LANG char(2) NOT NULL, UPD TIMESTAMP,'.
  281. ($own ?'OWN varchar(40),':'').
  282. ($valid?'PUBLISH tinyint(4) default 1,':'').' PRIMARY KEY (KOID, LANG))';
  283. updateQuery($q);
  284. if(!XSystem::tableExists($table, true)) return false;
  285. // Creation du dictionnaire et de msgs
  286. $order=0;
  287. updateQuery("INSERT INTO DICT values('$table','UPD','XTimestampDef',0,0,0,0,0,1,0,0,'%','')");
  288. updateQuery("INSERT INTO MSGS values('$table','UPD','".TZR_DEFAULT_LANG."','".XLabels::getSysLabel('general','last_update','text')."')");
  289. $order++;
  290. if($own) {
  291. updateQuery("INSERT INTO DICT values('$table','OWN','XLinkDef',0,$order,0,1,0,1,0,0,'USERS','')");
  292. updateQuery("INSERT INTO MSGS values('$table','OWN','".TZR_DEFAULT_LANG."','".XLabels::getSysLabel('general','owner','text')."' )");
  293. $order++;
  294. }
  295. if($valid) {
  296. updateQuery("INSERT INTO DICT values ('$table','PUBLISH','XBoolDef',0,$order,0,0,0,1,0,0,'%','')");
  297. updateQuery("INSERT INTO MSGS values ('$table','PUBLISH','".TZR_DEFAULT_LANG."','".XLabels::getSysLabel('general','approved','text')."')");
  298. $order++;
  299. }
  300. return true;
  301. }
  302. /// Parcours les champs de la table
  303. function browseFields($ar=NULL){
  304. $p=new XParam($ar,NULL);
  305. $refresh=$p->get('refresh');
  306. $addOption = substr($p->get('addOption'), 2); //option additionelle prefixée par __
  307. $this->_getDesc($refresh);
  308. $groups=array();
  309. $allOpts = array();
  310. if(is_array($this->orddesc)) {
  311. foreach($this->orddesc as $o => $field) {
  312. $v=&$this->desc[$field];
  313. $i=array_search($v->fgroup,$groups);
  314. if($i===false){
  315. $i=array_push($groups,$v->fgroup)-1;
  316. }
  317. $tableGroup[$field]='group_'.$i;
  318. //option additionelle
  319. $optUI = '';
  320. foreach ($v->getOptions('addOptions') as $opt) {
  321. $allOpts[$opt['field']] = $opt['label'];
  322. if ($opt['field'] == $addOption) {
  323. $optUI = $opt['edit'];
  324. }
  325. }
  326. $tableAddOption[$field] = $optUI;
  327. }
  328. }
  329. $result=array();
  330. $result['tableObject']=$this->desc;
  331. $result['tableGroup']=$tableGroup;
  332. $result['groups']=$groups;
  333. $result['table']=$this->base;
  334. $result['boid']=$this->boid;
  335. asort($allOpts);
  336. $result['allOpts']=$allOpts;
  337. $result['addOption']=$tableAddOption;
  338. list($types, $labels)=XFieldDef::getTypes();
  339. foreach ($types as $i => $type)
  340. $type_labels[$type] = $labels[$i];
  341. $result['type_labels']=$type_labels;
  342. return $result;
  343. }
  344. /// Prepare la création d'un nouveau champ
  345. function newField($ar=NULL) {
  346. $p=new XParam($ar,NULL);
  347. $fnumber=$this->newFieldName();
  348. $types=XFieldDef::getTypes();
  349. $type=$types[0];
  350. $type_labels=$types[1];
  351. $btranslatable=$this->isTranslatable();
  352. $liste=$this->getBaseList();
  353. reset($liste);
  354. $target_key=array(TZR_DEFAULT_TARGET);
  355. $target_val=array("---");
  356. foreach($liste as $k=>$my) {
  357. $my_xst=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$k);
  358. if($my_xst->isTherePublishedField()) {
  359. $target_key[]=$k;
  360. $target_val[]=$my;
  361. }
  362. }
  363. $forder=$this->newFieldOrder();
  364. $result=array();
  365. $result['table']=$this->base;
  366. $result['boid']=$this->boid;
  367. $result['fnumber']=$fnumber;
  368. $result['type']=$type;
  369. $result['type_labels']=$type_labels;
  370. $result['type_default']='XShortTextDef';
  371. $result['btranslatable']=$btranslatable;
  372. $result['target_key']=$target_key;
  373. $result['target_val']=$target_val;
  374. $result['forder']=$forder;
  375. return $result;
  376. }
  377. /// Enregistre un nouveau champ
  378. public function procNewField($ar=NULL) {
  379. $p=new XParam($ar,NULL);
  380. $field=$p->get('field');
  381. $ftype=$p->get('ftype');
  382. $fcount=$p->get('fcount');
  383. $forder=$p->get('forder');
  384. $compulsory=$p->get('compulsory');
  385. $queryable=$p->get('queryable');
  386. $browsable=$p->get('browsable');
  387. $translatable=$p->get('translatable');
  388. $multivalued=$p->get('multivalued');
  389. $published=$p->get('published');
  390. $label=$p->get('label');
  391. $target=$p->get('target');
  392. $options=$p->get('options');
  393. $options=array_stripslashes($options);
  394. $error=false;
  395. $table=$this->getTable();
  396. // Controle des donnees obligatoires
  397. if(!$this->newFieldDescIsCorrect($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,
  398. $published,$target,$label) ) {
  399. $message='Incorrect description for field '.$label[TZR_DEFAULT_LANG].' ! Try again.<br/>';
  400. $error=true;
  401. }elseif($this->fieldExists($field)){
  402. $message='Field '.$label[TZR_DEFAULT_LANG].' already exists ! Try again ...<br/>';
  403. $error=true;
  404. }else{
  405. $this->newDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,$target,$label,
  406. $options);
  407. $this->sql_newFieldDesc($field);
  408. $this->majUpOtherFieldOrder($field,$forder);
  409. $this->sql_newField($field);
  410. $message='Field '.$label[TZR_DEFAULT_LANG].' created<br/>';
  411. }
  412. XLogs::update('newfield',NULL,$table.':'.$field.' '.$message);
  413. $result=array('message'=>$message,'error'=>$error);
  414. return $result;
  415. }
  416. /// Ajoute un champ du desc dans le dictionnaire
  417. function sql_newFieldDesc($field) {
  418. if(!is_array($this->desc)) return false;
  419. if(empty($this->desc[$field])) return false;
  420. // Insertion dans DICT
  421. $def=$this->desc[$field];
  422. $ftype=$def->get_ftype();
  423. $fcount=$def->get_fcount();
  424. $forder=$def->get_forder();
  425. $compulsory=($def->get_compulsory()?"1":"0");
  426. $queryable=($def->get_queryable()?"1":"0");
  427. $browsable=$def->get_browsable();
  428. $translatable=$def->get_translatable();
  429. $multivalued=$def->get_multivalued();
  430. $published=$def->get_published();
  431. $target=$def->get_target();
  432. $t1=$def->_options->toXML($def);
  433. $dparam=addslashes($t1);
  434. updateQuery('INSERT INTO DICT (DTAB,FIELD,FTYPE,FCOUNT,FORDER,COMPULSORY,QUERYABLE,BROWSABLE,TRANSLATABLE,MULTIVALUED,PUBLISHED,'.
  435. 'TARGET,DPARAM) values ("'.$this->base.'","'.$field.'","'.$ftype.'","'.$fcount.'","'.$forder.'","'.$compulsory.'",'.
  436. '"'.$queryable.'","'.$browsable.'","'.$translatable.'","'.$multivalued.'","'.$published.'","'.$target.'","'.$dparam.'")');
  437. // Insertion des labels dans MSGS
  438. $msg=$def->get_labels();
  439. foreach($msg as $lg=>$m) {
  440. updateQuery('INSERT INTO MSGS (MTAB,FIELD,MLANG,MTXT) values ("'.$this->base.'","'.$field.'","'.$lg.'","'.$m.'")');;
  441. }
  442. return true;
  443. }
  444. /// Ajout du champ dans la table SQL
  445. function sql_newField($field) {
  446. if(!is_array($this->desc)) return false;
  447. if(empty($this->desc[$field])) return false;
  448. $def=$this->desc[$field];
  449. $sqltype=$def->sqltype();
  450. updateQuery('alter table '.$this->base.' add '.$field.' '.$sqltype);
  451. // Ajoute le champ à la table des archives si elle existe
  452. if(XSystem::tableExists('A_'.$this->base)) updateQuery('alter table A_'.$this->base.' add '.$field.' '.$sqltype);
  453. }
  454. /// Prepare la création / l'édition d'un champ
  455. public function editField($ar=NULL) {
  456. GLOBAL $XLANG;
  457. $p=new XParam($ar,NULL);
  458. $LANG_USER=XShell::getLangUser();
  459. $LANG_DATA=XShell::getLangData();
  460. $field=$p->get("field");
  461. $XLANG->getCodes();
  462. if(is_array($XLANG->codes) && is_array($this->desc)) {
  463. $v=$this->desc[$field];
  464. // Labels
  465. $labels=$v->get_labels();
  466. for($myi=0;$myi<$XLANG->nbLang;$myi++) $fnames[$myi]=$labels[$XLANG->codes[$myi]];
  467. // Number
  468. $fnumber=$field;
  469. // Type
  470. $types=XFieldDef::getTypes();
  471. $type=$types[0];// liste des types
  472. $type_labels=$types[1];// liste des libelles
  473. foreach($type as $i=>$ft) {
  474. if($v->get_ftype()==$ft ) $type_selectionFlag[]='selected';
  475. else $type_selectionFlag[]='';
  476. }
  477. $fcount=$v->get_fcount();
  478. $compulsory=$v->get_compulsory();
  479. $queryable=$v->get_queryable();
  480. $browsable=$v->get_browsable();
  481. $btranslatable=$this->isTranslatable();
  482. $translatable=$v->get_translatable();
  483. $multivalued=$v->get_multivalued();
  484. $published=$v->get_published();
  485. $liste=$this->getBaseList();
  486. reset($liste);
  487. $target_key=array(TZR_DEFAULT_TARGET);
  488. $target_val=array('---');
  489. $target_selectionFlag=array('');
  490. foreach($liste as $k=>$my) {
  491. $my_xst=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$k);
  492. if($my_xst->isTherePublishedField()) {
  493. $target_key[]=$k;
  494. $target_val[]=$my;
  495. if($v->get_target()==$k ) $target_selectionFlag[]="selected";
  496. else $target_selectionFlag[]="";
  497. }
  498. }
  499. $forder=$v->get_forder();
  500. $opts=$v->getOptions('options');
  501. $result['options']=$opts;
  502. }
  503. $result['table']=$this->base;
  504. $result['boid']=$this->boid;
  505. $result['field']=$field;
  506. $result['fnames']=$fnames;
  507. $result['fnumber']=$fnumber;
  508. $result['type_selectionFlag']=$type_selectionFlag;
  509. $result['type']=$type;
  510. $result['type_labels']=$type_labels;
  511. $result['fcount']=$fcount;
  512. $result['ftype']=$v->get_ftype();
  513. $result['compulsory']=$compulsory;
  514. $result['queryable']=$queryable;
  515. $result['browsable']=$browsable;
  516. $result['btranslatable']=$btranslatable;
  517. $result['translatable']=$translatable;
  518. $result['multivalued']=$multivalued;
  519. $result['published']=$published;
  520. $result['target_key']=$target_key;
  521. $result['target_val']=$target_val;
  522. $result['target_selectionFlag']=$target_selectionFlag;
  523. $result['forder']=$forder;
  524. return $result;
  525. }
  526. /// Enregistre les modifications sur un champ
  527. function procEditField($ar) {
  528. global $XLANG;
  529. $XLANG->getCodes();
  530. $p=new XParam($ar,array('batch'=>'0','options'=>NULL));
  531. $field=$p->get('field');
  532. $def=$this->desc[$field];
  533. // Pour chaque parametre, on verifie si une nouvelle valeur est spécifiée, sinon on garde l'ancienne
  534. $ftype=$p->get('ftype');
  535. if(!$ftype) $ftype=$def->get_ftype();
  536. $fcount=$p->get('fcount');
  537. if(!$fcount) $fcount=$def->get_fcount();
  538. $forder=$p->get('forder');
  539. if(!empty($forder)) {
  540. $forder = $this->_guessFieldOrder($forder);
  541. } else {
  542. $forder = $def->get_forder();
  543. }
  544. $compulsory=$p->get('compulsory');
  545. $compulsory_hid=$p->get('compulsory_HID');
  546. if(!$compulsory && $compulsory!==false && $compulsory_hid!=2) $compulsory=$def->get_compulsory();
  547. else $compulsory=($compulsory=='on'?1:0);
  548. $queryable=$p->get('queryable');
  549. $queryable_hid=$p->get('queryable_HID');
  550. if(!$queryable && $queryable!==false && $queryable_hid!=2) $queryable=$def->get_queryable();
  551. else $queryable=($queryable=='on'?1:0);
  552. $browsable=$p->get('browsable');
  553. $browsable_hid=$p->get('browsable_HID');
  554. if(!$browsable && $browsable!==false && $browsable_hid!=2) $browsable=$def->get_browsable();
  555. else $browsable=($browsable=='on'?1:0);
  556. $translatable=$p->get('translatable');
  557. $translatable_hid=$p->get('translatable_HID');
  558. if(!$translatable && $translatable!==false && $translatable_hid!=2) $translatable=$def->get_translatable();
  559. else $translatable=($translatable=='on'?1:0);
  560. $multivalued=$p->get('multivalued');
  561. $multivalued_hid=$p->get('multivalued_HID');
  562. if(!$multivalued && $multivalued!==false && $multivalued_hid!=2) $multivalued=$def->get_multivalued();
  563. else $multivalued=($multivalued=='on'?1:0);
  564. $published=$p->get('published');
  565. $published_hid=$p->get('published_HID');
  566. if(!$published && $published!==false && $published_hid!=2) $published=$def->get_published();
  567. else $published=($published=='on'?1:0);
  568. $label=$p->get('label');
  569. $target=$p->get('target');
  570. if(empty($target)) $target=$def->get_target();
  571. $batch=$p->get('batch');
  572. $options=$p->get('options');
  573. $error=false;
  574. // Remplissage des options non definit
  575. $def->_options->procDialog($def,$options);
  576. if(!$this->fieldDescIsCorrect($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,
  577. $target,$label)) {
  578. $message='Incorrect description ! Try again.<br/>';
  579. $error=true;
  580. }else{
  581. $this->sql_changeFieldDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,
  582. $target,$label,$XLANG->codes,$options);
  583. $this->majOtherFieldOrder($field,$def->get_forder(),$forder);
  584. $this->sql_changeField($field,$ftype,$fcount);
  585. $this->changeDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,$target,
  586. $label);
  587. $message.='Field '.$field.' modified.<br/>';
  588. }
  589. // Convertit les données présentes en base si necessaire
  590. $this->desc[$field]->convertValues($def->get_ftype());
  591. // Efface le cache
  592. XDbIni::clear('modules'.$this->base);
  593. // efface le cache des chronos
  594. XDbIni::clear('Chrono%'.$this->base.'%');
  595. return array('message'=>$message,'error'=>$error);
  596. }
  597. /// Modifie un champ du desc dans le dictionnaire
  598. function sql_changeFieldDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,
  599. $target,$label,$langs,$options=NULL) {
  600. $def=$this->desc[$field];
  601. $t1=$def->_options->toXML($def);
  602. preparedUpdateQuery('UPDATE DICT set FTYPE="'.$ftype.'",FCOUNT='.$fcount.',FORDER='.$forder.',COMPULSORY='.$compulsory.','.
  603. 'QUERYABLE='.$queryable.',BROWSABLE='.$browsable.',TRANSLATABLE='.$translatable.',MULTIVALUED='.$multivalued.','.
  604. 'PUBLISHED='.$published.',TARGET="'.$target.'",DPARAM=? where FIELD="'.$field.'" and DTAB="'.$this->base.'"',
  605. array($t1));
  606. $oldlabel=$def->get_labels();
  607. reset($langs);
  608. while(list($k,$l)=each($langs)) {
  609. if($label[$l]!=$oldlabel[$l]){
  610. if($label[$l]!=''){
  611. if(isset($oldlabel[$l]))
  612. preparedUpdateQuery('UPDATE MSGS set MTXT=? where MTAB="'.$this->base.'" and FIELD="'.$field.'" and MLANG="'.$l.'"', array($label[$l]));
  613. else
  614. preparedUpdateQuery('INSERT INTO MSGS (MTAB,FIELD,MLANG,MTXT) values ("'.$this->base.'","'.$field.'","'.$l.'",?)', array($label[$l]));
  615. }else{
  616. updateQuery('DELETE FROM MSGS where MTAB="'.$this->base.'" and FIELD="'.$field.'" and MLANG="'.$l.'"');
  617. }
  618. }
  619. }
  620. }
  621. /// Modifie un champ dans la table SQL
  622. function sql_changeField($field,$ftype,$fcount) {
  623. $def=$this->desc[$field];
  624. if($def->get_ftype()!=$ftype || $def->get_fcount()!=$fcount) {
  625. $t['FTYPE']=$ftype;
  626. $t['FCOUNT']=$fcount;
  627. $t['FIELD']='bidon';
  628. $obj=(object)$t;
  629. $new=&XFieldDef::objectFactory($obj);
  630. $new->set_fcount($fcount);
  631. $sqltype=$new->sqltype();
  632. updateQuery('alter table '.$this->base.' modify '.$field.' '.$sqltype);
  633. // Modifie la table des archives si elle existe
  634. if(XSystem::tableExists('A_'.$this->base)) updateQuery('alter table A_'.$this->base.' modify '.$field.' '.$sqltype);
  635. }
  636. }
  637. /// Suppression d'un champ
  638. function delField($ar=NULL) {
  639. $p=new XParam($ar,NULL);
  640. $field=$p->get('field');
  641. $message='';
  642. $error=false;
  643. if(!$this->deleteIsSafe($message,$field)) {
  644. $message.='<br/>Field $field not deleted. <br/>';
  645. $error=true;
  646. }else{
  647. $def=$this->desc[$field];
  648. // Action specifique sur suppression d'un champ, par exemple suppression des fichier
  649. $def->delfield();
  650. // Suppression du tuple dans les tables
  651. updateQuery('DELETE FROM SETS WHERE STAB="'.$this->base.'" AND FIELD="'.$field.'"');
  652. $this->sql_delFieldDesc($field);
  653. $this->majDownOtherFieldOrder($field,$def->get_forder());
  654. $this->sql_delField($field);
  655. $this->delDesc($field);
  656. // Suppression des droits sur le champ
  657. $mods=XModule::modulesUsingTable($this->base,true,false,false);
  658. if(!empty($mods)) {
  659. foreach($mods as $moid => $name) {
  660. updateQuery('delete from ACL4 where AMOID="'.$moid.'" and AKOID="_field-'.$field.'"');
  661. }
  662. }
  663. // Il n'y a plus de champ de description. Suppression des tuples de data dans Txxx et Kernel et les annexes
  664. if(!count($this->desc)) $this->clear();
  665. $message.='Field '.$field.' '.XLabels::getSysLabel('general.deleted').'.<br/>';
  666. }
  667. XLogs::update('delfield', NULL, $this->base.':'.$field.' '.$message);
  668. XDbIni::clear('modules'.$this->base);
  669. return array('message'=>$message,'error'=>$error);
  670. }
  671. /// Verifie si un champ peut etre supprimé
  672. function deleteIsSafe(&$out,$field) {
  673. // Verifie que ce n'est pas un champ systeme
  674. if(in_array($field,array('UPD','KOID','LANG'))) {
  675. $out='Champ obligatoire : impossible de supprimer';
  676. return false;
  677. }
  678. $def=$this->desc[$field];
  679. $fieldLabel=$def->get_label();
  680. // Le champ est publié
  681. if($def->get_published()) {
  682. // Comptage du nombre de champs published sur la table
  683. if($this->getPublishedFieldCount()==1) {
  684. $links=XDSTable::fieldsUsingTable($this->base);
  685. // Des champs utilisent cette table comme source de données
  686. if(count($links)) {
  687. if(count($this->desc)==1) {
  688. // Le champ est le dernier de la table, il ne peut etre supprimé
  689. $out.='Field '.$fieldLabel.' ('.$field.') is the only published field !<br/>';
  690. $out.='No other field can be set published instead ...<br/>';
  691. $out.='Delete is not safe.<br/>';
  692. return false;
  693. }else{
  694. // Le champ n'est pas le dernier de la table, on met d'office le premier field a published
  695. $rs=selectQuery('select FIELD from DICT where DTAB="'.$this->base.'" and FORDER!='.$def->get_forder().' order by FORDER');
  696. if($ors=$rs->fetch()){
  697. $f=$ors['FIELD'];
  698. $fdef=$this->desc[$f];
  699. $fLabel=$fdef->get_label();
  700. $fdef->set_published(true);
  701. updateQuery('UPDATE DICT set DTAB="'.$this->base.'" and PUBLISHED=1 where FIELD="'.$f.'"');
  702. $out.='Field '.$fieldLabel.' ('.$field.') was the only published field !<br/>';
  703. $out.='Field '.$fLabel.' ('.$f.') is automatically set published instead ...<br/>';
  704. }
  705. $out.='Delete is now safe.<br/>';
  706. }
  707. }
  708. }
  709. }
  710. return true;
  711. }
  712. /// Supprime un champ du desc du dictionnaire
  713. function sql_delFieldDesc($field) {
  714. updateQuery('DELETE FROM DICT where FIELD="'.$field.'" and DTAB="'.$this->base.'"');
  715. updateQuery('DELETE FROM MSGS where MTAB="'.$this->base.'" and FIELD="'.$field.'"');
  716. updateQuery('DELETE FROM AMSG where MOID LIKE "'.$this->base.':'.$field.':%"');
  717. }
  718. // maj des la structure de la table Txxx pour suppression de la colonne Fxxxx
  719. //
  720. function sql_delField($field) {
  721. $def=$this->desc[$field];
  722. // drop column col_name
  723. $requete = "alter table " . $this->base . " drop $field";
  724. updateQuery($requete);
  725. if(XSystem::tableExists('A_'.$this->base)) {
  726. $requete = "alter table A_" . $this->base . " drop $field";
  727. updateQuery($requete);
  728. }
  729. }
  730. /// Met à jour l'ordre des champs dans DICT par le haut
  731. function majUpOtherFieldOrder($field,$forder) {
  732. updateQuery('UPDATE DICT SET FORDER=FORDER+1 where DTAB="'.$this->base.'" and FIELD!="'.$field.'" and FORDER>="'.$forder.'"');
  733. }
  734. /// Met à jour l'ordre des champs dans DICT par le bas
  735. function majDownOtherFieldOrder($field,$forder) {
  736. updateQuery('UPDATE DICT SET FORDER=FORDER-1 where DTAB="'.$this->base.'" and FIELD!="'.$field.'" and FORDER>"'.$forder.'"');
  737. }
  738. /// Met à jour l'ordre des champs dans DICT
  739. function majOtherFieldOrder($field,$oldOrder,$newOrder) {
  740. // Si augmente, -- sur les order > old et <= new
  741. if($newOrder>$oldOrder ){
  742. updateQuery('UPDATE DICT set FORDER=FORDER-1 where DTAB="'.$this->base.'" and FIELD!="'.$field.'" and FORDER>'.$oldOrder.' and '.
  743. 'FORDER<='.$newOrder);
  744. }
  745. // Si diminue, ++ sur les order >= new et < old
  746. if($newOrder<$oldOrder) {
  747. updateQuery('UPDATE DICT set FORDER=FORDER+1 where DTAB="'.$this->base.'" and FIELD!="'.$field.'" and FORDER>='.$newOrder.' and '.
  748. 'FORDER<'.$oldOrder);
  749. }
  750. }
  751. /// Récupère le nombre de champ publié
  752. function getPublishedFieldCount() {
  753. $c = 0;
  754. $requete = "select count(*) from DICT where DTAB='$this->base' and PUBLISHED=".true;
  755. $rs=selectQueryByNum($requete);
  756. $ors=array();
  757. if ( $ors=$rs->fetch() ) $c = $ors[0];
  758. $rs->closeCursor();
  759. return $c;
  760. }
  761. /// Genere un nouveau nom de table
  762. static function newTableNumber($prefix='T',$add=0) {
  763. $tmax=$prefix.'001';
  764. while(1){
  765. if(XSystem::tableExists($tmax,true) || XDataSource::sourceExists($tmax)) $tmax++;
  766. elseif($add){
  767. $tmax++;
  768. $add--;
  769. } else break;
  770. }
  771. return $tmax;
  772. }
  773. /// Prepare la duplication d'une source
  774. public function duplicateDataSource($ar=NULL){
  775. return array('newtable'=>XDSTable::newTableNumber(),'mtxt'=>'- '.$this->getSourceName(),'boid'=>$this->boid);
  776. }
  777. /// Duplique la source
  778. public function procDuplicateDataSource($ar=NULL){
  779. $p=new XParam($ar,array('tplentry'=>''));
  780. $tplentry = $p->get('tplentry');
  781. $bnewtab=$p->get('newtable');
  782. $bnewoid=XDataSourceWd::getNewBoid();
  783. $bnewlib=$p->get('mtxt');
  784. $data=$p->get('data');
  785. $btab=$this->base;
  786. $boid=$this->boid;
  787. if(empty($bnewtab) || (!empty($bnewtab) && XSystem::tableExists($bnewtab))) $bnewtab = XDSTable::newTableNumber();
  788. if(empty($bnewlib)){
  789. $ors=selectQueryGetOne('SELECT * FROM AMSG WHERE MOID="'.$boid.'" LIMIT 0,1');
  790. $bnewlib='- '.$ors['MTXT'];
  791. }
  792. // Duplication du dictionnaire
  793. preparedUpdateQuery("CREATE TEMPORARY TABLE tmpdict AS SELECT * FROM DICT where DTAB=?",array($btab));
  794. preparedUpdateQuery("UPDATE tmpdict set DTAB=?",array($bnewtab));
  795. // Duplication du nom de la table et des commentaires de champ
  796. updateQuery('CREATE TEMPORARY TABLE tmpmsg as select * from AMSG where MOID="'.$boid.'" or MOID REGEXP "^'.$btab.':.+$"');
  797. preparedUpdateQuery('UPDATE tmpmsg set MOID=?,MTXT=? where MOID=?',array($bnewoid,$bnewlib,$boid));
  798. updateQuery('UPDATE tmpmsg set MOID=REPLACE(MOID,"'.$btab.'","'.$bnewtab.'") where MOID REGEXP "^'.$btab.':.+$"');
  799. // Duplications des libelles des champs
  800. updateQuery("CREATE TEMPORARY TABLE tmpmsgs AS SELECT * FROM MSGS WHERE MTAB='$btab'");
  801. updateQuery("UPDATE tmpmsgs SET MTAB='".$bnewtab."'");
  802. updateQuery("CREATE TEMPORARY TABLE tmpsets AS SELECT * FROM SETS WHERE STAB='$btab'");
  803. updateQuery("UPDATE tmpsets set STAB='".$bnewtab."'");
  804. // Duplication de l'entree dans basebase
  805. preparedUpdateQuery('CREATE TEMPORARY TABLE tmpbase AS SELECT * FROM BASEBASE where BOID=?',array($boid));
  806. updateQuery("UPDATE tmpbase set BTAB='".$bnewtab."',BOID='$bnewoid'");
  807. // Create de la table
  808. updateQuery('INSERT INTO DICT select * from tmpdict');
  809. updateQuery('INSERT INTO AMSG select * from tmpmsg');
  810. updateQuery('INSERT INTO MSGS select * from tmpmsgs');
  811. updateQuery("INSERT INTO SETS select SOID, STAB, FIELD, SLANG, STXT, SORDER from tmpsets");
  812. updateQuery('INSERT INTO BASEBASE select * from tmpbase');
  813. updateQuery('CREATE TABLE '.$bnewtab.' like '.$btab);
  814. if($data){
  815. updateQuery('INSERT INTO '.$bnewtab.' (select * from '.$btab.')');
  816. updateQuery('UPDATE '.$bnewtab.' SET UPD=UPD,KOID=replace(KOID,"'.$btab.':","'.$bnewtab.':")');
  817. // copie des donnees
  818. Global $DATA_DIR;
  819. XDir::copy($DATA_DIR.$btab, $DATA_DIR.$bnewtab, true);
  820. }
  821. updateQuery('DROP TEMPORARY TABLE tmpbase');
  822. updateQuery('DROP TEMPORARY TABLE tmpdict');
  823. updateQuery('DROP TEMPORARY TABLE tmpmsg');
  824. updateQuery('DROP TEMPORARY TABLE tmpmsgs');
  825. updateQuery('DROP TEMPORARY TABLE tmpsets');
  826. return array('message'=>'Duplication finished','boid'=>$bnewoid,'table'=>$bnewtab);
  827. }
  828. /// Check/repare la source de donnée
  829. public function chk($ar=NULL) {
  830. $p=new XParam($ar, array("repair"=>false));
  831. $repair=$p->get("repair");
  832. $msg='';
  833. // Verification des index déjà dans XIntegrity::chkDatabases et mieux fait
  834. //updateQuery('alter table '.$this->base.' add primary key(KOID,LANG);');
  835. // Verification des champs
  836. foreach($this->desc as $k=>$v) {
  837. if(!fieldExists($this->base, $k)) $msg.=$this->base.':'.$k.' fields exist in catalog not in table<br>';
  838. else $v->chk($msg);
  839. }
  840. // Verification des langues
  841. $translatable=$this->getTranslatable();
  842. if(!$translatable) {
  843. updateQuery('delete from '.$this->base.' where LANG!="'.TZR_DEFAULT_LANG.'"');
  844. }elseif($translatable!=TZR_LANG_FREELANG) {
  845. $rs=selectQuery('select * from '.$this->base.' where LANG="'.TZR_DEFAULT_LANG.'"');
  846. $ors=array();
  847. while($ors=$rs->fetch()) {
  848. $oid=$ors['KOID'];
  849. $this->propagateOnOtherLangs($oid);
  850. }
  851. }
  852. // Verification des donnnees
  853. $rs=selectQuery('SELECT * FROM '.$this->base);
  854. $ors=array();
  855. while($ors=$rs->fetch()) {
  856. $oid=$ors['KOID'];
  857. $lang=$ors['LANG'];
  858. if(empty($GLOBALS['TZR_LANGUAGES'][$lang])) {
  859. $msg.=$oid.' '.$lang.' '.XLabels::getSysLabel('general.deleted').'<br>';
  860. updateQuery('delete from '.$this->base.' where LANG="'.$lang.'" and KOID="'.$oid.'"');
  861. }
  862. }
  863. return array('message'=>$msg);
  864. }
  865. /// Exporte les champs de la source dans une feuille d'un objet PHPExcel
  866. function exportSpec(&$sheet){
  867. $headers=array('table','forder');
  868. $langs=array_keys($GLOBALS['TZR_LANGUAGES']);
  869. foreach($langs as $lg) $headers[]='label['.$lg.']';
  870. $headers=array_merge($headers,array('field','ftype','fcount','compulsory','queryable','translatable','browsable','multivalued','published','target'));
  871. $rows=array();
  872. $table=$this->getTable();
  873. foreach($this->desc as $fn=>&$f){
  874. $row=array();
  875. $row['table']=$table;
  876. $row['forder']=$f->forder;
  877. $labels=array();
  878. $rs=&selectQuery('select * from MSGS where MTAB="'.$table.'" and FIELD="'.$fn.'" and MLANG in ("'.implode('","',$langs).'")');
  879. while($rs && $ors=$rs->fetch()) $labels[$ors['MLANG']]=$ors['MTXT'];
  880. foreach($langs as $lg) $row['label['.$lg.']']=$labels[$lg];
  881. $row['field']=$f->field;
  882. $row['ftype']=$f->ftype;
  883. $row['fcount']=$f->fcount;
  884. $row['compulsory']=$f->compulsory;
  885. $row['queryable']=$f->queryable;
  886. $row['translatable']=$f->translatable;
  887. $row['browsable']=$f->browsable;
  888. $row['multivalued']=$f->multivalued;
  889. $row['published']=$f->published;
  890. $row['target']=$f->target;
  891. if($row['target']=='%') $row['target']='';
  892. $opts=$f->_options->getAllValues($f, array('for_export' => 1));
  893. $row=array_merge($row,$opts);
  894. foreach($opts as $optn=>$opt) if(!in_array($optn,$headers)) $headers[]=$optn;
  895. $rows[]=$row;
  896. }
  897. foreach($headers as $i=>$h) {
  898. $sheet->setCellValueByColumnAndRow($i, 1, $h);
  899. }
  900. $line=1;
  901. foreach($rows as $row){
  902. $line++;
  903. foreach($headers as $i=>$h){
  904. if(array_key_exists($h,$row)) $sheet->setCellValueByColumnAndRow($i, $line, $row[$h]);
  905. }
  906. }
  907. }
  908. /// Importe les champs de la source via une feuille d'un objet PHPExcel
  909. function importSpec(&$sheet,&$log,$param=array()){
  910. $tables=array();
  911. $reorder=array();
  912. $table=$this->getTable();
  913. $fields=array();
  914. $prefixSQL=($param['prefixSQL']?$param['prefixSQL']:'');
  915. $delallfields=$param['delallfields'];
  916. $delotherfields=$param['delotherfields'];
  917. $oo=array('compulsory','queryable','browsable','translatable','multivalued','published'); // Champs booleen de base
  918. // Suppression de tous les champs non systeme
  919. if(!empty($delallfields)){
  920. foreach($this->desc as $fn=>&$f){
  921. if(!$this->sys) $this->delField(array('field'=>$fn,'action'=>'OK'));
  922. }
  923. $log.='<dd>Suppression de tous les champs non système de la table.</dd>';
  924. }
  925. // Recherche de l'entete
  926. $col=0;
  927. $h=$sheet->getCellByColumnAndRow($col,1)->getValue();
  928. while(!empty($h)) {
  929. $head[$col]=$h;
  930. $col++;
  931. $h=$sheet->getCellByColumnAndRow($col,1)->getValue();
  932. }
  933. unset($h);
  934. $it=$sheet->getRowIterator();
  935. foreach ($it as $ii) {
  936. $i=$ii->getRowIndex();
  937. if($i==1) continue;
  938. $row=array();
  939. foreach($head as $j=>$h) {
  940. $value = $sheet->getCellByColumnAndRow($j,$i)->getValue();
  941. if($value==='') continue;
  942. $pos=strpos($h,'[');
  943. if($pos) $tmp='['.substr($h,0,$pos).']'.substr($h,$pos);
  944. else $tmp='['.$h.']';
  945. $tmp=str_replace(array('[',']'),array("['","']"),$tmp);
  946. utf8_cp1252_replace($value);
  947. if($value==='_empty_') eval('$row'.$tmp.'="";');
  948. else eval('$row'.$tmp.'="'.str_replace('"','\\"',trim($value)).'";');
  949. }
  950. if(empty($row['field'])){
  951. $log.='<dd>Ligne '.$i.' : champ manquant</dd>';
  952. continue;
  953. }
  954. if(!empty($row['table']) && $table!=$prefixSQL.$row['table']) {
  955. continue;
  956. }
  957. $field=$row['field'];
  958. $fields[]=$field;
  959. // Création du champ si il n'existe pas
  960. $row['target']=str_replace('tzrprefix_',$prefixSQL,$row['target']);
  961. if(!fieldExists($table,$field)) {
  962. foreach($oo as $o)
  963. if(empty($row[$o])) $row[$o]=0;
  964. $this->createField($field,'Tmpname',$row['ftype'],$row['fcount'],$row['forder'],$row['compulsory'],$row['queryable'],
  965. $row['browsable'],$row['translatable'],$row['multivalued'],$row['published'],$row['target']);
  966. $log.='<dd>Création du champ/Creating field "'.$field.'"</dd>';
  967. }
  968. // Traitement pour l'edition des différentes options
  969. foreach($row['options'] as $n=>$o){
  970. if($o=='O') $row['options'][$n]=1;
  971. elseif($o=='N') $row['options'][$n]=0;
  972. }
  973. foreach($oo as $o){
  974. if(!empty($row[$o]) && ($row[$o]==1 || $row[$o]=='O')) $row[$o]='on';
  975. else $row[$o]='off';
  976. }
  977. $row['_todo']='save';
  978. if(empty($row['label'][TZR_DEFAULT_LANG])){
  979. $t1=reset($row['label']);
  980. $row['label'][TZR_DEFAULT_LANG]=$t1;
  981. }
  982. $this->procEditField($row);
  983. $reorder[]=array('table'=>$table,'field'=>$field,'order'=>$row['forder']);
  984. $log.='<dd>Modification du champ/Updating field "'.$field.'"</dd>';
  985. }
  986. // Suppression des champs qui ne sont dans la feuille
  987. if(!empty($delotherfields)){
  988. foreach($this->desc as $fn=>&$f){
  989. if(!in_array($fn,$fields) && !$f->sys){
  990. $this->delField(array('field'=>$fn,'action'=>'OK'));
  991. $log.='<dd>Suppression du champ "'.$fn.'"</dd>';
  992. }
  993. }
  994. }
  995. // Reordonne
  996. foreach($reorder as $info){
  997. updateQuery('UPDATE DICT set FORDER='.$info['order'].' where DTAB="'.$info['table'].'" and FIELD="'.$info['field'].'"');
  998. }
  999. }
  1000. /// Ensemble d'actions à effectuer après qu'une modification de donnée ait eu lieu
  1001. protected function updateTasks(&$ar,$oid) {
  1002. if(parent::updateTasks($ar,$oid)){
  1003. if($this->base=='LOGS') return true;
  1004. XDbIni::clear('%|'.$this->base.':usedValues:%');
  1005. XDbIni::clear($this->base.'|%:usedValues:%');
  1006. XDbIni::clear($this->base.':usedValues:%');
  1007. }
  1008. return true;
  1009. }
  1010. /// Génère un oid pour la source
  1011. function getNewOID($ar=NULL){
  1012. // Si l'oid doit être généré à partir des infos d'autres champs
  1013. if($this->oidstruct1){
  1014. $p=new XParam($ar);
  1015. $oid=$p->get($this->oidstruct1);
  1016. if($this->oidstruct2) $oid.='-'.$p->get($this->oidstruct2);
  1017. if($this->oidstruct3) $oid.='-'.$p->get($this->oidstruct3);
  1018. if($oid){
  1019. $oid=substr($this->base.':'.rewriteToAscii($oid),0,40);
  1020. $cnt=countSelectQuery('select COUNT(KOID) from '.$this->base.' where KOID="'.$oid.'"');
  1021. if($cnt){
  1022. $i=0;
  1023. do{
  1024. $i++;
  1025. $tmpoid=substr($oid,0,37).'-'.$i;
  1026. $cnt=countSelectQuery('select COUNT(KOID) from '.$this->base.' where KOID="'.$tmpoid.'"');
  1027. }while($cnt>0);
  1028. $oid=$tmpoid;
  1029. }
  1030. return $oid;
  1031. }
  1032. }
  1033. return parent::getNewOID($ar);
  1034. }
  1035. }
  1036. ?>