PageRenderTime 42ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/class.xdatasource.inc

https://github.com/jcplat/console-seolan
PHP | 3190 lines | 2684 code | 219 blank | 287 comment | 733 complexity | 3681a96257cee3e37f34c19afd9aa61d MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /// Classe de base pour la gestion des sources de donnees
  3. class XDataSource implements XModuleContainerInterface {
  4. static $_sources;
  5. protected $base = NULL;
  6. protected $boid = NULL;
  7. protected $title=NULL;
  8. protected $translatable=false;
  9. protected $log=1;
  10. public $desc = array();
  11. public $orddesc = array();
  12. private static $_factory=array();
  13. private static $_factory_by_sourcepath=array();
  14. protected static $_basebase=NULL;
  15. protected static $_boid=array();
  16. public $published_fields_in_admin=2;
  17. public $sendacopytofields=array();
  18. /// construction d'une source de donnee avec un nom de table (legacy) ou un boid
  19. function __construct($boid=0) {
  20. XDataSource::preLoadBaseBase();
  21. if(!empty($boid)) {
  22. $this->boid=$boid;
  23. $this->base=XDataSource::$_boid[$boid]->BTAB;
  24. $this->initOptions();
  25. $param=XOptions::rawFromXML(XDataSource::$_boid[$this->boid]->BPARAM);
  26. $this->_options->setValues($this,$param);
  27. } else {
  28. XLogs::critical('XDataSource::construct', '<'.$boid.'> is empty');
  29. return NULL;
  30. }
  31. }
  32. /// Initialise les options de la source
  33. public function initOptions() {
  34. if(empty($this->_options)) $this->_options=new XOptions();
  35. $this->_options->setId($this->boid);
  36. }
  37. /// Supprime le cache des datasources
  38. static public function clearCache(){
  39. XDataSource::preLoadBaseBase(true);
  40. XDataSource::$_factory=array();
  41. XDataSource::$_factory_by_sourcepath=array();
  42. }
  43. /// chargement en mémoire de la liste des tables et les libellés associés
  44. static function preLoadBaseBase($refresh=false) {
  45. if(empty(XDataSource::$_basebase) || $refresh) {
  46. XLogs::debug('XShell::loadBaseBase: start');
  47. $lang = XShell::getLangUser();
  48. $rs=selectQueryGetAll('select BASEBASE.*,AMSG.* from BASEBASE,AMSG where BASEBASE.BOID=AMSG.MOID and MLANG="'.$lang.'" AND MTXT != ""');
  49. XDataSource::$_basebase=array();
  50. XDataSource::$_boid=array();
  51. foreach($rs as $idx => $o1) {
  52. XDataSource::$_basebase[$o1['BTAB']]=(object)$o1;
  53. XDataSource::$_boid[$o1['BOID']]=&XDataSource::$_basebase[$o1['BTAB']];
  54. }
  55. // Chargement des tables qui ne sont pas traduites
  56. if($lang!=TZR_DEFAULT_LANG) {
  57. $rs=selectQuery('select BASEBASE.*,AMSG.* from BASEBASE,AMSG where BASEBASE.BOID=AMSG.MOID and MLANG="'.TZR_DEFAULT_LANG.'"');
  58. $ors=array();
  59. while($ors=$rs->fetch() ) {
  60. if(empty(XDataSource::$_basebase[$ors['BTAB']])) {
  61. XDataSource::$_basebase[$ors['BTAB']]=(object)$ors;
  62. XDataSource::$_boid[$ors['BOID']]=&XDataSource::$_basebase[$ors['BTAB']];
  63. }
  64. }
  65. $rs->closeCursor();
  66. }
  67. XLogs::debug('XShell::loadBaseBase: end');
  68. }
  69. }
  70. /// Creation d'un objet de type xdatasource via le boid
  71. public static function objectFactory8($boid) {
  72. XLogs::debug('XDataSource::objectfactory8 boid='.$boid);
  73. if(!preg_match('/^[0-9a-f]+$/',$boid)) securityWarning('XDataSource::objectFactory8: Trying to get unauthorized <'.$boid.'>');
  74. XDataSource::preLoadBaseBase();
  75. if(empty(XDataSource::$_boid[$boid])) XDataSource::preLoadBaseBase(true);
  76. $c=XDataSource::$_boid[$boid]->BCLASS;
  77. if(!class_exists($c)) {
  78. XLogs::notice('XDataSource::objectfactory8','class '.$c.' doesn\'t exist');
  79. $c='XDSTable';
  80. }
  81. if(empty(XDataSource::$_factory[$boid])) {
  82. XLogs::debug($c.'::objectFactory8 creating '.$boid);
  83. XDataSource::$_factory[$boid]=new $c($boid);
  84. }
  85. return XDataSource::$_factory[$boid];
  86. }
  87. /// Creation d'un objet de type xdatasource via ses caratéristiques
  88. /// Ex de sourcepath : BCLASS=XDSTable&SPECS=_MLOGS pour recuperer la source de type XDSTable sur la table _MLOGS
  89. public static function objectFactoryHelper8($sourcepath) {
  90. XLogs::debug('XDataSource::objectfactoryHelper8 source='.$sourcepath);
  91. if(isset(XDataSource::$_factory_by_sourcepath[$sourcepath]))
  92. return XDataSource::$_factory_by_sourcepath[$sourcepath];
  93. XDataSource::preLoadBaseBase();
  94. parse_str($sourcepath,$output);
  95. $c=@$output['BCLASS'];
  96. $specs=@$output['SPECS'];
  97. if(Kernel::isAKoid($specs)) $specs=Kernel::getTable($specs);
  98. $boid=XDataSource::getBoidFromSpecs($c, $specs);
  99. if(empty($boid)) return NULL;
  100. return XDataSource::$_factory_by_sourcepath[$sourcepath] = XDataSource::objectFactory8($boid);
  101. }
  102. static function getBoidFromSpecs($class, $spec) {
  103. if(empty(XDataSource::$_basebase[$spec])) XDataSource::preLoadBaseBase(true);
  104. if(empty(XDataSource::$_basebase[$spec])) return NULL;
  105. return XDataSource::$_basebase[$spec]->BOID;
  106. }
  107. static function sysTable($table) {
  108. return in_array($table,array('USERS','GRP','TEMPLATES','LOGS','TASKS','LETTERS','REPLI','JOURNAL','OPTS','_MLOGS','_MLOGSD'));
  109. }
  110. static function notToReplicate($table) {
  111. return in_array($table,array('TASKS','REPLI','JOURNAL'));
  112. }
  113. static function tablesLogStatus() {
  114. XDataSource::preLoadBaseBase(true);
  115. $tablesLogStatus = array();
  116. foreach (XDataSource::$_basebase as $tableName => $tableObject)
  117. $tablesLogStatus[$tableName] = ($tableObject->LOG == 1 && $tableName != 'LOGS');
  118. return $tablesLogStatus;
  119. }
  120. public function &actionlist1() {
  121. $actions = array();
  122. $this->_actionlist($actions);
  123. return $actions;
  124. }
  125. // rend la liste des champs browsables
  126. //
  127. function browsableFields($selectedfields=NULL) {
  128. $fields=array();
  129. foreach($this->desc as $k => &$v) {
  130. if($v->get_browsable() || ($selectedfields=='all')) {
  131. $fields[]=$k;
  132. }
  133. }
  134. return $fields;
  135. }
  136. /// Transforme le résultat d'un formulaire en object requête
  137. function captureQuery($ar=NULL) {
  138. $p=new XParam($ar, array());
  139. $options=$p->get('options');
  140. $_FIELDS=$p->get('_FIELDS');
  141. $st=array();
  142. $st['_date']=mktime();
  143. $st['_table']=$this->base;
  144. $st['options']=$p->get('options');
  145. $st['oids']=$p->get('oids');
  146. $st['operator']=$p->get('operator');
  147. $st['_select']=$p->get('_select');
  148. $st['pagesize']=$p->get('pagesize');
  149. $st['order']=array();
  150. if(!empty($_FIELDS)) {
  151. $st['_querymode']='query2';
  152. $st['_FIELDS']=$_FIELDS;
  153. }else{
  154. $st['_FIELDS']=array();
  155. foreach($this->desc as $k=>&$v) $_FIELDS[$k]=$k;
  156. }
  157. foreach($_FIELDS as $field=>$k) {
  158. $v=&$this->desc[$k];
  159. if(is_object($v)) {
  160. if(!$v->get_queryable()) continue;
  161. $v1=$p->get($field);
  162. $st[$field]=$v1;
  163. $st[$field.'_op']=$p->get($field.'_op');
  164. $st[$field.'_HID']=$p->get($field.'_HID');
  165. $st[$field.'_FMT']=$p->get($field.'_FMT');
  166. $st[$field.'_PAR']=$p->get($field.'_PAR');
  167. $st[$field.'_empty']=$p->get($field.'_empty');
  168. }
  169. }
  170. $order=$p->get('order');
  171. $_order=$p->get('_order');
  172. if(is_array($order)) {
  173. foreach($order as $i=>$f) {
  174. if(!empty($f)) $st['order'][]=trim($order[$i].' '.$_order[$i]);
  175. }
  176. }
  177. return $st;
  178. }
  179. /// prend en entrée une requête stockée ($qinit) et génére les paramètres d'entrée
  180. public function prepareQuery(&$qinit, $storedname=NULL) {
  181. // table dans laquelle se trouvenet les donnees
  182. if(!empty($storedname)) {
  183. $rs=& selectQuery("select * from QUERIES where KOID = '$storedname' and LANG='".TZR_DEFAULT_LANG."'");
  184. $ors=array();
  185. if($ors=$rs->fetch()) {
  186. // fusion du contenu de la recherche sauevardee et de la recherche en cours.
  187. // on prend en priorite le contenu de la requete sauvegardee, qinit sinon
  188. $q1 = unserialize(stripslashes($ors['query']));
  189. $q2=$q1;
  190. foreach($qinit as $k=>$v) {
  191. if(!empty($qinit[$k])) $q2[$k]=$v;
  192. }
  193. $qinit=$q2;
  194. }
  195. }
  196. $selectedfields=array();
  197. $r=NULL;
  198. $r['operator']=@$qinit['operator'];
  199. if(empty($r['operator'])) $r['operator']='and';
  200. $parametrized=false;
  201. $labelin=@$qinit['labelin'];
  202. if(is_array($qinit)) {
  203. foreach($this->desc as $k => &$v) {
  204. if(!empty($qinit[$k.'_PAR'])) {
  205. $parametrized=true;
  206. $selectedfields[]=$k;
  207. unset($qinit[$k]);
  208. unset($qinit[$k.'_op']);
  209. unset($qinit[$k.'_HID']);
  210. unset($qinit[$k.'_PAR']);
  211. unset($qinit[$k.'_FMT']);
  212. if(!empty($labelin)) $qinit['options'][$k]['labelin']=true;
  213. }
  214. }
  215. if(!empty($selectedfields)) {
  216. $r=$this->query(array('tplentry'=>TZR_RETURN_DATA,'selectedfields'=>$selectedfields,
  217. 'searchmode'=>'simple','_preparedquery'=>$qinit, 'fmoid' => $qinit['fmoid']));
  218. }
  219. }
  220. $r['parametrized']=$parametrized;
  221. return $r;
  222. }
  223. /// rend vrai si la base existe
  224. public static function sourceExists($t) {
  225. XDataSource::preLoadBaseBase();
  226. return isset( XDataSource::$_basebase[$t] );
  227. }
  228. /// rend le libelle de la table
  229. public function getLabel() {
  230. return $this->title;
  231. }
  232. /// Rend la table de la source
  233. public function getTable() {
  234. return $this->base;
  235. }
  236. /// Rend le boid de la source
  237. function getBoid(){
  238. return $this->boid;
  239. }
  240. /// Rend le nom de la source
  241. function getSourceName(){
  242. return XDataSource::$_boid[$this->boid]->MTXT;
  243. }
  244. /// Rend un propriété d'une source via la BOID
  245. static function getBoidProp($boid,$prop){
  246. return XDataSource::$_boid[$boid]->$prop;
  247. }
  248. /// Rend un propriété d'une source via le nom de la table
  249. static function getTableProp($table,$prop) {
  250. return XDataSource::$_basebase[$table]->$prop;
  251. }
  252. public function &getPublished($field=true) {
  253. $links=array();
  254. foreach($this->desc as $i => &$v) {
  255. if(is_object($v)) {
  256. $f=$v->get_field();
  257. if($v->get_published()){
  258. if($field) $links[]=$f;
  259. else $links[]=$i;
  260. }
  261. }
  262. }
  263. return $links;
  264. }
  265. public function isTranslatable() {
  266. return ($this->translatable>0);
  267. }
  268. public function getTranslatable() {
  269. return $this->translatable;
  270. }
  271. public function toLog() {
  272. return ($this->base!='LOGS' && $this->log==1);
  273. }
  274. public function getAutoTranslate() {
  275. return $this->autotranslate;
  276. }
  277. /// genere les traductions dans toutes les langues
  278. function autoTranslate() {
  279. if($this->isTranslatable()) {
  280. $xk=new Kernel;
  281. $requete='select distinct KOID from '.$this->base.' where LANG="'.TZR_DEFAULT_LANG.'"';
  282. $rs=selectQuery($requete);
  283. while($rs && ($ors=$rs->fetch())) {
  284. $koid=$ors['KOID'];
  285. $xk->data_autoTranslate($koid);
  286. }
  287. $rs->closeCursor();
  288. }else{
  289. updateQuery('delete from '.$this->base.' where LANG!="'.TZR_DEFAULT_LANG.'"');
  290. }
  291. }
  292. public static function &getBaseList($myselfIncluded=true,$refresh=false) {
  293. XDataSource::preLoadBaseBase($refresh);
  294. $liste = array();
  295. foreach(XDataSource::$_basebase as $b=>&$o) {
  296. $liste[$b]=$o->MTXT;
  297. }
  298. asort($liste);
  299. return $liste;
  300. }
  301. public static function &getBaseList8($myself=true){
  302. XDataSource::preLoadBaseBase();
  303. $liste=array();
  304. foreach(XDataSource::$_boid as $b=>&$o){
  305. if($myself || (!$myself && (empty($this) || $this->boid!=$b)))
  306. $liste[$b]=$o->MTXT;
  307. }
  308. asort($liste);
  309. return $liste;
  310. }
  311. /// Créer une boite de selection de champ
  312. function fieldSelector($ar=NULL) {
  313. $p=new XParam($ar, array('tplentry'=>'','compulsory'=>true,'filter'=>array()));
  314. $tplentry=$p->get('tplentry');
  315. $fieldname=$p->get('fieldname');
  316. $value=$p->get('value');
  317. $type=$p->get('type');
  318. if(!is_array($type) && !empty($type)) $type=array($type);
  319. $compulsory=$p->get('compulsory');
  320. $multivalued=$p->get('multivalued');
  321. $filter=$p->get('filter','local');
  322. if($multivalued) $retval='<select name="'.$fieldname.'[]" size="6" multiple>';
  323. else $retval='<select name="'.$fieldname.'">';
  324. if(!$compulsory) $retval.='<option value="">----</option>';
  325. foreach($this->desc as $k => &$v) {
  326. if(empty($type) || in_array($v->get_ftype(),$type)){
  327. $ok=true;
  328. foreach($filter as $prop=>$val){
  329. if(is_array($val)){
  330. if(!eval('return (\''.$val[1].'\''.$val[0].'\''.$v->$prop.'\');' ) ){
  331. $ok=false;
  332. break;
  333. }
  334. }else{
  335. if($v->$prop!=$val){
  336. $ok=false;
  337. break;
  338. }
  339. }
  340. }
  341. if($ok) $retval.='<option value="'.$k.'" '.(isset($value) && ($value==$k || is_array($value) && in_array($k,$value))?'selected':'')." >". $v->get_label().'</option>';
  342. }
  343. }
  344. $retval.='</select>';
  345. return $retval;
  346. }
  347. function order_selector($ar=NULL) {
  348. $p = new XParam($ar, array('tplentry'=>'','compulsory'=>true,'random'=>true,'multiple'=>false));
  349. $tplentry = $p->get('tplentry');
  350. $LANG_USER = XShell::getLangUser();
  351. $LANG_DATA = XShell::getLangData();
  352. $fieldname=$p->get('fieldname');
  353. $value=$p->get('value');
  354. if(isset($value) && !is_array($value)) $value=array($value);
  355. $random=$p->get('random');
  356. $compulsory=$p->get('compulsory');
  357. $multiple=$p->get('multiple');
  358. $retval='<select name="'.$fieldname.'"'.($multiple?' multiple size="6"':'').'>';
  359. if(!$compulsory) $retval.='<option value="">---</option>';
  360. if($random) $retval.='<option value="RAND()">'.XLabels::getSysLabel('xdatasource.random').'</option>';
  361. foreach($this->desc as $k => $v) {
  362. $retval.='<option value="'.$k.'" '.(isset($value) && in_array($k,$value)?'selected':'').
  363. ' >'. $v->get_label().'</option>';
  364. }
  365. $retval.='</select>';
  366. return $retval;
  367. }
  368. /// rend le descriptif d'un champ
  369. public function getField($f) {
  370. return $this->desc[$f];
  371. }
  372. /// Rend la liste des champs de la table filtres par type et par propriétés
  373. public function &getFieldsList($type=NULL,$browsable=false,$published=false,$queryable=false,$compulsory=false,$translatable=false,
  374. $multivalued=false,$fields=null,$op='AND') {
  375. if(!is_array($fields) || empty($fields)) $fields=$this->orddesc;
  376. $list=array();
  377. $checktype=is_array($type) && !empty($type);
  378. foreach($fields as $i=>$f) {
  379. if(empty($this->desc[$f])) continue;
  380. $v=&$this->desc[$f];
  381. if($op=='AND' && (!$checktype || in_array($v->get_ftype(),$type)) && (!$browsable || $v->get_browsable()) && (!$published || $v->get_published()) && (!$queryable || $v->get_queryable()) && (!$compulsory || $v->get_compulsory()) && (!$translatable || $v->get_translatable()) && (!$multivalued || $v->get_multivalued()))
  382. $list[]=$f;
  383. elseif($op=='OR' && (($checktype && in_array($v->get_ftype(),$type)) || ($browsable && $v->get_browsable()) || ($published && $v->get_published()) || ($queryable && $v->get_queryable()) || ($compulsory && $v->get_compulsory()) || ($translatable && $v->get_translatable()) || ($multivalued && $v->get_multivalued())))
  384. $list[]=$f;
  385. }
  386. return $list;
  387. }
  388. /// Rend les champs indexables
  389. function getIndexablesFields($fields=NULL){
  390. if(!is_array($fields) || empty($fields)) $fields=$this->orddesc;
  391. $list=array();
  392. foreach($fields as $i=>$f) {
  393. if(!isset($this->desc[$f])) continue;
  394. if (isset($this->desc[$f]->indexable) && $this->desc[$f]->indexable == 1)
  395. $list[] = $f;
  396. }
  397. return $list;
  398. }
  399. /// Rend le nombre de champ non traduisible
  400. function getNonTranslatableFieldCount() {
  401. if (!isset($this->_NonTranslatableFieldCount))
  402. $this->_NonTranslatableFieldCount = countSelectQuery("select count(*) from DICT where DTAB='$this->base' and TRANSLATABLE!=1");
  403. return $this->_NonTranslatableFieldCount;
  404. }
  405. /// Fabrique une condition pour une recherche
  406. function make_cond($def, $v){
  407. return '';
  408. }
  409. function make_simple_cond($k, $v) {
  410. return '';
  411. }
  412. /// generation d'une condition utilisable sur le container
  413. function select_query($args=NULL) {
  414. return '';
  415. }
  416. /// Retourne une requete pour retourner des objets aléatoires
  417. function random_select_query($args=NULL) {
  418. return '';
  419. }
  420. /// Retourne une requete pour compter des objects
  421. function count_query($args=NULL) {
  422. return '';
  423. }
  424. // Fonction reservee a la creation d'une data pour la langue par defaut.
  425. // La creation d'une data dans tout autre code langue se fait par Kernel::data_edit() et Kernel::proc_data_edit()
  426. // apres avoir cree une data en l'initialisant avec la data correspondante dans le code langue par defaut.
  427. //
  428. public function input($ar=NULL) {
  429. $p = new XParam($ar, array( 'tplentry'=>$this->base,'hiddenfields'=>array(),'options'=>array(),'fieldssec'=>array()));
  430. $tplentry = $p->get('tplentry');
  431. $options = $p->get('options');
  432. $translatable= $this->getTranslatable();
  433. $fieldssec=$p->get('fieldssec','local');
  434. $module_filter=$p->get('module_filter','local');
  435. $moid=$p->get('fmoid','local');
  436. $selectedfields=$p->get('selectedfields');
  437. $editbatch=$p->get('editbatch');
  438. if(empty($selectedfields) || (is_string($selectedfields) && ($selectedfields=='all'))) $all=true;
  439. else $all=false;
  440. if(empty($selectedfields)) $selectedfields=array();
  441. $lang=XShell::getLangData($p->get('LANG_DATA'));
  442. if(($translatable!=3) && $this->isTranslatable() && ($lang!=TZR_DEFAULT_LANG)) {
  443. if($tplentry!=TZR_RETURN_DATA)
  444. XShell::redirect2error(array('message'=>'Security violation'));
  445. return;
  446. }
  447. $LANG_USER = XShell::getLangUser();
  448. $myi=0;
  449. $ofieldvalue=array();
  450. $osysvalue=array();
  451. foreach($this->orddesc as $i => $k) {
  452. if(!empty($fieldssec[$k]) && $fieldssec[$k]!='rw') continue;
  453. if(!($all || in_array($k,$selectedfields))) continue;
  454. $v=&$this->desc[$k];
  455. $options[$k]['fmoid']=$moid;
  456. $options[$k]['editbatch']=$editbatch;
  457. $options[$k]['module_filter']=$module_filter;
  458. if(!$v->sys) {
  459. $ofieldvalue[$myi]=$v->edit($v->default_value(),$options[$k]);
  460. $result['o'.$k]=$ofieldvalue[$myi];
  461. $myi++;
  462. } else {
  463. $value=$v->edit($v->default_value(),$options[$k]);
  464. $osysvalue[]=$value;
  465. if($k=='PUBLISH' || $k=='PRP') $result['o'.$k]=$value;
  466. }
  467. }
  468. $result['fields_object']= $ofieldvalue;
  469. $result['sysfields_object']= $osysvalue;
  470. $result['newoid']=$this->getNewOID($ar);
  471. $result['tablelabel']=$this->getLabel();
  472. // recherche des groupes de champs
  473. $groups=array();
  474. foreach($this->orddesc as $foo => $k) {
  475. if(!empty($fieldssec[$k]) && $fieldssec[$k]!='rw') continue;
  476. if(!($all || in_array($k,$selectedfields))) continue;
  477. $v=&$this->desc[$k];
  478. if(!$v->sysField()) {
  479. if(empty($v->fgroup)) $v->fgroup='General';
  480. if(!empty($v->fgroup)) {
  481. $groups[$v->fgroup][]=&$result['o'.$k];
  482. }
  483. }
  484. }
  485. ksort($groups);
  486. if(count($groups)>1) $result['_groups']=$groups;
  487. // Information sur le caractere 'translatable' ou non de toute la table
  488. $result['translatable'] = $this->isTranslatable();
  489. return XShell::toScreen1($tplentry, $result);
  490. }
  491. /// génération de l'écran de recherche
  492. public function query($ar=NULL) {
  493. $p = new XParam($ar, array( 'tplentry'=>$this->base,'selectedfields'=>'','searchmode'=>'advanced','querymode'=>'query',
  494. 'operator'=>'AND','genoptions'=>array(),'fieldssec'=>array()));
  495. $LANG_USER = XShell::getLangUser();
  496. $LANG_DATA = XShell::getLangData();
  497. $tplentry = $p->get('tplentry');
  498. $fieldssec=$p->get('fieldssec','local');
  499. $module_filter=$p->get('module_filter','local');
  500. $fmoid = $p->get('fmoid','local');
  501. $persistent=$p->get('_persistent');
  502. $selectedfields=$p->get('selectedfields');
  503. if(empty($selectedfields) || (is_string($selectedfields) && ($selectedfields=='all'))) $all=true;
  504. else $all=false;
  505. if(empty($selectedfields)) $selectedfields=array();
  506. $genoptions=array();
  507. $selectquery='';
  508. // on a une requete preparee qui contraint le formulaire
  509. $preparedquery=$p->get('_preparedquery');
  510. if(!empty($preparedquery)) {
  511. $preparedquery['getselectonly']=true;
  512. $preparedquery['_options']=array('local'=>1);
  513. // on construit la requete sql contraignante
  514. $selectquery=self::procQuery($preparedquery);
  515. if (isset($preparedquery['options']))
  516. $genoptions=$preparedquery['options'];
  517. elseif (isset($preparedquery['genoptions']))
  518. $genoptions=$preparedquery['genoptions'];
  519. }
  520. if ($p->is_set('options'))
  521. $genoptions=array_merge($genoptions,$p->get('options'));
  522. elseif ($p->is_set('genoptions'))
  523. $genoptions=array_merge($genoptions,$p->get('genoptions'));
  524. $searchmode=$p->get('searchmode');
  525. $mode=$p->get('querymode');
  526. $myi=0;
  527. $result=array();
  528. foreach($this->orddesc as $field){
  529. if(!empty($fieldssec[$field]) && $fieldssec[$field]=='none') continue;
  530. $v=&$this->desc[$field];
  531. if(!($v->get_queryable() && ($all || in_array($field,$selectedfields)))) continue;
  532. if(!$persistent){
  533. if(!empty($genoptions[$field]['value'])) {
  534. $initval=$genoptions[$field]['value'];
  535. if(!is_array($initval)) $initval=array($initval);
  536. } else {
  537. $initval=$p->get($field);
  538. if(!is_array($initval)){
  539. $initval=trim($initval);
  540. if(!empty($initval)) $initval=array($initval);
  541. }
  542. }
  543. }else{
  544. $initval=null;
  545. }
  546. if(!empty($genoptions[$field])) $opts1=$genoptions[$field];
  547. else $opts1=array();
  548. $opts1['searchmode']=$searchmode;
  549. // requete contrainte
  550. $opts1['select']=$selectquery;
  551. $opts1['fmoid']=$fmoid;
  552. $opts1['module_filter']=$module_filter;
  553. if(empty($opts1['op'])) $opts1['op']=$p->get($field.'_op');
  554. if($mode=='query2') $opts1['fieldname']='fieldxidxid';
  555. if($mode=='pquery') $ofieldvalue[$myi]=$v->pquery($initval, $opts1);
  556. else $ofieldvalue[$myi]=$v->query($initval, $opts1);
  557. if($mode=='query2') $ofieldvalue[$myi]->html.='<input type="hidden" name="_FIELDS[fieldxidxid]" value="'.$field.'">';
  558. $result['o'.$field]=&$ofieldvalue[$myi];
  559. $fieldpar[$myi]=@$genoptions[$field]['par'];
  560. $fieldname[$myi]=$v->get_label();
  561. $myi++;
  562. }
  563. if($mode=='query2') array_multisort($fieldname,SORT_STRING,$fieldpar,$ofieldvalue);
  564. $result['operator']=$p->get('operator');
  565. $result['fields_object']=&$ofieldvalue;
  566. $result['fields_par']=$fieldpar;
  567. return XShell::toScreen1($tplentry, $result);
  568. }
  569. /// Génération de l'écran de recherche rapide
  570. public function quickquery($ar=NULL) {
  571. $p=new XParam($ar,array('tplentry'=>$this->base,'selectedfields'=>'','genoptions'=>array()));
  572. $tplentry=$p->get('tplentry');
  573. $fields=$p->get('selectedfields');
  574. $fmoid=$p->get('fmoid','local');
  575. $persistent=$p->get('_persistent');
  576. if(!empty($fields) && is_array($fields)) $selectedfields=$fields;
  577. else $selectedfields=self::browsableFields($fields);
  578. $genoptions=$p->get('genoptions');
  579. if($p->is_set('options')) $genoptions=$p->get('options');
  580. $myi=0;
  581. $result=array();
  582. $ofieldvalue=array();
  583. $fieldpar=array();
  584. foreach($this->orddesc as $i => $field){
  585. $v=$this->desc[$field];
  586. if($v->get_queryable() && in_array($field,$selectedfields)) {
  587. $fieldname[$myi]=$v->get_label();
  588. if(!$persistent){
  589. if(!empty($genoptions[$field]['value'])) {
  590. $initval=$genoptions[$field]['value'];
  591. if(!is_array($initval)) $initval=array($initval);
  592. } else {
  593. $initval=$p->get($field);
  594. if(!is_array($initval)){
  595. $initval=trim($initval);
  596. if(!empty($initval)) $initval=array($initval);
  597. }
  598. }
  599. }else{
  600. $initval=NULL;
  601. }
  602. if(empty($genoptions[$field])) $genoptions[$field]=array();
  603. $genoptions[$field]['fmoid']=$fmoid;
  604. $genoptions[$field]['op']=$p->get($field.'_op');
  605. $genoptions[$field]['fields_complement'] = $ar;
  606. $ofieldvalue[$myi]=$v->quickquery($initval, $genoptions[$field]);
  607. $result['o'.$field]=$ofieldvalue[$myi];
  608. $ftable['o'.$field]=$ofieldvalue[$myi];
  609. $fieldpar[$myi]=@$genoptions[$field]['par'];
  610. $myi++;
  611. }
  612. }
  613. $result['operator']=$p->get('operator');
  614. $result['fields_object']=$ofieldvalue;
  615. $result['fields_par']=$fieldpar;
  616. if(!empty($ftable)) $result['fields_ftable']=$ftable;
  617. return XShell::toScreen1($tplentry,$result);
  618. }
  619. /// Verifie si l'oid peut etre traité par la source
  620. function checkOID($oid,&$ar,$f,$return=false){
  621. if(Kernel::getTable($oid)!=$this->base){
  622. if($return) return false;
  623. else securityWarning('XDataSource::'.$f.': Trying to use '.$oid.' with wrong XDataSource <'.$this->base.'>');
  624. }
  625. return true;
  626. }
  627. /// Génère un oid pour la source
  628. function getNewOID($ar=NULL){
  629. return self::getNewBasicOID($this->base);
  630. }
  631. /// Génère un oid au format par defaut pour une table donnée (généré à partir du timestamp avec les µs et d'un nombre aléatoire, chacun converti en base 36)
  632. static function getNewBasicOID($t){
  633. $addr=str_replace('.','', base_convert(microtime(true),10,36));
  634. $addr.=base_convert(rand(1,32000),10,36);
  635. $newoid=substr($t.':'.$addr,0,40);
  636. /* on verifie si le koid n'existe pas deja */
  637. $cnt=countSelectQuery('select COUNT(KOID) from '.$t.' where KOID="'.$newoid.'"');
  638. if(!$cnt) return $newoid;
  639. else return self::getNewBasicOID($t);
  640. }
  641. /// Génère un oid au format spécifique pour une table donnée (simple raccourci pour ne pas instancier soit meme la source pour générer un oid)
  642. static function getNewSpecificOID($t,$ar=NULL){
  643. $xset=XDataSource::objectFactoryHelper8('SPECS='.$t);
  644. return $xset->getNewOID($ar);
  645. }
  646. /// Generation d'un ecran d'edition
  647. function edit($ar=NULL) {
  648. $p=new XParam($ar,array('tplentry'=>$this->base,'options'=>array(),'selectedfields'=>array(),'fieldssec'=>array(),'accesslog'=>0));
  649. $accesslog=$p->get('accesslog');
  650. $tplentry = $p->get('tplentry');
  651. $fieldssec = $p->get('fieldssec','local');
  652. $moid=$p->get('fmoid','local');
  653. $oid=$p->get('oid');
  654. XLogs::debug('XDataSource::edit('.$oid.')');
  655. $this->checkOID($oid,$ar,'edit');
  656. $options=$p->get('options');
  657. if(!empty($GLOBALS['XLOCK'])) {
  658. $mode=$p->get('_mode');
  659. if($mode=='lock') {
  660. $GLOBALS['XLOCK']->lock($oid, TZR_DEFAULT_LANG, XUser::get_current_user_uid());
  661. $GLOBALS['XLOCK']->initLocks();
  662. }
  663. }
  664. $selectedfields=$p->get('selectedfields');
  665. if(!is_array($selectedfields)) {
  666. unset($selectedfields);
  667. $selectedfields=array();
  668. }
  669. $translatable=$this->getTranslatable();
  670. $LANG_DATA=$p->get('LANG_DATA');
  671. if(!$translatable) $LANG_DATA=TZR_DEFAULT_LANG;
  672. else $LANG_DATA=XShell::getLangData($LANG_DATA,true);
  673. $LANG_TRAD = XShell::getLangTrad($p->get('LANG_TRAD'));
  674. $LANG_USER = XShell::getLangUser();
  675. if(($translatable!=TZR_LANG_FREELANG) && !empty($LANG_TRAD) && ($LANG_TRAD!=$LANG_DATA)) {
  676. $ar1=$ar;
  677. $ar1['LANG_DATA']=$LANG_TRAD;
  678. $ar1['tplentry']=TZR_RETURN_DATA;
  679. $result=array();
  680. $result['d']=self::display($ar1);
  681. }
  682. $rs=selectQuery('select * from '.$this->base.
  683. " where KOID='$oid' and LANG='$LANG_DATA'");
  684. // si on ne trouve pas dans la langue en cours on regarde dans la langue de base
  685. if(!$ors=$rs->fetch()) {
  686. $rs->closeCursor();
  687. $rs=selectQuery('select * from '.$this->base.
  688. " where KOID='$oid' and LANG='".TZR_DEFAULT_LANG."'");
  689. $ors=$rs->fetch();
  690. }
  691. $rs->closeCursor();
  692. $myi=0;
  693. foreach($this->desc as $k=>$v) {
  694. if(!empty($selectedfields) && !in_array($k, $selectedfields)) continue;
  695. $options[$k]['oid']=$oid;
  696. $options[$k]['fmoid']=$moid;
  697. if(empty($fieldssec[$k]) || $fieldssec[$k]=='rw') $f='edit';
  698. elseif($fieldssec[$k]=='ro') $f='display';
  699. else continue;
  700. if($LANG_DATA!=TZR_DEFAULT_LANG && $translatable!=TZR_LANG_FREELANG && !$v->get_translatable() && $this->isTranslatable()) $f='display';
  701. $ofieldvalue[$myi]=&$v->$f($ors[$k],$options[$k],$ors);
  702. $fieldequiv[$myi] = $k;
  703. $result['o'.$k]=&$ofieldvalue[$myi];
  704. $myi++;
  705. }
  706. $rs->closeCursor();
  707. $result['oid']= $oid;
  708. $result['fields_object']=&$ofieldvalue;
  709. $result['tablelabel']=$this->getLabel();
  710. if(!empty($GLOBALS['XLOCK'])) {
  711. $result['_lock']=$GLOBALS['XLOCK']->locked($oid, TZR_DEFAULT_LANG);
  712. if(!empty($result['_lock'])) {
  713. $result['_lock_editable']=(empty($result['_lock'])||
  714. (XUser::get_current_user_uid()==$result['_lock']['OWN']));
  715. }
  716. }
  717. // recherche des groupes de champs
  718. $groups=array();
  719. foreach($fieldequiv as $foo => $k) {
  720. $v=&$this->desc[$k];
  721. if(!$v->sysField()) {
  722. if(empty($v->fgroup)) $v->fgroup='General';
  723. if(!empty($v->fgroup)) {
  724. $groups[$v->fgroup][]=&$result['o'.$k];
  725. }
  726. }
  727. }
  728. ksort($groups);
  729. if(count($groups)>1) $result['_groups']=$groups;
  730. // Log
  731. if($accesslog) XLogs::uniqueUpdate('access',$oid);
  732. // Information sur le caractere 'translatable' ou non de toute la table
  733. $result['translatable'] = $this->isTranslatable();
  734. return XShell::toScreen1($tplentry,$result);
  735. }
  736. /// publication d'une donnée (oid) ou d'un ensemble de données (_selected)
  737. public function publish($ar) {
  738. $p=new XParam($ar, array('value'=>1, '_selected'=>NULL,'key'=>true));
  739. $oid=$p->get('oid');
  740. $value=$p->get('value');
  741. $lang=$p->get('LANG_DATA');
  742. $sel = $p->get('_selected');
  743. $key=$p->get('key');
  744. if(is_array($sel) && !$key) $sel=array_flip($sel);
  745. if(empty($sel) && !empty($oid)) $sel=array($oid=>$value);
  746. // traitement de la valeur pour se ramener à 1 (oui) ou 2 (non)
  747. if(empty($value)) $value=2;
  748. if(empty($sel)) return;
  749. foreach($sel as $oid => $val) {
  750. if(Kernel::objectExists($oid)) {
  751. $this->procEdit(array('oid'=>$oid, 'LANG_DATA'=>$lang, 'PUBLISH'=>$value, '_options'=>array('local'=>true)));
  752. }
  753. }
  754. }
  755. /// Affichage d'un objet
  756. public function &display($ar) {
  757. $p=new XParam($ar,array('tplentry'=>$this->base,'_lastupdate'=>XShell::admini_mode(),'genempty'=>1,'selectedfields'=>array(),
  758. 'fieldssec'=>array(),'accesslog'=>0,'tlink'=>false));
  759. $tplentry = $p->get('tplentry');
  760. $fallback = $p->get('fallback');
  761. $publishedonly = $p->get('_publishedonly');
  762. $selectedfields=$p->get('selectedfields');
  763. if(!is_array($selectedfields)) {
  764. unset($selectedfields);
  765. $selectedfields=array();
  766. }
  767. $genempty = $p->get('genempty');
  768. $moid = $p->get('fmoid','local');
  769. $fieldssec = $p->get('fieldssec','local');
  770. $archive = $p->get('_archive');
  771. $accesslog=$p->get('accesslog');
  772. $tlink=$p->get('tlink');
  773. // dans le cas ou la data d'archive est codee en 9999-99-99 99:99:99
  774. // on enleve tous les caracteres non chiffres
  775. if(!empty($archive) && !preg_match('/^([0-9]+)$/',$archive)) $archive=preg_replace('/([^0-9])/','',$archive);
  776. $charset = $p->get('_charset');
  777. $table = $this->base;
  778. $filter='';
  779. $_filter = $p->get('_filter', 'local');
  780. if (!empty($_filter))
  781. $filter = ' AND '.$_filter;
  782. if(!empty($archive)) {
  783. $table='A_'.$this->base;
  784. $filter=" AND UPD='$archive'";
  785. }
  786. $LANG_USER = XShell::getLangUser();
  787. $LANG_DATA = XShell::getLangData($p->get('LANG_DATA','local'));
  788. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  789. $LANG_TRAD = XShell::getLangTrad($p->get('LANG_TRAD'));
  790. $oid = $p->get('oid');
  791. if(empty($oid)) {
  792. $r= 'XDataSource::display: no oid';
  793. return $r;
  794. }
  795. $this->checkOID($oid,$ar,'display');
  796. XLogs::debug('XDataSource::display('.$oid.')');
  797. $options = $p->get('options');
  798. $_format=$p->get('_format');
  799. $_options = $p->get('_options');
  800. $lastupdate = $p->get('_lastupdate');
  801. $genpublishtag= @$_options['genpublishtag'];
  802. $error = @$_options['error'];
  803. $published=$this->publishedMode($p);
  804. if(!isset($genpublishtag)) $genpublishtag=true;
  805. XAudit::plusplus('display('.$table.')');
  806. // Recherche de l'objet en base et génération d'une erreur si introuvable
  807. $rs=selectQuery('SELECT * FROM '.$table.' WHERE KOID="'.$oid.'" AND LANG="'.$LANG_DATA.'" '.$filter);
  808. if(!$ors=$rs->fetch()) {
  809. if($this->isTranslatable() || $fallback) {
  810. $rs->closeCursor();
  811. $rs=selectQuery('SELECT * FROM '.$table.' WHERE KOID="'.$oid.'" AND LANG="'.$LANG_TRAD.'" '.$filter);
  812. if(!$ors=$rs->fetch()) {
  813. if($error=='return') return $r='XDataSource('.$table.')->display: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>';
  814. else XShell::quit('XDataSource('.$table.')->display: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>');
  815. }
  816. } else {
  817. if($error=='return') return $r='XDataSource('.$table.')->display: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>';
  818. else XShell::quit('XDataSource('.$table.')->display: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>');
  819. }
  820. }
  821. $rs->closeCursor();
  822. // Fiche non publié
  823. if($published=='public' && $ors['PUBLISH']!=1) {
  824. if($error=='return') return $r='XDataSource('.$table.')->display: data '.$oid.' has not been published has public<br/>';
  825. else XShell::quit('XDataSource('.$table.')->display: data '.$oid.' has not been published has public<br/>');
  826. }
  827. $result=array();
  828. // Si on est dans l'admin, vérification de la génération du champ publié ou non
  829. if($genpublishtag && XShell::admini_mode() && ($published=='marked')) {
  830. $mark=$ors['PUBLISH'];
  831. if($mark=='1') $pubval='checked';
  832. else $pubval='';
  833. $result['_PUBLISH_tag']='<input type="checkbox" class="checkbox" name="_PUBLISH['.$oid.']" '.$pubval.'/>';
  834. $result['_PUBLISH_tag'].='<input type="hidden" name="_PUBLISH_H['.$oid.']" value="'.$mark.'"/>';
  835. }
  836. // Display sur chaque champ
  837. $result['fields_object']=array();
  838. $result['link']='';
  839. if($tlink) $result['tlink']='';
  840. foreach($this->desc as $k => &$v) {
  841. if((!empty($selectedfields) && !in_array($k, $selectedfields)) || (!empty($fieldssec[$k]) && $fieldssec[$k]=='none')) continue;
  842. if(($v->get_published() && $publishedonly) || !isset($publishedonly)) {
  843. $val=$ors[$k];
  844. // Calcul des options d'affichage
  845. $opt=@$options[$k];
  846. if(!empty($moid)) $opt['fmoid']=$moid;
  847. if($published=='marked' && $ors['PUBLISH']=='2') $opt['_published']=false;
  848. else $opt['_published']=true;
  849. if(!empty($archive)) $opt['_archive']=$archive;
  850. if(!empty($charset)) $opt['_charset']=$charset;
  851. $opt['_format']=$_format;
  852. // Nouvel objet d'affichage
  853. $o=&$v->display($val,$opt);
  854. $result['o'.$k]=$o;
  855. // Construction de fields_object et du lien avec les champs publié
  856. if($genempty || $o->html!='') {
  857. $result['fields_object'][]=$o;
  858. if($v->get_published()) {
  859. if(!empty($result['link'])) $result['link'].=' ';
  860. $result['link'].=$o->html;
  861. if($tlink){
  862. if(!empty($result['tlink'])) $result['tlink'].=' ';
  863. $result['tlink'].=$o->text;
  864. }
  865. }
  866. }
  867. }
  868. }
  869. $result['oid']= $oid;
  870. // Information sur le caractere 'translatable' ou non de toute la table
  871. $result['translatable']=$this->isTranslatable();
  872. if($result['translatable'] && isset($LANG_TRAD)) {
  873. $cnt=countSelectQuery("select COUNT(KOID) from $table where KOID='$oid' and LANG='$LANG_TRAD' $filter");
  874. if($cnt<=0) $result['_translation_ok']='0';
  875. else $result['_translation_ok']='1';
  876. }
  877. // information sur la langue générée
  878. $result['_lang_data']=$LANG_DATA;
  879. if(!empty($LANG_TRAD) && ($LANG_TRAD!=$LANG_DATA)) {
  880. $ar['tplentry']=TZR_RETURN_DATA;
  881. $ar['LANG_DATA']=$LANG_TRAD;
  882. $r2=self::display($ar);
  883. $result['d']=$r2;
  884. }
  885. // Etat du verouillage de la fiche
  886. if(!empty($GLOBALS['XLOCK'])) {
  887. $result['_lock']=$GLOBALS['XLOCK']->locked($oid,$LANG_DATA);
  888. $result['_lock_user'] = $GLOBALS['XLOCK']->getUser($oid,$LANG_DATA);
  889. $result['_lock_editable']=(empty($result['_lock']) || (XUser::get_current_user_uid()==$result['_lock']['OWN']));
  890. }
  891. // Derniere mise à jour
  892. if(!empty($lastupdate)) $result['lst_upd']=XLogs::getLastUpdate($oid,(!empty($result['oUPD'])?$result['oUPD']->raw:NULL));
  893. // Recherche des groupes de champs
  894. $groups=array();
  895. foreach($this->orddesc as $foo => $k) {
  896. $v=&$this->desc[$k];
  897. if(!$v->sysField()) {
  898. if(empty($v->fgroup)) $v->fgroup='General';
  899. if(!empty($v->fgroup) && !empty($result['o'.$k])) $groups[$v->fgroup][]=&$result['o'.$k];
  900. }
  901. }
  902. ksort($groups);
  903. if(count($groups)>1) $result['_groups']=$groups;
  904. // Log
  905. if($accesslog) XLogs::uniqueUpdate('access',$oid);
  906. return XShell::toScreen1($tplentry,$result);
  907. }
  908. /// affichage d'une objet
  909. public function &display2($ar) {
  910. $p = new XParam($ar, array('_lastupdate'=>XShell::admini_mode(),
  911. 'genempty'=>1));
  912. $publishedonly = $p->get('_publishedonly');
  913. $genempty = $p->get('genempty');
  914. $archive = $p->get('_archive');
  915. // dans le cas ou la data d'archive est codee en 9999-99-99 99:99:99
  916. // on enleve tous les caracteres non chiffres
  917. if(!empty($archive) && !preg_match('/^([0-9]+)$/',$archive)) $archive=preg_replace('/([^0-9]+)/','',$archive);
  918. $charset = $p->get('_charset');
  919. $table = $this->base;
  920. $filter='';
  921. if(!empty($archive)) {
  922. $table='A_'.$this->base;
  923. $filter=" AND UPD='$archive' ";
  924. }
  925. $LANG_USER = XShell::getLangUser();
  926. $LANG_DATA = XShell::getLangData($p->get('LANG_DATA','local'));
  927. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  928. $oid = $p->get('oid');
  929. XLogs::debug('XDataSource::display2('.$oid.')');
  930. $r=array();
  931. if(empty($oid)) return $r;
  932. $this->checkOID($oid,$ar,'display2');
  933. $options = $p->get('options');
  934. $_format=$p->get('_format');
  935. $_options = $p->get('_options');
  936. $lastupdate = $p->get('_lastupdate');
  937. $genpublishtag=@$_options['genpublishtag'];
  938. $published=$this->publishedMode($p);
  939. if(!isset($genpublishtag)) $genpublishtag=true;
  940. $verb='display2('.$table.')';
  941. XAudit::plusplus($verb);
  942. $rs=selectQuery("SELECT * FROM $table WHERE KOID='$oid' AND LANG='$LANG_DATA' $filter");
  943. if(!$ors=$rs->fetch()) {
  944. return $r;
  945. }
  946. $rs->closeCursor();
  947. if(($published=='public') && ($ors['PUBLISH']!=1)) {
  948. return $r;
  949. }
  950. $result=array();
  951. // si on est dans l'admin, vérification de la génération du champ publié ou non
  952. if($genpublishtag && XShell::admini_mode() && ($published=='marked')) {
  953. $mark=$ors['PUBLISH'];
  954. if($mark=='1') $pubval='checked';
  955. else $pubval='';
  956. $result['_PUBLISH_tag']='<input type="checkbox" class="checkbox" name="_PUBLISH['.$oid.']" '.$pubval.'/>';
  957. $result['_PUBLISH_tag'].='<input type="hidden" name="_PUBLISH_H['.$oid.']" value="'.$mark.'"/>';
  958. }
  959. $myi=0;
  960. $link='';
  961. $tlink='';
  962. foreach($this->desc as $k => &$v) {
  963. if(($v->get_published() && $publishedonly)||!isset($publishedonly)) {
  964. $val = $ors[$k];
  965. // calcul des options d'affichage
  966. $opt = $options[$k];
  967. if(($published=='marked') && ($ors['PUBLISH']=='2'))
  968. $opt['_published']=false;
  969. else
  970. $opt['_published']=true;
  971. if(!empty($archive))
  972. $opt['_archive']=$archive;
  973. $opt['_format']=$_format;
  974. if(!empty($charset)) {
  975. $opt['_charset']=$charset;
  976. }
  977. // nouvel objet d'affichage
  978. $o=&$v->display($val,$opt);
  979. $result['o'.$k]=$o;
  980. if($genempty || ($o->html!='')) {
  981. $result['fields_object'][$myi]=$o;
  982. $result[$k]=$o->html;
  983. $result['fields_field'][$myi]=$k;
  984. $myi++;
  985. if($v->get_published()) {
  986. if(!empty($link)) {
  987. $link.=' ';
  988. $tlink.=' ';
  989. }
  990. $link.=$o->html;
  991. $tlink.=$o->text;
  992. }
  993. }
  994. }
  995. }
  996. $result['link']=$link;
  997. $result['tlink']=$tlink;
  998. $result['oid']= $oid;
  999. if(!empty($lastupdate)) {
  1000. $result['lst_upd']=XLogs::getLastUpdate($oid);
  1001. }
  1002. XLogs::debug('XDataSource::display2: end '.$oid);
  1003. return $result;
  1004. }
  1005. public function &rDisplayText($oid, $LANG_DATA='', $LANG_USER='', $opts=array()) {
  1006. if(empty($LANG_USER)) $LANG_USER=XShell::getLangUser();
  1007. if(empty($LANG_DATA)) $LANG_DATA=XShell::getLangData();
  1008. $fallback = true;
  1009. $table = $this->base;
  1010. $charset=@$opts['_charset'];
  1011. $_format=@$opts['_format'];
  1012. $fmoid=@$opts['fmoid'];
  1013. $selectedfields=@$opts['selectedfields'];
  1014. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  1015. $verb='rDisplayText('.$table.')';
  1016. XAudit::plusplus($verb);
  1017. if(is_array($oid)) {
  1018. $ors=$oid;
  1019. $oid=$ors['KOID'];
  1020. } else {
  1021. $p=new XParam(array(),NULL);
  1022. $rs=&selectQuery('SELECT * FROM '.$table.' WHERE KOID="'.$oid.'" AND LANG="'.$LANG_DATA.'"');
  1023. if(!$ors=$rs->fetch()) {
  1024. $ret='XDataSource('.$table.')::rDisplayText: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>';
  1025. XLogs::critical('rDisplayText',$ret);
  1026. return $ret;
  1027. }elseif($this->publishedMode($p)=='public' && array_key_exists('PUBLISH',$ors) && $ors['PUBLISH']!=1){
  1028. XLogs::critical('rDisplayText', 'XDataSource('.$table.')::rDisplayText: Unpublished object with oid='.$oid.' and lang='.$LANG_DATA);
  1029. return $ret='UNPUBLISHED';
  1030. }
  1031. $rs->closeCursor();
  1032. }
  1033. $result=array();
  1034. $myi=0;
  1035. $tlink='';
  1036. foreach($this->desc as $k => &$v) {
  1037. if($selectedfields == 'all' || $v->get_published() || (!empty($selectedfields) && in_array($k,$selectedfields))) {
  1038. $val = $ors[$k];
  1039. // calcul des options d'affichage
  1040. if(isset($options[$k])) $opt = $options[$k];
  1041. else $opt=array();
  1042. if(!empty($fmoid)) $opt['fmoid']=$fmoid;
  1043. $opt['_published']=true;
  1044. $opt['_format']=$_format;
  1045. if(!empty($charset)) {
  1046. $opt['_charset']=$charset;
  1047. }
  1048. // nouvel objet d'affichage
  1049. $o=&$v->display($val,$opt);
  1050. if(!empty($tlink)) $tlink.=" ";
  1051. $tlink.=$o->toText();
  1052. }
  1053. }
  1054. $result['link']=$tlink;
  1055. $result['oid']= $oid;
  1056. return $result;
  1057. }
  1058. /**
  1059. * generation d'infos d'affichage simplifiees a partir d'un oid
  1060. * utilisé en particulier pour le display des champs liens
  1061. * @param KOID $oid
  1062. * @param PDO_STATEMENT $ors si renseigné écrase l'oid par $ors['KOID'], (utilisé ?)
  1063. * @param bool $publishedonly retourner uniquement les champs publiés
  1064. * @param string $LANG_DATA
  1065. * @param string $LANG_USER
  1066. * @param $opts [ tableau d'options indirectes
  1067. * selectedfields : tableau des champs sql à calculer (ou 'all')
  1068. * ...
  1069. * ]
  1070. * @return array [
  1071. * array fields_object : array of XFieldVal Object, integer key
  1072. * XFieldVal Object ofield : pour chaque champ retourné
  1073. * string link : représentation html
  1074. * KOID oid
  1075. * bool translatable
  1076. * ]
  1077. */
  1078. public function &rDisplay($oid,$ors=array(),$publishedonly=false,$LANG_DATA='',$LANG_USER='',$opts=array()) {
  1079. if(empty($LANG_USER)) $LANG_USER=XShell::getLangUser();
  1080. if(empty($LANG_DATA)) $LANG_DATA=XShell::getLangData();
  1081. $table=$this->base;
  1082. $charset=@$opts['_charset'];
  1083. $_format=@$opts['_format'];
  1084. $fmoid=@$opts['fmoid'];
  1085. $lastupdate=@$opts['_lastupdate'];
  1086. $selectedfields=@$opts['selectedfields'];
  1087. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  1088. XLogs::debug('XDataSource::rDisplay('.$oid.')');
  1089. XAudit::plusplus('rDisplay('.$table.')');
  1090. if(!empty($ors)) {
  1091. $oid=$ors['KOID'];
  1092. } else {
  1093. $ar=array();
  1094. $p=new XParam($ar,NULL);
  1095. $rs=selectQuery('SELECT * FROM '.$table.' WHERE KOID="'.$oid.'" AND LANG="'.$LANG_DATA.'"');
  1096. if(!$rs || !$ors=$rs->fetch()){
  1097. $ret='XDataSource('.$table.')::rDisplay: could not find object with oid='.$oid.' and lang='.$LANG_DATA.'<br/>';
  1098. XLogs::critical('rDisplay',$ret);
  1099. return $ret;
  1100. }elseif($this->publishedMode($p)=='public' && array_key_exists('PUBLISH',$ors) && $ors['PUBLISH']!=1){
  1101. XLogs::critical('rDisplay', 'XDataSource('.$table.')::rDisplay: Unpublished object with oid='.$oid.' and lang='.$LANG_DATA);
  1102. return $ret='UNPUBLISHED';
  1103. }
  1104. $rs->closeCursor();
  1105. }
  1106. $link='';
  1107. $result=array('fields_object'=>array());
  1108. foreach($this->desc as $k => &$v) {
  1109. if($selectedfields == 'all' || (($v->get_published() && $publishedonly) || !$publishedonly) && (empty($selectedfields) || in_array($k,$selectedfields))) {
  1110. $val = $ors[$k];
  1111. // calcul des options d'affichage
  1112. if(isset($opts[$k])) $opt = $opts[$k];
  1113. else $opt=array();
  1114. if(!empty($fmoid)) $opt['fmoid']=$fmoid;
  1115. if (empty($opt['selectedfields']))
  1116. $opt['_published']=true;
  1117. $opt['_format']=$_format;
  1118. if(!empty($charset)) $opt['_charset']=$charset;
  1119. // Nouvel objet d'affichage
  1120. $o=&$v->display($val,$opt);
  1121. $result['o'.$k]=$o;
  1122. $result['fields_object'][]=$o;
  1123. if($v->get_published()) {
  1124. if(!empty($link)) $link.=' ';
  1125. $link.=$o->html;
  1126. }
  1127. }
  1128. }
  1129. $result['link']=$link;
  1130. $result['oid']=$oid;
  1131. // Derniere mise à jour
  1132. if(!empty($lastupdate)) $result['lst_upd']=XLogs::getLastUpdate($oid,$result['oUPD']->raw);
  1133. // Information sur le caractere 'translatable' ou non de toute la table
  1134. $result['translatable']=$this->isTranslatable();
  1135. return $result;
  1136. }
  1137. /// Affichage d'une donnee dont l'oid est $oid, via la methode rdisplay
  1138. public static function objectDisplayHelper($oid) {
  1139. $x=XDataSource::objectFactoryHelper8('SPECS='.$oid);
  1140. if(!empty($x) && Kernel::objectExists($oid)) return $x->display(array('oid'=>$oid));
  1141. else return NULL;
  1142. }
  1143. /****m* XDataSource/fdisplay
  1144. * NAME
  1145. * XDataSource::fdisplay - affichage detaille d'un champ
  1146. * DESCRIPTION
  1147. * Permet d'afficher le contenu detaille d'un champ, fonction utilisée
  1148. * principalement pour l'affichage detaille.
  1149. ****/
  1150. public function fdisplay($ar) {
  1151. $p = new XParam($ar, array('tplentry'=>$this->base,
  1152. // liste des champs qui seront affichés sur des liens
  1153. // si on ne veut pas prendre les published par defaut
  1154. 'genempty'=>1));
  1155. $tplentry = $p->get('tplentry');
  1156. $field = $p->get('field');
  1157. $LANG_USER = XShell::getLangUser();
  1158. $LANG_DATA = XShell::getLangData($p->get('LANG_DATA'));
  1159. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  1160. $verb='fdisplay('.$this->base.')';
  1161. XAudit::plusplus($verb);
  1162. $ar['tplentry']=TZR_RETURN_DATA;
  1163. $r=self::display($ar);
  1164. XShell::toScreen2($tplentry, 'field', $r['o'.$field]);
  1165. }
  1166. /*****
  1167. Fonction : XDataSource::gen_random_display_mask()
  1168. Description : Display d'1 tuple pris aléatoirement.
  1169. *****/
  1170. function gen_random_display_mask($ar=NULL) {
  1171. $query = $this->random_select_query($ar);
  1172. $rs=selectQuery($query);
  1173. $ors=array();
  1174. if ( $ors=$rs->fetch()) $oid = $ors['KOID'];
  1175. $ar['oid'] = $oid;
  1176. $this->display($ar);
  1177. $rs->closeCursor();
  1178. }
  1179. // Fonction reservee a la creation d'une data pour la langue par defaut.
  1180. // La creation d'une data dans tout autre code langue se fait par Kernel::data_edit() et Kernel::proc_data_edit()
  1181. // apres avoir cree une data en l'initialisant avec la data correspondante dans le code langue par defaut.
  1182. //
  1183. public function procInput($ar=NULL) {
  1184. $this->preUpdateTasks($ar);
  1185. $p=new XParam($ar, array('tplentry'=>$this->base,'_inputs'=>array(),'options'=>array()));
  1186. $tplentry = $p->get('tplentry');
  1187. $j=$p->get('_nojournal');
  1188. $journal=empty($j);
  1189. $moid=$p->get('fmoid','local');
  1190. $nolog=$p->get('_nolog','local');
  1191. $all=$p->get('_allfields');
  1192. $fieldssec=$p->get('fieldssec','local');
  1193. $delayed=$p->get('_delayed');
  1194. if(!empty($delayed)) $delayed='LOW_PRIORITY ';
  1195. else $delayed='';
  1196. $options=$p->get('options');
  1197. // Si option est un champ
  1198. if(is_string($options)) $options=array();
  1199. $unique=$p->get('_unique');
  1200. $updateifexists = $p->get('_updateifexists');
  1201. $unique_val = array();
  1202. $insert = true;
  1203. $jn='';
  1204. // Nouvel oid puisqu'on cree une nouvelle data en langue par defaut
  1205. $oid=$p->get('newoid'); // permet d'imposer le KOID
  1206. if(!empty($oid) && empty($updateifexists)) {
  1207. $cnt=countSelectQuery("select COUNT(KOID) from {$this->base} where KOID='$oid' limit 1");
  1208. if($cnt) {
  1209. XLogs::notice('XDataSource::procInput', $oid.' already exist');
  1210. return array('error'=>true,'message'=>$oid.' already exist');
  1211. }
  1212. }
  1213. if(empty($oid)) $oid=$this->getNewOID($ar);
  1214. else $this->checkOID($oid,$ar,'procInput');
  1215. // traitement des langues
  1216. $translatable = $this->getTranslatable();
  1217. if(!$this->isTranslatable()) $lang=TZR_DEFAULT_LANG;
  1218. elseif($translatable==3)
  1219. $lang=XShell::getLangData($p->get('LANG_DATA'));
  1220. else {
  1221. $lang=XShell::getLangData($p->get('LANG_DATA'));
  1222. if($lang!=TZR_DEFAULT_LANG) return array('error'=>true,'message'=>'Lang error');
  1223. }
  1224. $query = $jn."INSERT {$delayed}INTO ".$this->base.'(';
  1225. $fields='KOID,LANG';
  1226. $values="'$oid','".$lang."'";
  1227. $nottorepeat=array('UPD');
  1228. if($this->fieldExists('OWN') && !$p->get('OWN')) {
  1229. $fields.=',OWN';
  1230. $values.=",'".XUser::get_current_user_uid()."'";
  1231. $nottorepeat[]='OWN';
  1232. }
  1233. if($this->fieldExists('CREAD')) {
  1234. $fields.=',CREAD';
  1235. $values.=",'".date('Y-m-d H:i:s')."'";
  1236. $nottorepeat[]='CREAD';
  1237. }
  1238. if($this->fieldExists('PUBLISH') && !$p->is_set('PUBLISH')) {
  1239. $fields.=',PUBLISH';
  1240. $values.=",'2'";
  1241. $nottorepeat[]='PUBLISH';
  1242. }
  1243. $inputs=$p->get('_inputs','local');
  1244. $inputvalues=array();
  1245. foreach($this->desc as $k => &$v) {
  1246. if(!empty($fieldssec[$k]) && $fieldssec[$k]!='rw') continue;
  1247. if(($p->is_set($k) || $p->is_set($k.'_HID') || !empty($all)) && !in_array($k, $nottorepeat)) {
  1248. $value = $p->get($k);
  1249. $value_hid = $p->get($k.'_HID');
  1250. // traitement en post edit dans les cas simples
  1251. if(!is_object($v)) XShell::quit(array('message'=>'XDataSource::procInput: '.$this->base.':'.$k.' is not a valid field'));
  1252. $options[$k]['oid']=$oid;
  1253. $options[$k][$k.'_HID']=$value_hid;
  1254. $options[$k][$k.'_title']=$p->get($k.'_title');
  1255. $options[$k]['fmoid']=$moid;
  1256. $r1=$v->post_edit($value,$options[$k],$inputs);
  1257. $inputs[$k]=$r1;
  1258. $nvalue=$r1->raw;
  1259. $fields .= ','.$k;
  1260. if(!empty($unique) && in_array($k, $unique)) $unique_val[]="$k like '$nvalue'";
  1261. // cas ou on garde la valeur
  1262. $value=$nvalue;
  1263. if(is_array($value) && (count($value)>1)) {
  1264. $finalval='||';
  1265. foreach($value as $o1=>$o2)
  1266. $finalval.=$o2.'||';
  1267. $values.=",'".$finalval."'";
  1268. } elseif(is_array($value)) {
  1269. list($o1,$o2)=each($value);
  1270. $values.=',?';
  1271. $inputvalues[]=$o2;
  1272. } else {
  1273. if(!empty($r1->forcenull)) {
  1274. $values.=",NULL";
  1275. } else {
  1276. $values.=',?';
  1277. $inputvalues[]=$value;
  1278. }
  1279. }
  1280. }
  1281. }
  1282. $query.=$fields.') values ('.$values.')';
  1283. // verification que l'enregistrement n'est pas existant dans le cas où on gère l'unicité
  1284. if(!empty($unique) || !empty($updateifexists)) {
  1285. if(!empty($unique) && !empty($unique_val)) $rs=selectQuery("select * from {$this->base} where ".implode(' and ',$unique_val));
  1286. else $rs=selectQuery("select * from {$this->base} where KOID='$oid'");
  1287. if($rs && ($ors=$rs->fetch())) {
  1288. $rs->closeCursor();
  1289. $insert = false;
  1290. if(!empty($updateifexists)) {
  1291. $oid=$ors['KOID'];
  1292. $ar['oid']=$oid;
  1293. $ar['_langs'] = 'all';
  1294. return $this->procEdit($ar);
  1295. }
  1296. }
  1297. }
  1298. if(!$insert) {
  1299. XLogs::notice('XDataSource::procInput', $values.' rejeté');
  1300. return array('error'=>true,'message'=>'Values not unique');
  1301. }
  1302. preparedUpdateQuery($query,$inputvalues,$journal);
  1303. // Tag les metas des champs xfile
  1304. $ar['oid']=$oid;
  1305. $this->setFilesMeta($ar);
  1306. // Propagation dans toutes les langues
  1307. if($this->isTranslatable() && $this->getAutoTranslate()) {
  1308. $xk=new Kernel;
  1309. $xk->data_autoTranslate($oid);
  1310. }
  1311. // On met une ligne dans les logs pour dire qu'il y a eu modification de cet objet
  1312. if($this->toLog() && empty($nolog)) XLogs::update('create',$oid);
  1313. // Actions annexes
  1314. $this->updateTasks($ar,$oid);
  1315. // Préparation des retours de résultats
  1316. $result=array();
  1317. $result['oid']=$oid;
  1318. $result['inputs']=$inputs;
  1319. $result['message']=XLabels::getSysLabel('xdatasource','update_ok');
  1320. return XShell::toScreen1($tplentry, $result);
  1321. }
  1322. public function &prepareReInput($ar=NULL) {
  1323. return $this->prepareReEdit($ar);
  1324. }
  1325. public function &prepareReEdit($ar=NULL) {
  1326. $p = new XParam($ar);
  1327. $journal=empty($j);
  1328. $all = $p->get('_allfields');
  1329. $options=array();
  1330. foreach($this->desc as $k => $v) {
  1331. if ((isset($_REQUEST[$k]) || isset($_REQUEST[$k.'_HID'])) && empty($all))
  1332. $_REQUEST['selectedfields'][] = $k;
  1333. if(($p->is_set($k)||$p->is_set($k.'_HID')||!empty($all))) {
  1334. $value = $p->get($k);
  1335. $value_hid = $p->get($k.'_HID');
  1336. // traitement en post edit dans les cas simples
  1337. if(!is_object($v)) {
  1338. XShell::quit(array('message'=>'XDataSource::prepareReEdit: '.$this->base.":$k is not a valid field"));
  1339. }
  1340. $r1=$v->post_edit($value,array('oid'=>$oid,$k.'_HID'=>$value_hid),$inputs);
  1341. $nvalue=$r1->raw;
  1342. // cas ou on garde la valeur
  1343. $value=$nvalue;
  1344. if(is_array($value) && (count($value)>1)) {
  1345. $finalval='||';
  1346. foreach($value as $o1=>$o2)
  1347. $finalval=$finalval.$o2.'||';
  1348. $options[$k]['value']=$finalval;
  1349. } elseif(is_array($value)) {
  1350. list($o1,$o2)=each($value);
  1351. $options[$k]['value']=$o2;
  1352. } else {
  1353. $options[$k]['value']=$value;
  1354. }
  1355. }
  1356. }
  1357. return $options;
  1358. }
  1359. /// Recherche sur la source
  1360. public function &procQuery($ar=NULL) {
  1361. $p=new XParam($ar, array('tplentry'=>$this->base,'_storedquery'=>NULL,'getselectonly'=>false,'fieldssec'=>array()));
  1362. $tplentry=$p->get('tplentry');
  1363. $storedquery=$p->get('_storedquery');
  1364. $fieldssec=$p->get('fieldssec','local');
  1365. $persistent=$p->get('_persistent');
  1366. $fmoid=$p->get('fmoid');
  1367. if(!empty($storedquery)) {
  1368. if(empty($ar)) $ar=array();
  1369. self::prepareQuery($ar, $storedquery);
  1370. $p=new XParam($ar,array('tplentry'=>$this->base,'_storedquery'=>NULL,'operator'=>'AND','getselectonly'=>false));
  1371. }
  1372. $getselectonly=$p->get('getselectonly');
  1373. $fulltext=$p->get('fulltext');
  1374. $filter=$p->get('_filter','norequest');
  1375. $_select=$p->get('_select');
  1376. if(!is_array($_select) && !empty($_select)) $_select=array($_select);
  1377. $operator=$p->get('operator');
  1378. if(empty($operator)) $operator='AND';
  1379. $queryobject=$queryfields=array();
  1380. if($fulltext=='1') {
  1381. $query=$this->fulltext_query($ar);
  1382. $ar['select']=$query;
  1383. $rq='';
  1384. $queryobject['fulltext']=1;
  1385. $queryobject['keyword']=$p->get('keyword');
  1386. } else {
  1387. if(!empty($filter)) $rq=$filter;
  1388. else $rq='1';
  1389. if(!empty($_select)) {
  1390. foreach($_select as $c1=>$c2) {
  1391. if(empty($c2)) unset($_select[$c1]);
  1392. }
  1393. if(!empty($_select)) $rq.=' AND (('.implode(') '.$operator.' (',$_select).'))';
  1394. }
  1395. // Recherche de la liste des champs
  1396. $first=true;
  1397. $_FIELDS=$p->get('_FIELDS');
  1398. if(empty($_FIELDS)) {
  1399. foreach($this->desc as $k => &$v) $_FIELDS[$k]=$k;
  1400. }
  1401. foreach($_FIELDS as $field => $k) {
  1402. if(!empty($fieldssec) && $fieldssec[$k]=='none' || !$this->desc[$k]) continue;
  1403. $v=&$this->desc[$k];
  1404. $v1 = $p->get($field);
  1405. $queryobject[$field]=$v1;
  1406. $o=$v->_newXFieldQuery();
  1407. $o->value=$v1;
  1408. $o->empty=$p->get($field.'_empty');
  1409. $o->op = $p->get($field.'_op');
  1410. $o->hid=$p->get($field.'_HID');
  1411. $o->fmt=$p->get($field.'_FMT');
  1412. $o->par=$p->get($field.'_PAR');
  1413. $v->post_query($o,$ar);
  1414. if(!empty($o->empty)) $queryobject[$field.'_empty']=$o->empty;
  1415. if(!empty($o->op)) $queryobject[$field.'_op']=$o->op;
  1416. if(!empty($o->hid)) $queryobject[$field.'_HID']=$o->hid;
  1417. if(!empty($o->fmt)) $queryobject[$field.'_FMT']=$o->fmt;
  1418. if(!empty($o->par)) $queryobject[$field.'_PAR']=$o->par;
  1419. if(!empty($o->rq)) {
  1420. if(!$persistent) $queryfields[$field]=$o;
  1421. if($first) {
  1422. $rq.=' AND ( '.$o->rq;
  1423. $first=false;
  1424. }else{
  1425. $rq.=' '.$operator.' '.$o->rq;
  1426. }
  1427. }
  1428. }
  1429. if(!$first) $rq.=')';
  1430. }
  1431. $oids=$p->get('oids');
  1432. if(!empty($oids)){
  1433. // Si les clés sont les oids
  1434. if(empty($oids[0])) $oids=array_keys($oids);
  1435. $rq.=' AND '.$this->base.'.KOID in ("'.implode($oids,'","').'")';
  1436. }
  1437. $ar['_filter']=$rq;
  1438. $ar['fields']=$this->base.'.*';
  1439. list($select,$query)=$this->getSelectQuery($ar);
  1440. if(empty($getselectonly)) {
  1441. if($ar==NULL) $ar=array();
  1442. $ar['queryobject']=$queryobject;
  1443. $ar['selected']=0;
  1444. $ar['_filter']='';
  1445. $ar['select']=$query;
  1446. $ar['fmoid']=$fmoid;
  1447. $r=&$this->browse($ar);
  1448. $r['operator']=$operator;
  1449. $r['queryfields']=$queryfields;
  1450. return $r;
  1451. }else{
  1452. return $query;
  1453. }
  1454. }
  1455. /// Verification que la table des archive existe et construction si elle n'existe pas.
  1456. protected function checkArchiveTable($createifneeded=true) {
  1457. return true;
  1458. }
  1459. /// Modification d'une donnée ou d'un ensemble de données
  1460. public function procEdit($ar=NULL) {
  1461. global $value;
  1462. $this->preUpdateTasks($ar);
  1463. $p = new XParam($ar, array('tplentry'=>$this->base,'_inputs'=>array(),'fieldssec'=>array(),'options'=>array(),'_logname'=>'update'));
  1464. $LANG_USER = XShell::getLangUser();
  1465. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  1466. else $LANG_DATA=XShell::getLangData(@$ar['LANG_DATA']);
  1467. $tplentry = $p->get('tplentry');
  1468. $fieldssec = $p->get('fieldssec','local');
  1469. $delayed = $p->get('_delayed');
  1470. $nolog = $p->get('_nolog','local');
  1471. $track = $this->toLog();
  1472. $options = $p->get('options');
  1473. $langs = $p->get('_langs','local'); // En local car le module doit vérifier les droits auparavent
  1474. // Si option est un champ
  1475. if(is_string($options)) $options=array();
  1476. $moid=$p->get('fmoid','local');
  1477. if(!empty($delayed)) $delayed='LOW_PRIORITY ';
  1478. else $delayed='';
  1479. $oid=$p->get('oid');
  1480. $editfields=$p->get('editfields');
  1481. $editbatch=$p->get('editbatch');
  1482. if(is_array($oid)) {
  1483. $P1=array();
  1484. $oids = array();
  1485. foreach($this->desc as $f => $o) {
  1486. if(($editfields=='all') || in_array($f,$editfields)){
  1487. $P1[$f]=$p->get($f);
  1488. $P1[$f.'_HID']=$p->get($f.'_HID');
  1489. }
  1490. }
  1491. foreach($oid as $i => $oid1) {
  1492. if(!$editbatch){
  1493. $ar1=array();
  1494. foreach($this->desc as $f => $o) {
  1495. if(($editfields=='all') || in_array($f,$editfields)){
  1496. if(isset($P1[$f][$i]) || isset($P1[$f.'_HID'][$i])) {
  1497. $ar1[$f]=$P1[$f][$i];
  1498. $ar1[$f.'_HID']=$P1[$f.'_HID'][$i];
  1499. }
  1500. }
  1501. }
  1502. }else{
  1503. $ar1=$P1;
  1504. }
  1505. $ar1['editfields']=$editfields;
  1506. $ar1['editbatch']=$editbatch;
  1507. $ar1['fieldssec']=$fieldssec;
  1508. $ar1['oid']=$oid1;
  1509. $ar1['options']=$options;
  1510. $ret = $this->procEdit($ar1);
  1511. $oids[] = $ret['oid'];
  1512. }
  1513. return array('oid' => $oids);
  1514. }
  1515. if(!empty($GLOBALS['XLOCK'])) {
  1516. $mode = $p->get('_mode');
  1517. $locked=$GLOBALS['XLOCK']->locked($oid, TZR_DEFAULT_LANG);
  1518. $procok=(empty($locked) ||
  1519. XShell::admini_mode()||
  1520. ($locked && (XUser::get_current_user_uid()==$locked['OWN'])));
  1521. }
  1522. $this->checkOID($oid,$ar,'procEdit');
  1523. // Si la donnée n'existe pas dans la langue voulue, on la crée
  1524. if(!$this->objectExists($oid, $LANG_DATA)) {
  1525. $k = new Kernel;
  1526. $k->data_autoTranslate($oid, $LANG_DATA);
  1527. }
  1528. // on genere la donnee en affichage pour calculer les differences
  1529. if($track && empty($nolog) || $editbatch) $disp=$this->display(array('oid'=>$oid,'lang'=>$LANG_DATA,'tplentry'=>TZR_RETURN_DATA,'_lastupdate'=>0));
  1530. // archivage de l'ancienne donnée si nécessaire
  1531. $archive = $p->get('_archive');
  1532. $aupd=NULL;
  1533. if($archive && $this->checkArchiveTable(true)) {
  1534. $this->duplicate(array('oid'=>$oid,'changeown'=>false,'lastonly'=>true,'nolog'=>true),'A_'.$this->base,$aupd);
  1535. }
  1536. // Sauver dans toutes les langues
  1537. if($langs=='all'){
  1538. $langs=array();
  1539. foreach($GLOBALS['TZR_LANGUAGES'] as $l=>&$v) $langs[]=$l;
  1540. }
  1541. $logname=$p->get('_logname');
  1542. $rq='UPD=NULL,KOID="'.$oid.'",LANG="'.$LANG_DATA.'"';
  1543. $inputs=$p->get('_inputs','local');
  1544. $inputvalues=array();
  1545. $trace=array();
  1546. foreach($this->orddesc as $foo => $k) {
  1547. // Cerification des droits sur le champ
  1548. if(!empty($fieldssec[$k]) && $fieldssec[$k]!='rw') continue;
  1549. // Si on est dans une edition par lot, ne traiter que les champs concernés
  1550. if(!empty($editbatch) && !in_array($k,$editfields)) continue;
  1551. $v=&$this->desc[$k];
  1552. if($LANG_DATA!=TZR_DEFAULT_LANG && !$v->get_translatable()) continue;
  1553. if($p->is_set($k)||$p->is_set($k.'_HID')) {
  1554. $value=$p->get($k);
  1555. $value_hid=$p->get($k.'_HID');
  1556. $options[$k]['oid']=$oid;
  1557. $options[$k][$k.'_HID']=$value_hid;
  1558. $options[$k][$k.'_title']=$p->get($k.'_title');
  1559. $options[$k]['old']=@$disp['o'.$k];
  1560. $options[$k]['_track']=$track;
  1561. $options[$k]['fmoid']=$moid;
  1562. $options[$k]['editbatch']=$editbatch;
  1563. // Si on sauve dans plusieurs langues, les fichiers ne doivent pas etre effacés
  1564. if($langs!==NULL && $v->get_translatable() && ($v->get_ftype()=='XFileDef' || $v->get_ftype()=='XImageDef')) $options[$k]['del']=false;
  1565. $r1=$v->post_edit($value,$options[$k],$inputs);
  1566. // Si on sauve dans plusieurs langues, on recupere les dates au format internationnal
  1567. if($langs!==NULL && $v->get_translatable() && $v->get_ftype()=='XDateDef' && $LANG_DATA==TZR_DEFAULT_LANG) $ar[$k]=$r1->raw;
  1568. $nvalue=$r1->raw;
  1569. $inputs[$k]=$r1;
  1570. if($track && !empty($r1->trace)) {
  1571. $trace=array_merge($trace,$r1->trace);
  1572. }
  1573. // cas ou on garde la valeur
  1574. if ( $nvalue !== TZR_UNCHANGED ) {
  1575. if(is_array($nvalue) || ($nvalue!==NULL)) {
  1576. $value=$nvalue;
  1577. if(is_array($value) && (count($value)>1)) {
  1578. $finalval='||';
  1579. foreach($value as $o1 => $o2)
  1580. $finalval=$finalval.$o2.'||';
  1581. $rq.=' ,'.$k."= ?";
  1582. $inputvalues[]=$finalval;
  1583. } elseif(is_array($value)) {
  1584. list($o1,$o2)=each($value);
  1585. $rq.=' ,'.$k."= ?";
  1586. $inputvalues[]=$o2;
  1587. } else {
  1588. $rq.=' ,'.$k."= ?";
  1589. $inputvalues[]=$value;
  1590. }
  1591. }
  1592. else {
  1593. if(!empty($r1->forcenull)) $rq.=' ,'.$k."=NULL";
  1594. else $rq.=' ,'.$k."= ''";
  1595. }
  1596. }
  1597. }
  1598. }
  1599. preparedUpdateQuery('UPDATE '.$delayed.$this->base.' set '.$rq.' where KOID="'.$oid.'" and LANG="'.$LANG_DATA.'"',$inputvalues);
  1600. // Debloquage de l'objet
  1601. if(!empty($GLOBALS['XLOCK']) && $mode=='unlock') $GLOBALS['XLOCK']->unlock($oid, TZR_DEFAULT_LANG);
  1602. // Propagation dans toutes les langues
  1603. if($LANG_DATA==TZR_DEFAULT_LANG){
  1604. $this->propagateOnOtherLangs($oid);
  1605. if(!empty($langs)){
  1606. $ar1=$ar;
  1607. $ar1['_nolog']=true;
  1608. $ar1['_langs']=array();
  1609. foreach($langs as $l){
  1610. if($l==TZR_DEFAULT_LANG) continue;
  1611. $_REQUEST['LANG_DATA']=$l;
  1612. XShell::getLangData(NULL,true);
  1613. $this->procEdit($ar1);
  1614. }
  1615. $_REQUEST['LANG_DATA']=$LANG_DATA;
  1616. XShell::getLangData(NULL,true);
  1617. }
  1618. }
  1619. // Tag les metas des champs xfile
  1620. $this->setFilesMeta($ar);
  1621. // On met une ligne dans les logs pour dire qu'il y a eu modification de cet objet
  1622. if($track && empty($nolog)) XLogs::update($logname,$oid,$trace,$aupd);
  1623. // Actions annexes
  1624. $this->updateTasks($ar,$oid);
  1625. // Message OK
  1626. if(!empty($GLOBALS['XSHELL']->labels)){
  1627. $label=$GLOBALS['XSHELL']->labels->get_label(array('variable'=>'update_success'));
  1628. $result['message']=$label['update_success'];
  1629. }
  1630. $result['oid']=$oid;
  1631. $result['inputs']=$inputs;
  1632. return XShell::toScreen1($tplentry, $result);
  1633. }
  1634. /// Duplication d'un objet (toar=>table d'archivage)
  1635. public function duplicate($ar=NULL,$toar='',&$upd='') {
  1636. $p=new XParam($ar,array('changeown'=>true,'lastonly'=>false));
  1637. $oid=$p->get('oid');
  1638. $nolog=$p->get('nolog');
  1639. $lastonly=$p->get('lastonly');
  1640. $changeown=$p->get('changeown');
  1641. $tdest=(empty($toar)?$this->base:$toar);
  1642. $nkoid=$p->get('newoid');
  1643. if(empty($nkoid)) $nkoid=(($tdest==$this->base)?$this->getNewOID($ar):$oid);
  1644. $upd=XTimestampDef::default_timestamp();
  1645. updateQuery('CREATE TEMPORARY TABLE tmp1 AS SELECT * FROM '.$this->base.' WHERE KOID="'.$oid.'"');
  1646. updateQuery('UPDATE tmp1 SET KOID="'.$nkoid.'",UPD="'.$upd.'"'.
  1647. ($changeown && $this->fieldExists('OWN')?',OWN="'.XUser::get_current_user_uid().'"':''));
  1648. updateQuery('INSERT INTO '.$tdest.' SELECT * FROM tmp1');
  1649. updateQuery('DROP TEMPORARY TABLE tmp1');
  1650. $inputvalues=array();
  1651. $sql='UPD=UPD';
  1652. foreach($this->desc as $f=>$v) {
  1653. if($v->hasExternals()) $sql.=','.$f.'=:'.$f;
  1654. }
  1655. $rs=selectQuery('SELECT * FROM '.$this->base.' WHERE KOID="'.$oid.'" order by '.($lastonly?'UPD DESC,':'').'field(LANG,"'.TZR_DEFAULT_LANG.'") desc');
  1656. while($ors=$rs->fetch()){
  1657. if($lastonly && !empty($oupd) && $oupd!=$ors['UPD']) break;
  1658. $oupd=$ors['UPD'];
  1659. $lang=$ors['LANG'];
  1660. foreach($this->desc as $f=>$v) {
  1661. if($v->hasExternals() && ($lastonly || $lang==TZR_DEFAULT_LANG || $v->get_translatable())) {
  1662. if($tdest!=$this->base) $nv=$v->copyExternalsTo($ors[$f],$oid,$nkoid,preg_replace('/([^0-9])/','',$upd));
  1663. else $nv=$v->copyExternalsTo($ors[$f],$oid,$nkoid,'');
  1664. $inputvalues[$f]=$nv;
  1665. }
  1666. }
  1667. if(!empty($inputvalues)) preparedUpdateQuery('UPDATE '.$tdest.' SET '.$sql.' where KOID="'.$nkoid.'" and LANG="'.$lang.'" AND UPD="'.$upd.'"',$inputvalues,true);
  1668. }
  1669. if(!$nolog && $this->toLog()) XLogs::update('create',$nkoid);
  1670. return $nkoid;
  1671. }
  1672. /// Duplication d'un enregistrement a partir d'une page ecran
  1673. public function procEditDup($ar=NULL) {
  1674. $p = new XParam($ar, array('tplentry'=>$this->base));
  1675. $LANG_USER = XShell::getLangUser();
  1676. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  1677. else $LANG_DATA=XShell::getLangData(@$ar['LANG_DATA']);
  1678. $tplentry=$p->get('tplentry');
  1679. $oidsrc=$p->get('oid');
  1680. $oiddst=$this->getNewOID($ar);
  1681. $nottorepeat=array();
  1682. $rq = "UPD=NULL, KOID='$oiddst', LANG= '$LANG_DATA'";
  1683. if($this->fieldExists('CREAD')) {
  1684. $rq.=', CREAD="'.date('Y-m-d H:i:s').'"';
  1685. $nottorepeat[]='CREAD';
  1686. }
  1687. if($this->fieldExists('OWN') && !($p->is_set('OWN') || $p->is_set('OWN_HID'))) {
  1688. $rq .= ", OWN='".XUser::get_current_user_uid()."'";
  1689. }
  1690. // champ publish ?
  1691. if ($this->fieldExists('PUBLISH')){
  1692. $rq .= ", PUBLISH=2";
  1693. $nottorepeat[]='PUBLISH';
  1694. }
  1695. $inputvalues=array();
  1696. foreach($this->desc as $k => $v) {
  1697. if(($p->is_set($k) || $p->is_set($k.'_HID')) && (!$p->is_set($k.'_del') || is_array($p->get($k.'_del'))) && !in_array($k,$nottorepeat)) {
  1698. $value = $p->get($k);
  1699. $value_hid = $p->get($k.'_HID');
  1700. // traitement en post edit dans les cas simples
  1701. $nvalue=$v->post_edit_dup($value,array('oidsrc'=>$oidsrc, 'oiddst'=>$oiddst,
  1702. $k.'_HID'=>$value_hid));
  1703. // cas ou on garde la valeur
  1704. if ( $nvalue != TZR_UNCHANGED ) {
  1705. if(is_array($nvalue) || ($nvalue!=NULL)) {
  1706. $value=$nvalue;
  1707. if(is_array($value) && (count($value)>1)) {
  1708. $finalval='||';
  1709. foreach($value as $o1 => $o2)
  1710. $finalval=$finalval.$o2.'||';
  1711. $rq=$rq.' ,'.$k.'= ?';
  1712. $inputvalues[]=$finalval;
  1713. } elseif(is_array($value)) {
  1714. list($o1,$o2)=each($value);
  1715. $rq=$rq.' ,'.$k.'= ?';
  1716. $inputvalues[]=$o2;
  1717. } else {
  1718. $rq=$rq.' ,'.$k.'= ?';
  1719. $inputvalues[]=$value;
  1720. }
  1721. }
  1722. else {
  1723. $rq=$rq.' ,'.$k."= ''";
  1724. }
  1725. }
  1726. }
  1727. }
  1728. preparedUpdateQuery('INSERT INTO '.$this->base.' set '.$rq, $inputvalues);
  1729. // Creation automatique des tuples dans les autres langues (si translation automatique)
  1730. // (ou si pas de translation - provisoire - )
  1731. if ( $this->isTranslatable() && $this->getAutoTranslate()) {
  1732. $xk = new Kernel;
  1733. $xk->data_autoTranslate($oiddst);
  1734. }
  1735. // on met une ligne dans les logs pour dire qu'il y a eu modification de cet objet
  1736. if($this->toLog()) XLogs::update('create',$oiddst);
  1737. // message ok
  1738. $result = array('message'=>"Mise &agrave; jour r&eacute;ussie.",'oid'=>$oiddst);
  1739. $result['oid']=$oiddst;
  1740. return XShell::toScreen1($tplentry, $result);
  1741. }
  1742. // les valeurs de retour possible sont
  1743. // all, marked, public
  1744. // all = le champ pulished n'existe pas
  1745. // marked = le champs published exiete et on est en mode authentife
  1746. // public = le champs existe et on ne montre que ce qui est valide
  1747. function publishedMode(XParam $p) {
  1748. if(!isset($this->desc['PUBLISH'])) {
  1749. return 'all';
  1750. }
  1751. if(XShell::admini_mode()){
  1752. $published = $p->get('_published');
  1753. if(!isset($published) || $published!==false) $published='marked';
  1754. } else {
  1755. $published = $p->get('_published');
  1756. if(!isset($published) || $published!==false) $published='public';
  1757. }
  1758. return $published;
  1759. }
  1760. /// Parcours la source
  1761. public function &browse($ar=NULL) {
  1762. $params = new XParam
  1763. ($ar,array('tplentry'=>$this->base,
  1764. // la requete qui va servir a faire le select en base
  1765. 'select'=>'',
  1766. // tableau des champs qu'on veut browser. Par defaut on prend l'attribut browsable dans la base
  1767. 'selectedfields'=>'*',
  1768. // tableau de type de champ qu'on veut browser.
  1769. 'selectedtypes'=>array(),
  1770. // tableau propriété=>true/false (browsable, queryable...) qu'on veut browser (ex : array('browsable'=>true))
  1771. 'selectedprops'=>array(),
  1772. // opératuer à appliquer entre les critères de sélection
  1773. 'selectedop'=>'AND',
  1774. // complément pour la requete de selection : ordre de tri des data selectionnees
  1775. 'order'=>'',
  1776. // nombre de lignes par page
  1777. 'pagesize'=>TZR_XMODTABLE_BROWSE_PAGESIZE,
  1778. // cas des affichages en plusieurs pages (next/previous),
  1779. // pour savoir quel est le first de la page
  1780. 'first'=>'0', 'nocount'=>'0', 'editfields'=>array(), 'fieldssec'=>array(), 'noeditoids'=>array()
  1781. ));
  1782. XLogs::debug('XDataSource::browse('.$this->base.')');
  1783. XLabels::loadLabels('browse');
  1784. $tplentry = $params->get('tplentry');
  1785. $selectedop = $params->get('selectedop');
  1786. $limit = $params->get('limit');
  1787. $selectedfields = $params->get('selectedfields');
  1788. $selectedtypes = $params->get('selectedtypes');
  1789. $selectedprops = $params->get('selectedprops');
  1790. $options = $params->get('options');
  1791. $fieldssec = $params->get('fieldssec','local');
  1792. $fmoid = $params->get('fmoid');
  1793. $first = $params->get('first');
  1794. $_format = $params->get('_format');
  1795. $charset = $params->get('_charset');
  1796. $last = $params->get('last');
  1797. $pagesize = $params->get('pagesize');
  1798. if(!isInteger($pagesize) || empty($pagesize)) $pagesize=TZR_XMODTABLE_BROWSE_PAGESIZE;
  1799. $nocount=$params->get('nocount');
  1800. $tlink=$params->get('tlink');
  1801. $published=$this->publishedMode($params);
  1802. $translatable = $this->getTranslatable();
  1803. $_options = $params->get('_options');
  1804. $genpublishtag=@$_options['genpublishtag'];
  1805. $editfields = $params->get('editfields');
  1806. $noeditoids = $params->get('noeditoids');
  1807. if(!isset($genpublishtag)) $genpublishtag=true;
  1808. XAudit::plusplus('browse('.$this->base.')');
  1809. $LANG_TRAD=XShell::getLangTrad($params->get('LANG_TRAD'));
  1810. $LANG_DATA=XShell::getLangData($params->get('LANG_DATA'));
  1811. if(!$translatable) $LANG_DATA=TZR_DEFAULT_LANG;
  1812. if(!empty($LANG_TRAD) && ($LANG_DATA!=$LANG_TRAD) && ($translatable!=TZR_LANG_FREELANG)) $lang_other=$LANG_DATA;
  1813. $result=array();
  1814. $result['header_fields']=array();
  1815. $result['lines_oid']=array();
  1816. $result['lines_published']=array();
  1817. // Construction des titres des colonnes
  1818. // - Demande les champs d'un certain type (on prend aussi les champs publié et browsable)
  1819. // - Demande des champs prédéfinies
  1820. // - Demande tout
  1821. // - Demande les champs browsable (defaut)
  1822. $fields = '';
  1823. if($selectedfields=='all'){
  1824. $fieldlist=$this->orddesc;
  1825. }else{
  1826. if(!is_array($selectedfields) && empty($selectedprops) && empty($selectedtypes)) $selectedprops['browsable']=true;
  1827. $fieldlist=$this->getFieldsList($selectedtypes,@$selectedprops['browsable'],@$selectedprops['published'],@$selectedprops['queryable'],@$selectedprops['compulsory'],@$selectedprops['translatable'],@$selectedprops['multivalued'],$selectedfields,$selectedop);
  1828. }
  1829. $result['header_fields']=array();
  1830. foreach($fieldlist as $my1 => $my2) {
  1831. if(!empty($fieldssec[$my2]) && $fieldssec[$my2]=='none') continue;
  1832. if(isset($this->desc[$my2])) {
  1833. $v=&$this->desc[$my2];
  1834. $result['header_fields'][]=$v;
  1835. $fields.=','.$this->base.'.'.$my2;
  1836. }
  1837. }
  1838. if($published!='all') $fields.=','.$this->base.'.PUBLISH';
  1839. $ar['fields']=$fields;
  1840. list($select,$requete,$order,$oorder)=$this->getSelectQuery($ar);
  1841. // Calcul des pages
  1842. if($nocount!='1') $last=countSelectQuery($select.' LIMIT 1000',true);
  1843. if($pagesize<$last) {
  1844. for($p=0,$i=0;($i<$last);$i+=$pagesize) $pages[$p++]=$i;
  1845. }
  1846. // Execution de la requete
  1847. if(!empty($pagesize)) $rs=selectQuery($requete.' limit '.$first.', '.$pagesize);
  1848. else $rs=selectQuery($requete);
  1849. // Création du resultat
  1850. $myi=0;
  1851. $anyedit=false;
  1852. $adminmode=XShell::admin_mode();
  1853. $editfieldsres=array();
  1854. // Construction des data
  1855. $ors=array();
  1856. $pub=NULL;
  1857. while($rs && ($ors=$rs->fetch())) {
  1858. $oid=$ors['KOID'];
  1859. $result['lines_oid'][$myi]=$oid;
  1860. if($tlink) $result['lines_tlink'][$myi]='';
  1861. if($genpublishtag && ($published=='marked')) {
  1862. $mark=$ors['PUBLISH'];
  1863. if($mark=='1') $pubval='checked';
  1864. else $pubval='';
  1865. $pub[$myi]='<input type="checkbox" class="checkbox" name="_PUBLISH['.$oid.']" '.$pubval.'/>';
  1866. $pub[$myi].='<input type="hidden" name="_PUBLISH_H['.$oid.']" value="'.$mark.'"/>';
  1867. }
  1868. // on regarde si l'info existe dans le cas ou il y a une langue de traduction
  1869. if($translatable && !empty($lang_other)) {
  1870. if($this->objectExists($oid, $lang_other)) {
  1871. $result['lines_translation_ok'][$myi]='1';
  1872. } else {
  1873. $result['lines_translation_ok'][$myi]='0';
  1874. }
  1875. }
  1876. $tabindex = 1;
  1877. foreach($result['header_fields'] as $i => $def) {
  1878. $k=$def->get_field();
  1879. $value = $ors[$k];
  1880. $opt=@$options[$k];
  1881. $opt['_format']=$_format;
  1882. if(empty($opt)) $opt=array();
  1883. $opt['_published']=true;
  1884. if($published=='marked') {
  1885. if($ors['PUBLISH']=='2')
  1886. $opt['_published']=false;
  1887. }
  1888. if(!empty($charset)) {
  1889. $opt['_charset']=$charset;
  1890. }
  1891. if(($editfields=='all' || is_array($editfields) && in_array($k,$editfields)) && (empty($fieldssec[$k]) || $fieldssec[$k]=='rw') &&
  1892. !in_array($oid,$noeditoids)) {
  1893. if(!in_array($k,$editfieldsres)) $editfieldsres[]=$k;
  1894. $method='edit';
  1895. $opt['intable']="$myi";
  1896. $anyedit=true;
  1897. } else $method='browse';
  1898. $k1=trim($k);
  1899. $opt['fmoid']=$fmoid;
  1900. $opt['admin']=$adminmode;
  1901. $opt['tabindex']=$tabindex++;
  1902. $result['lines_o'.$k][$myi]=$def->$method($value,$opt,$ors);
  1903. if($published=='marked') $result['lines_published'][$myi]=$ors['PUBLISH'];
  1904. if($tlink && $def->get_published()) $result['lines_tlink'][$myi].=$result['lines_o'.$k][$myi]->text.' ';
  1905. }
  1906. $myi++;
  1907. }
  1908. $result['pagesize']=$pagesize;
  1909. if($published=='marked') $result['lines_PUBLISH_tag']=$pub;
  1910. if(isset($editfields)) $result['editfields']=$editfieldsres;
  1911. $result['table']=$this->base;
  1912. $result['first']=$first;
  1913. $result['last']=$last;
  1914. $result['firstlastpage']=(($last-$pagesize<=0)?'0':($last-$pagesize));
  1915. $result['firstnext']=($first+$pagesize);
  1916. $result['firstprev']=($first-$pagesize>=0?($first-$pagesize):$first);
  1917. $result['select']=$select;
  1918. $result['order']=$oorder;
  1919. if(isset($pages)) $result['pages']=$pages;
  1920. // Information sur le caractere "translatable" ou non de toute la table
  1921. $result['translatable'] = $translatable;
  1922. $result['anyedit'] = $anyedit;
  1923. $result['queryobject']=$params->get('queryobject');
  1924. return XShell::toScreen1($tplentry, $result);
  1925. }
  1926. /// Retourne les oids correspondant à une requête
  1927. public function &browseOids($ar=NULL) {
  1928. list($select,$requete,$order)=$this->getSelectQuery($ar);
  1929. $rs=selectQuery($requete);
  1930. $ors=array();
  1931. $result=array();
  1932. while($rs && ($ors=$rs->fetch())) {
  1933. $result[]=$ors['KOID'];
  1934. }
  1935. return $result;
  1936. }
  1937. /// Construit une requete select selon les parametres fournis
  1938. public function getSelectQuery($ar){
  1939. $p=new XParam($ar,array('select'=>'','fields'=>'','order'=>'','cond'=>null));
  1940. $select=$p->get('select','norequest');
  1941. $order=$p->get('order');
  1942. if(is_array($order)) $order=implode(',',$order);
  1943. $oorder=$order;
  1944. if(!empty($order)) $ar['order']=$order;
  1945. if (!$select && ($p->is_set('cond') || $p->is_set('where')))
  1946. $select = $this->select_query($ar);
  1947. $fields=$p->get('fields');
  1948. if(empty($fields)) $fields=$this->base.'.KOID';
  1949. elseif($fields!='*' && $fields!=$this->base.'.*') $fields=$this->base.'.KOID'.$fields;
  1950. // Langue
  1951. $translatable=$this->getTranslatable();
  1952. $LANG_USER=XShell::getLangUser();
  1953. $LANG_TRAD=XShell::getLangTrad($p->get('LANG_TRAD'));
  1954. $LANG_DATA=XShell::getLangData($p->get('LANG_DATA'));
  1955. if(!$translatable) $LANG_DATA=TZR_DEFAULT_LANG;
  1956. $lang_list=$LANG_DATA;
  1957. if(!empty($LANG_TRAD) && ($LANG_DATA!=$LANG_TRAD) && ($translatable!=TZR_LANG_FREELANG)) {
  1958. $lang_list=$LANG_TRAD;
  1959. $lang_other=$LANG_DATA;
  1960. }
  1961. if($this->getTranslatable())
  1962. $cond=$this->base.'.LANG="'.$lang_list.'"';
  1963. else $cond='1';
  1964. // Filtre
  1965. $filter=$p->get('_filter','norequest');
  1966. if(!empty($filter)) {
  1967. $context=array();
  1968. $context['/(\$\(user\))/']=XUser::get_current_user_uid();
  1969. $filter=preg_replace(array_keys($context),array_values($context),$filter);
  1970. $cond.=' AND '.$filter;
  1971. if(!empty($select) && preg_match('/(where)/i',$select)) $select=preg_replace('/(where)/i','where '.$filter.' and ',$select);
  1972. elseif(!empty($select)) $select=preg_replace('/(from [a-z0-1]+ )/i','$1 where '.$filter, $select);
  1973. }
  1974. // Publication
  1975. $published=$this->publishedMode($p);
  1976. if($published!='all' && $fields!='*' && $fields!=$this->base.'.*') $fields.=','.$this->base.'.PUBLISH';
  1977. if($published=='public') $cond.=' AND '.$this->base.'.PUBLISH="1" ';
  1978. // Ordre
  1979. $jointcond = NULL;
  1980. if(!empty($order) && empty($select)) {
  1981. $torder=explode(',',$order);
  1982. $order=array();
  1983. $order=$this->makeOrder($torder,$order,$jointcond);
  1984. }
  1985. // Construction de la requete de selection des data
  1986. if(!empty($select) && !empty($order) && !preg_match('/(order[ ]+by)/i',$select)) $requete=$select.' order by '.$order;
  1987. elseif(!empty($select)) $requete=$select;
  1988. else{
  1989. if(!empty($jointcond)) $select='select '.$fields.' from '.$this->base.' '.$jointcond.' where '.$cond;
  1990. else $select='select '.$fields.' from '.$this->base.' where '.$cond;
  1991. if(!empty($order)) $requete=$select.' order by '.$order;
  1992. else $requete=$select;
  1993. }
  1994. return array($select,$requete,$order,$oorder);
  1995. }
  1996. /// Construction de l'ordre
  1997. function makeOrder($torder,&$order,&$jointcond){
  1998. $tmp=implode(',',$torder);
  1999. if(!preg_match("/^[ a-z0-9_,;.\[\]-]+$/i",$tmp)){
  2000. $order=$tmp;
  2001. return $order;
  2002. }
  2003. foreach($torder as $i=>$actorder){
  2004. $decorder=explode(' ',trim($actorder));
  2005. $orderfield=$decorder[0];
  2006. if(($pos=strpos($orderfield,'['))!==false){
  2007. $ssorderfields=explode(';',substr($orderfield,$pos+1,-1));
  2008. $orderfield=substr($orderfield,0,$pos);
  2009. }else{
  2010. $ssorderfields=NULL;
  2011. }
  2012. if(!empty($orderfield) && isset($this->desc[$orderfield])) {
  2013. $ftype=$this->desc[$orderfield]->get_ftype();
  2014. if (XFieldDef::isObjectLink($ftype) || $ftype=='XDocumentDef') {
  2015. $grouporder=array();
  2016. $sens = $decorder[1];
  2017. // comme on veut tout on fait un left outer join
  2018. if (XFieldDef::isObjectLink($ftype)) {
  2019. $rtables[0]['t'] = $this->desc[$orderfield]->get_target();
  2020. if($rtables[0]['t']=='%'){
  2021. $order[]=implode(' ',$decorder);
  2022. continue;
  2023. }
  2024. }else{
  2025. $rtables=selectQueryGetAll('select DISTINCT SUBSTRING_INDEX('.$orderfield.',":",1) as t from '.$this->base);
  2026. }
  2027. foreach($rtables as $z){
  2028. $rtable=$z['t'];
  2029. $xt=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$rtable);
  2030. $jointcond.=' left outer join '.$rtable.' as '.$rtable.'_'.$i.' on '.$this->base.'.'.$orderfield.'='.$rtable.'_'.$i.'.KOID and '.
  2031. $rtable.'_'.$i.'.LANG="'.($xt->isTranslatable()?XShell::getLangData():TZR_DEFAULT_LANG).'"';
  2032. if(!empty($ssorderfields)) $links=$ssorderfields;
  2033. else $links=$xt->getPublished();
  2034. foreach($links as $kl=>$vl){
  2035. if(fieldExists($rtable,$vl)) $grouporder[$rtable][]='ifnull('.$rtable.'_'.$i.'.'.$vl.',"")';
  2036. }
  2037. }
  2038. foreach($grouporder as $kl=>$vl){
  2039. $decorder[0]='CONCAT('.implode(',',$vl).')';
  2040. $decorder[1]=$sens;
  2041. $order[]=implode(' ',$decorder);
  2042. }
  2043. } else {
  2044. $decorder[0] = $this->base.'.'.$decorder[0];
  2045. $order[]=implode(' ',$decorder);
  2046. }
  2047. }else{
  2048. $order[]=implode(' ',$decorder);
  2049. }
  2050. }
  2051. $order=implode(',',$order);
  2052. return $order;
  2053. }
  2054. function getFirstFieldName() {
  2055. // Fisrt field = selon FORDER
  2056. // Dans orddesc, on a les fields tries par FORDER
  2057. $f=$this->orddesc[0];
  2058. $od = $this->desc[$f];
  2059. if(!is_object($od)) {
  2060. XShell::quit('could not find published field in table '.$this->base);
  2061. }
  2062. $of = $od->sqlfields();
  2063. return $of;
  2064. }
  2065. /// Propage le contenu des champs non traduits de la langue maitre sur toutes les autres langues
  2066. function propagateOnOtherLangs($oid) {
  2067. if(!$this->isTranslatable() || $this->getNonTranslatableFieldCount()==0) return;
  2068. // Recuperation des valeurs de la langue maitre
  2069. $rq1 = 'select * from '.$this->base." where KOID='".$oid."' and LANG='".TZR_DEFAULT_LANG."'";
  2070. $rs=selectQuery($rq1);
  2071. $ors=array();
  2072. if ($ors=$rs->fetch()) {
  2073. // Update des champs non translatables uniquement
  2074. $rq2 = 'UPDATE '.$this->base." set KOID='".$oid."'";
  2075. $inputvalues=array();
  2076. foreach ($this->desc as $k => $v) {
  2077. if(!$v->get_translatable()) {
  2078. $rq2 .= ', ' . $k . ' = ?';
  2079. $inputvalues[]=$ors[$k];
  2080. }
  2081. }
  2082. $rq2 .= " where KOID='".$oid."' and LANG!='".TZR_DEFAULT_LANG."'";
  2083. preparedUpdateQuery($rq2,$inputvalues);
  2084. }
  2085. }
  2086. /// Recherche fulltext sur la source
  2087. function fulltext_query($ar=NULL) {
  2088. $p=new XParam($ar,array('keyseparator'=>','));
  2089. $published=$this->publishedMode($p);
  2090. $keys=$p->get('keyword');
  2091. $fields=$p->get('keyfields');
  2092. $sep=$p->get('keyseparator');
  2093. $options=$p->get('options');
  2094. if(empty($fields)) $fields=array_keys($this->desc);
  2095. if($this->isTranslatable()) $lang=XShell::getLangData();
  2096. else $lang=TZR_DEFAULT_LANG;
  2097. if(!is_array($keys)) $keys=array($keys);
  2098. foreach($keys as $i => $str) {
  2099. $ks=explode($sep,$str);
  2100. foreach($ks as $j=>$kt) {
  2101. if($kt!='') $keywords[]=trim($kt);
  2102. }
  2103. }
  2104. $cond='';
  2105. foreach($keywords as $i=>$keyword) {
  2106. if($cond!='') $cond.=' AND ';
  2107. $scond='';
  2108. foreach($fields as $k) {
  2109. $def=$this->desc[$k];
  2110. $s1=$def->search($keyword,$options[$k]);
  2111. if($scond!='' && $s1!='') $scond.=' OR ';
  2112. if($s1!='') $scond.=$s1;
  2113. }
  2114. if($scond!='') $cond.='('.$scond.')';
  2115. }
  2116. if($published=='public') {
  2117. if(empty($cond)) $cond=' PUBLISH="1" ';
  2118. else $cond.=' AND PUBLISH="1" ';
  2119. }
  2120. return 'select * from '.$this->base.' where LANG="'.$lang.'" AND '.$cond;
  2121. }
  2122. function del($ar) {
  2123. $this->preUpdateTasks($ar);
  2124. $p=new XParam($ar,array('_selectedok'=>'nok'));
  2125. $oid=$p->get('oid');
  2126. $lang=XShell::getLangData();
  2127. $selected=$p->get('_selected');
  2128. $selectedok=$p->get('_selectedok');
  2129. $k=new Kernel();
  2130. return $k->data_forcedDel(array('oid'=>$oid,'tplentry'=>TZR_RETURN_DATA,'action'=>'OK',
  2131. '_selected'=>$selected,'_selectedok'=>$selectedok, '_mytable'=>$this->base));
  2132. // Actions annexes
  2133. $this->updateTasks($ar,$oid);
  2134. }
  2135. /// rend la liste des emails dans un enregistrement en explorant tous les champs
  2136. public function emails(&$ors) {
  2137. $emails=array();
  2138. $options=array();
  2139. foreach($this->desc as $k => $v) {
  2140. $o=&$v->display($ors[$k],$options);
  2141. if(!empty($o->emails)) {
  2142. if(is_string($o->emails))
  2143. $emails[]=$o->emails;
  2144. else {
  2145. foreach($o->emails as $i=>$email) {
  2146. $emails[]=$email;
  2147. }
  2148. }
  2149. }
  2150. }
  2151. return $emails;
  2152. }
  2153. /// rend la liste des emails dans un enregistrement
  2154. public function emailsFromDisplay(&$disp) {
  2155. $emails=array();
  2156. $options=array();
  2157. foreach($this->desc as $k => $v) {
  2158. $o=&$disp['o'.$k];
  2159. if(!empty($o->emails)) {
  2160. if(is_string($o->emails))
  2161. $emails[]=$o->emails;
  2162. else {
  2163. foreach($o->emails as $i=>$email) {
  2164. $emails[]=$email;
  2165. }
  2166. }
  2167. }
  2168. }
  2169. return $emails;
  2170. }
  2171. /// rend vrai s'il y a au moins un champ publie
  2172. function isTherePublishedField() {
  2173. $requete = "select count(*) from DICT where DTAB='".$this->base."' and PUBLISHED=1";
  2174. return (countSelectQuery($requete)>0);
  2175. }
  2176. /// recherche du premier ordre de champ disponible
  2177. function newFieldOrder() {
  2178. // Determine le prochain ordre pour Fxxxx
  2179. $forder = 1;
  2180. $rs=selectQueryByNum("select max(FORDER)+1 from DICT where DTAB='$this->base'");
  2181. $ors=array();
  2182. if ( $ors=$rs->fetch() ) {
  2183. if ( $ors[0] >= 1 ) $forder=$ors[0];
  2184. }
  2185. $rs->closeCursor();
  2186. return $forder;
  2187. }
  2188. function objectExists($koid,$lang=NULL) {
  2189. if(empty($lang)) $lang=XShell::getLangData();
  2190. $requete = "select count(*) from ".$this->base." where KOID='".$koid."' and LANG='".$lang."'";
  2191. $cnt=countSelectQuery($requete);
  2192. return ($cnt>0);
  2193. }
  2194. function gen_export($ar=NULL) {
  2195. global $XSHELL;
  2196. $params = new XParam
  2197. ($ar,array(
  2198. "tplentry"=>$this->base,
  2199. // est ce que les donnees ont deja ete selectionnees
  2200. "selected"=>0,
  2201. // la requete qui va servir a faire le select en base
  2202. "select"=>"",
  2203. // tableau des champs qu'on veut browser. Par defaut on prend l'attribut browsable dans le base
  2204. // complement pour la requete de selection : ordre de tri des data selectionnees
  2205. "order"=>$this->getFirstFieldName(),
  2206. // liste des champs qui seront affiches sur des liens, si on ne veut pas prendre les published par defaut
  2207. "published"=>array(),
  2208. // taille de la ligne en nombre de cellules
  2209. "linesize"=>0,
  2210. // nombre de lignes par page
  2211. // genere ou pas un lien HTML sur les champs de type "lien"
  2212. "genlinks"=>1,
  2213. // on utilise ou pas le {brow1_header}
  2214. "header"=>1
  2215. ));
  2216. $tplentry = $params->get("tplentry");
  2217. $selectedfields = $params->get("selectedfields");
  2218. $selected = $params->get("selected");
  2219. $published = $params->get("published");
  2220. $select = stripslashes($params->get("select"));
  2221. $options = $params->get("options");
  2222. $genlinks = $params->get("genlinks");
  2223. $order = $params->get("order");
  2224. $linesize=$params->get("linesize");
  2225. $LANG_USER = $params->get("LANG_USER");
  2226. $LANG_DATA = $params->get("LANG_DATA");
  2227. $genlinks="0";
  2228. $fields = "";
  2229. $col = 0;
  2230. $libelles=array();
  2231. $fieldcode=array();
  2232. // Construction des titres des colonnes
  2233. // cas ou les champs sont browsable si indique dans la base
  2234. reset($this->desc);
  2235. while(list($k,$v)=each($this->desc)) {
  2236. $libelles[$col] = $v->get_label();
  2237. $k = $v->get_field();
  2238. $result[$k."_label"]=$v->get_label();
  2239. $fieldcode[$col] = $k;
  2240. $fields.=$k;
  2241. $f[$k]=$k;
  2242. $col++;
  2243. }
  2244. // Construction de la requete de selection des data
  2245. if ($selected==0) {
  2246. if($select!="") {
  2247. $requete = $select ." order by $order ";
  2248. }
  2249. else {
  2250. $select = "select KOID$fields from ".$this->base." where LANG='".$LANG_DATA."'";
  2251. $requete = $select ." order by $order ";
  2252. }
  2253. $rs=selectQuery($requete);
  2254. }
  2255. $nblines=$rs->rowCount();
  2256. $myi=0;
  2257. $linesoid=array();
  2258. $linesrow=array();
  2259. $varoid=array();
  2260. if($linesize>0) {
  2261. $column=0;
  2262. $linenum=0;
  2263. }
  2264. // Construction des data
  2265. $ors=array();
  2266. while($ors=$rs->fetch()) {
  2267. reset($f);
  2268. $linesoid[$myi]=$ors['KOID'];
  2269. $oid=$ors['KOID'];
  2270. $linesrow[$myi]="";
  2271. if($linesize>0) $linesrowcol[$linenum][$column]["oid"] = $oid;
  2272. while(list($k,$n)=each($f)) {
  2273. $def = $this->desc[$k];
  2274. $value = $ors['$k'];
  2275. $opt=$options[$k];
  2276. if(!isset($opt["links"])) $opt["links"]=$genlinks;
  2277. $o=$def->display2($value,$opt);
  2278. $val=preg_replace('@<br/>@i',"",$o->html);
  2279. $linesrow[$myi] = $linesrow[$myi].$def->get_label()." : ".$val."\n";
  2280. ${$k}[$myi]=$val;
  2281. if($linesize>0) $linesrowcol[$linenum][$column][$k] = $val;
  2282. }
  2283. if($linesize>0) {
  2284. $column++;
  2285. if($column >= $linesize) {
  2286. $linenum++;
  2287. $column=0;
  2288. }
  2289. }
  2290. $myi++;
  2291. }
  2292. if($params->get("header")) {
  2293. $result["header_fieldname"]=$libelles;
  2294. $result["header_fieldcode"]=$fieldcode;
  2295. $result["header_equiv"]=array();
  2296. }
  2297. $result["lines_oid"]=$linesoid;
  2298. $result["lines_equiv"]=array();
  2299. reset($f);
  2300. while(list($k,$n)=each($f)) {
  2301. $result["lines_".$k]=${$k};
  2302. $result["lines_".$k."_url"]=${$k."_url"};
  2303. $result["lines_".$k."_oid"]=${$k."_raw"};
  2304. $result["lines_".$k."_raw"]=${$k."_oid"};
  2305. $result["lines_".$k."_file"]=${$k."_file"};
  2306. }
  2307. echo "Table: ".$result["tablelabel"]."\n----\n";
  2308. for($i=0;$i<$myi;$i++)
  2309. echo $linesrow[$i]."\n---\n";
  2310. $result["select"]="$select";
  2311. $result["order"]="$order";
  2312. echo "\n ";
  2313. $XSHELL->tpldata["$tplentry"] = $result;
  2314. }
  2315. function export($ar=NULL) {
  2316. global $XSHELL;
  2317. $params = new XParam
  2318. ($ar,array("tplentry"=>$this->base,
  2319. // est ce que les donnees ont deja ete selectionnees
  2320. "selected"=>0,
  2321. // la requete qui va servir a faire le select en base
  2322. "select"=>"",
  2323. // tableau des champs qu'on veut browser. Par defaut on prend l'attribut browsable dans le base
  2324. // complement pour la requete de selection : ordre de tri des data selectionnees
  2325. "order"=>$this->getFirstFieldName(),
  2326. // liste des champs qui seront affiches sur des liens, si on ne veut pas prendre les published par defaut
  2327. "published"=>array(),
  2328. // taille de la ligne en nombre de cellules
  2329. "linesize"=>0,
  2330. // nombre de lignes par page
  2331. // genere ou pas un lien HTML sur les champs de type "lien"
  2332. "genlinks"=>1,
  2333. // on utilise ou pas le {brow1_header}
  2334. "header"=>1
  2335. ));
  2336. $tplentry = $params->get("tplentry");
  2337. $selectedfields = $params->get("selectedfields");
  2338. $published = $params->get("published");
  2339. $options = $params->get("options");
  2340. $genlinks = $params->get("genlinks");
  2341. $LANG_USER = $params->get("LANG_USER");
  2342. $LANG_DATA = $params->get("LANG_DATA");
  2343. $included = $params->get("included");
  2344. $fields = "";
  2345. $col = 0;
  2346. $libelles=array();
  2347. $fieldcode=array();
  2348. if(!isset($included)) {
  2349. $name = uniqid("ex").".xml";
  2350. $tmpfname = $GLOBALS[DATA_DIR].$name;
  2351. $fp = fopen($tmpfname, "w");
  2352. fputs($fp, "<?xml version='1.0' encoding=\"utf-8\"?>");
  2353. fputs($fp, "<".$this->base."_set>");
  2354. } else {
  2355. $fp=$included;
  2356. }
  2357. // Construction des titres des colonnes
  2358. // cas ou les champs sont browsable si indique dans la base
  2359. reset($this->desc);
  2360. while(list($k,$v)=each($this->desc)) {
  2361. $libelles[$col] = $v->get_label();
  2362. $k = $v->get_field();
  2363. $label[$k]=$v->get_label();
  2364. $fieldcode[$col] = $k;
  2365. $fields.=$k;
  2366. $f[$k]=$k;
  2367. $col++;
  2368. }
  2369. $select = "select KOID$fields from ".$this->base." where LANG='".$LANG_DATA."'";
  2370. $rs=selectQuery($select);
  2371. $nblines=$rs->rowCount();
  2372. $myi=0;
  2373. // Construction des data
  2374. $ors=array();
  2375. while($ors=$rs->fetch()) {
  2376. reset($f);
  2377. $oid=$ors['KOID'];
  2378. fputs($fp, "<".$this->base." id=\"$oid\" xml:lang=\"$LANG_DATA\">");
  2379. while(list($k,$n)=each($f)) {
  2380. $def = $this->desc[$k];
  2381. $value = $ors['$k'];
  2382. $opt=$options[$k];
  2383. fputs($fp, $def->export($value));
  2384. }
  2385. fputs($fp, "</".$this->base.">");
  2386. if($linesize>0) {
  2387. $column++;
  2388. if($column >= $linesize) {
  2389. $linenum++;
  2390. $column=0;
  2391. }
  2392. }
  2393. $myi++;
  2394. }
  2395. fputs($fp, "</".$this->base."_set>");
  2396. if(isset($included)) fclose($fp);
  2397. $XSHELL->tpldata["$tplentry"] = array("message"=>"OK","url"=>$GLOBALS[DATA_URL].$name);
  2398. }
  2399. function gen_translate($ar=NULL) {
  2400. global $XSHELL;
  2401. global $XLANG;
  2402. $p = new XParam($ar,array( "tplentry"=>"",
  2403. "order"=>$this->getFirstFieldName(),
  2404. "first"=>0,
  2405. "pagesize"=>20 // nombre de lignes par page
  2406. ));
  2407. $tplentry = $p->get("tplentry");
  2408. $LANG_USER = XShell::getLangUser();
  2409. $first = $p->get("first");
  2410. $last = $p->get("last");
  2411. $order = $p->get("order");
  2412. $pagesize = $p->get("pagesize");
  2413. $oid = $p->get("oid");
  2414. $XLANG->getCodes();
  2415. $fields = "";
  2416. $col = 0;
  2417. $libelles=array();
  2418. $fieldcode=array();
  2419. reset($this->desc);
  2420. while(list($k,$v)=each($this->desc)) {
  2421. if($v->get_published()) {
  2422. $libelles[$col] = $v->get_label();
  2423. $fieldcode[$col] = $k;
  2424. $fields.=$k;
  2425. $f[$k]=$k;
  2426. $col++;
  2427. }
  2428. }
  2429. if(count($f)<=0) {
  2430. XShell::quit("XDataSource->translate: no published field in table $this->base<br/>\n");
  2431. }
  2432. $cond = "LANG = \"" . $LANG_USER . "\"";
  2433. if ($oid && ($oid!="") ) $cond .= " and KOID='$oid' ";
  2434. if ( !isset($last) ) {
  2435. $requete = "select count(*) from ".$this->base." where ".$cond;
  2436. $rs=selectQueryByNum($requete);
  2437. $t1=array();
  2438. if ($t1=$rs->fetch()) $last = $t1[0];
  2439. }
  2440. $requete = "select KOID$fields from ".$this->base." where ".$cond." order by ".$order." limit ".$first.", ".$pagesize;
  2441. $rs2=selectQuery($requete);
  2442. $myi=0;
  2443. $ors=array();
  2444. while($ors=$rs2->fetch()) {
  2445. reset($f);
  2446. $linesoid[$myi]=$ors['KOID'];
  2447. $linesrow[$myi]="<a name=\"".$linesoid[$myi]."\"/>";
  2448. $linesaction[$myi]="";
  2449. while(list($k,$n)=each($f)) {
  2450. $value = $ors['$k'];
  2451. $def=$this->desc[$k];
  2452. $o=$def->display2($value);
  2453. $val=$o->html;
  2454. $linesrow[$myi] = $linesrow[$myi]."<td>".$val."</td>\n";
  2455. ${$k}[$myi]=$val;
  2456. }
  2457. for ($myj=0; $myj<$XLANG->nbLang; $myj++) {
  2458. $LANG_DATA = $XLANG->codes[$myj];
  2459. if ( $this->objectExists( $linesoid[$myi], $LANG_DATA ) ) {
  2460. $theUrl = sprintf( "<A HREF=\"".$GLOBALS['TZR_SESSION_MANAGER']::complete_self()."&class=XDataSource&function=edit&table=".$this->base.
  2461. "&template=edit.html&oid=%s&LANG_DATA=%s&skip=1\">".XLabels::getSysLabel("general","edit")."</A>",
  2462. $linesoid[$myi],
  2463. $LANG_DATA
  2464. );
  2465. if ( $LANG_DATA != TZR_DEFAULT_LANG ) {
  2466. $theUrl .= ' ';
  2467. $theUrl .= sprintf( "<A HREF=\"".$GLOBALS['TZR_SESSION_MANAGER']::complete_self()."&class=Kernel&function=data_confirmDel&table=".$this->base.
  2468. "&template=generic_confirm.html&oid=%s&LANG_DATA=%s&skip=1\">".
  2469. XLabels::getSysLabel("general","delete")."</A>",
  2470. $linesoid[$myi],
  2471. $LANG_DATA
  2472. );
  2473. }
  2474. $linesaction[$myi] .= "<td>".$theUrl."</td>";
  2475. }
  2476. else {
  2477. $theUrl = sprintf( "<A HREF=\"".$GLOBALS['TZR_SESSION_MANAGER']::complete_self()."&class=Kernel&function=data_translate&table=".$this->base.
  2478. "&template=edit.html&oid=%s&LANG_DATA=%s&skip=1\">".
  2479. XLabels::getSysLabel("general","edit")."</A>",
  2480. $linesoid[$myi],
  2481. $LANG_DATA
  2482. );
  2483. $linesaction[$myi] .= "<td>".$theUrl."</td>";
  2484. }
  2485. }
  2486. $myi++;
  2487. }
  2488. $result['first']=$first;
  2489. $result['last']=$last;
  2490. $result['order']=$order;
  2491. $result['firstnext']=''.($first+$pagesize).'';
  2492. $result['firstprev']=''.($first-$pagesize>=0?($first-$pagesize):$first).'';
  2493. $result['pagesize']= $pagesize;
  2494. $result['header_fieldname']=$libelles;
  2495. $result['header_fieldcode']=$fieldcode;
  2496. $result['lang_header_code']=$XLANG->codes;
  2497. // $result['lines_row']=$linesrow;
  2498. $result['lines_action']=$linesaction;
  2499. $result['lines_oid']=$linesoid;
  2500. foreach($f as $k=>$n) {
  2501. $result['lines_'.$k]=${$k};
  2502. }
  2503. $XSHELL->tpldata["$tplentry"] = $result;
  2504. }
  2505. /// Suppression d'une source de donnees
  2506. function procDeleteDataSource($ar=NULL) {
  2507. if(empty($this->base)) securityWarning('XDataSource::procDeleteDataSource: trying to procDeleteBase with empty table');
  2508. // on verifie si c'est une table syteme
  2509. if($this->sysTable($this->base)) {
  2510. $txt=$this->base.' : '.XLabels::getSysLabel('xdatasource','cannot_delete').'</br>';
  2511. return array('message'=>$txt,'error'=>true);
  2512. }
  2513. // on verifie s'il y a des modules qui utilisent cette table
  2514. $mods=XModule::modulesUsingTable($this->base,true,false,false);
  2515. if(!empty($mods)) {
  2516. $txt=$this->base.' : '.XLabels::getSysLabel('xdatasource.table_in_use')."<br/><ul>";
  2517. foreach($mods as $moid => $name) {
  2518. $txt.="<li>$name ($moid)</li>";
  2519. }
  2520. $txt.='</ul><br/>'.XLabels::getSysLabel('xdatasource.cannot_delete').'</br>';
  2521. return array('message'=>$txt,'error'=>true);
  2522. }
  2523. // suppression des tuples dans Txxx
  2524. $table = $this->base;
  2525. $requete = "TRUNCATE $table";
  2526. updateQuery($requete);
  2527. if(XSystem::tableExists('A_'.$table)) {
  2528. $requete = "TRUNCATE A_$table";
  2529. updateQuery($requete);
  2530. }
  2531. // suppression des repertoires de donnees
  2532. XDir::unlink($GLOBALS['DATA_DIR'].$table,true,true);
  2533. // suppression dans BASEBASE et AMSG - recuperation du MOID
  2534. $requete = "delete AMSG from AMSG,BASEBASE where AMSG.MOID=BASEBASE.BOID and BTAB='$table'";
  2535. updateQuery($requete);
  2536. $requete = "DELETE FROM BASEBASE where BTAB = '$table'";
  2537. updateQuery($requete);
  2538. // suppression de l'ensemble de tables Txxx
  2539. // Drop table TXXX
  2540. $requete = "DROP TABLE $table";
  2541. updateQuery($requete);
  2542. if(XSystem::tableExists('A_'.$table)) {
  2543. $requete = "DROP TABLE A_$table";
  2544. updateQuery($requete);
  2545. }
  2546. // suppression de tous les champs de la table desc
  2547. $requete = "DELETE FROM DICT where DTAB='$table'";
  2548. updateQuery($requete);
  2549. // suppression de tous les libelles qui concernant cette table
  2550. $requete = "DELETE FROM MSGS where MTAB='$table'";
  2551. updateQuery($requete);
  2552. // suppression de tous les messages qui concernant cette table
  2553. $requete = "DELETE FROM SETS where STAB='$table';";
  2554. updateQuery($requete);
  2555. // suppression de toutes les options texte long des champs (commentaires...) de la table
  2556. $requete = 'DELETE FROM AMSG where MOID LIKE "'.$table.':%"';
  2557. $rs=&updateQuery($requete);
  2558. $txt=$this->base.' : '.XLabels::getSysLabel('xdatasource','update_ok').'</br>';
  2559. return array('message'=>$txt,'error'=>false);
  2560. }
  2561. static function createLetters() {
  2562. if(XSystem::tableExists('LETTERS')) {
  2563. return;
  2564. }
  2565. $lg = TZR_DEFAULT_LANG;
  2566. $ar1["translatable"]="1";
  2567. $ar1["auto_translate"]="1";
  2568. $ar1["btab"]='LETTERS';
  2569. $ar1["bname"][$lg]='System - '.XLabels::getSysLabel('general.letters');
  2570. XDSTable::procNewSource($ar1);
  2571. $x=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS=LETTERS');
  2572. // ord obl que bro tra mul pub tar
  2573. $x->createField('subject','Sujet','XShortTextDef','120','3','1','1','1','1','0','0');
  2574. $x->createField('name','Nom','XTextDef', '40','4','1','1','1','0','0','1');
  2575. $x->createField('modid','Module','XModuleDef', '','5','1','1','1','0','0','0');
  2576. $x->createField('letter','Corps','XTextDef', '60','6','0','0','0','1','0','0');
  2577. $x->createField('disp','Mise en page','XLinkDef', '','8','0','1','1','0','0','0','TEMPLATES');
  2578. }
  2579. function genImport($ar=NULL) {
  2580. global $XSHELL;
  2581. global $XLANG;
  2582. global $FILE_LINE_TERMINATOR_HTML;
  2583. global $TEXT_LINE_TERMINATOR_HTML;
  2584. global $FIELD_SEPARATOR_HTML;
  2585. global $FIELD_ENCLOSED_BY_HTML;
  2586. global $ESCAPE_CHAR_HTML;
  2587. $p = new XParam($ar, array("tplentry"=>""));
  2588. $tplentry = $p->get("tplentry");
  2589. $LANG_USER = XShell::getLangUser();
  2590. $LANG_DATA = XShell::getLangData();
  2591. // Recuperation des codes langue, pour le choix de la langue dans le fichier import
  2592. $XLANG->getCodes();
  2593. $lang = array();
  2594. $langSelectionFlag = array();
  2595. for ( $myi=0; $myi<$XLANG->nbLang; $myi++ ) {
  2596. $lang[$myi] = $XLANG->codes[$myi];
  2597. if ( $XLANG->codes[$myi] == $LANG_DATA ) $langSelectionFlag[$myi] = "selected";
  2598. else $langSelectionFlag[$myi] = "";
  2599. }
  2600. // Liste des champs de la table, pour le choix des champs a importer et leur valeur par defaut
  2601. $xsd = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->base);
  2602. if ( is_array($xsd->desc) ) {
  2603. $i = 0;
  2604. $order = 2;
  2605. foreach($xsd->desc as $k => $v) {
  2606. $fieldCodes[$i] = $k;
  2607. $fieldLabels[$i] = $v->get_label();
  2608. $fieldTypes[$i] = $v->get_ftype();
  2609. $fieldOrders[$i] = $order;
  2610. $fieldDefaults[$i] = $v->edit(array());
  2611. $i++;
  2612. }
  2613. }
  2614. $result = array();
  2615. $result["langs"] = $lang;
  2616. $result["langSelectionFlags"] = $langSelectionFlag;
  2617. $result["fieldCodes"]=$fieldCodes;
  2618. $result["fieldLabels"]=$fieldLabels;
  2619. $result["fieldTypes"]=$fieldTypes;
  2620. $result["fieldOrders"]=$fieldOrders;
  2621. $result["fieldDefaults"]=$fieldDefaults;
  2622. $result["fileLineTerminator"] = $FILE_LINE_TERMINATOR_HTML;
  2623. $result["textLineTerminator"] = $TEXT_LINE_TERMINATOR_HTML;
  2624. $result["fieldSeparator"] = $FIELD_SEPARATOR_HTML;
  2625. $result["fieldEnclosedBy"] = $FIELD_ENCLOSED_BY_HTML;
  2626. $result["escapeChar"] = $ESCAPE_CHAR_HTML;
  2627. $XSHELL->tpldata["$tplentry"] = $result;
  2628. }
  2629. /// Ensemble d'actions à effectuer avant qu'une modification de donnée ait lieu
  2630. protected function preUpdateTasks(&$ar) {
  2631. if(!empty($ar['noupdatetasks'])) return false;
  2632. if(array_key_exists('fmoid',$ar)){
  2633. $mod=XModule::objectFactory($ar['fmoid']);
  2634. $mod->preUpdateTasks($ar);
  2635. }
  2636. return true;
  2637. }
  2638. /// Ensemble d'actions à effectuer après qu'une modification de donnée ait eu lieu
  2639. protected function updateTasks(&$ar,$oid) {
  2640. if(!empty($ar['noupdatetasks'])) return false;
  2641. if(array_key_exists('fmoid',$ar)){
  2642. $mod=XModule::objectFactory($ar['fmoid']);
  2643. $mod->updateTasks($ar,$oid);
  2644. }
  2645. return true;
  2646. }
  2647. /// Tague les metas des champs fichiers à partir des données de la fiche
  2648. function setFilesMeta($ar){
  2649. $p=new XParam($ar);
  2650. $oid=$p->get('oid');
  2651. if(is_array($oid)){
  2652. foreach($oid as $tmpoid){
  2653. $ar1=$ar;
  2654. $ar1['oid']=$tmpoid;
  2655. $this->setFilesMeta($ar1);
  2656. }
  2657. return;
  2658. }
  2659. if(!$this->isTranslatable()) $LANG_DATA=TZR_DEFAULT_LANG;
  2660. else $LANG_DATA=XShell::getLangData(@$ar['LANG_DATA']);
  2661. $langs=$p->get('_langs');
  2662. if($LANG_DATA==TZR_DEFAULT_LANG && !empty($langs)){
  2663. // Si langue par defaut et langs spécifié, on ne tague que la langue par defaut, les autres langues le seront via le procEdit qui sera executé pour chaque langue
  2664. $langs=array($LANG_DATA);
  2665. }elseif($LANG_DATA==TZR_DEFAULT_LANG){
  2666. // Si langue par defaut et langs non spécifié, on tague toutes les langues
  2667. $langs=XLang::getCodes('code');
  2668. }else{
  2669. // SI pas langue par défaut, on ne tague que la langue en cours
  2670. $langs=array($LANG_DATA);
  2671. }
  2672. $xfiles=$this->getFieldsList(array('XFileDef','XImageDef'));
  2673. if(empty($xfiles)) return;
  2674. foreach($langs as $lang){
  2675. $d=null;
  2676. foreach($xfiles as $fname){
  2677. $field=$this->desc[$fname];
  2678. if($field->auto_write_meta && ($lang==TZR_DEFAULT_LANG || $this->isTranslatable() && $field->get_translatable())){
  2679. if(empty($d)) $d=$this->display(array('tplentry'=>TZR_RETURN_DATA,'LANG_DATA'=>$lang,'oid'=>$oid,'_lastupdate'=>0));
  2680. $this->_setFilesMeta($field,$d);
  2681. }
  2682. }
  2683. }
  2684. }
  2685. // Sous méthode de setFilesMeta pour enrichissement simple des données à taguer
  2686. function _setFilesMeta($field,$d){
  2687. XFileDef::setFileMetaWithDisplay($d,$d['o'.$field->field]->filename);
  2688. }
  2689. // implementation de l'interface des documents
  2690. function &XMCinput($ar) {
  2691. return $this->input($ar);
  2692. }
  2693. function &XMCprocInput($ar) {
  2694. return $this->procInput($ar);
  2695. }
  2696. function &XMCedit($ar) {
  2697. return $this->edit($ar);
  2698. }
  2699. function &XMCprocEdit($ar) {
  2700. return $this->procEdit($ar);
  2701. }
  2702. function &XMCprocEditDup($ar) {
  2703. return $this->procEditDup($ar);
  2704. }
  2705. function &XMCdisplay($ar,$rdisplay=true) {
  2706. if($rdisplay) return $this->rDisplay($ar['oid'],array(),false,'','',$ar);
  2707. else return $this->display($ar);
  2708. }
  2709. function &XMCdel($ar) {
  2710. return $this->del($ar);
  2711. }
  2712. function &XMCduplicate($oidsrc){
  2713. if(!is_array($oidsrc)) $oidsrc=array('oid'=>$oidsrc);
  2714. return $this->duplicate($oidsrc);
  2715. }
  2716. function &XMCquery($ar){
  2717. return $this->query($ar);
  2718. }
  2719. function &XMCprocQuery($ar){
  2720. return $this->procQuery($ar);
  2721. }
  2722. /// Debut v8
  2723. /// Fonction checker pour v8
  2724. static function procNewSource($ar){
  2725. return array('message'=>'','error'=>false);
  2726. }
  2727. function browseFields($ar=NULL){
  2728. }
  2729. function newField($ar=NULL){
  2730. }
  2731. function procNewField($ar=NULL){
  2732. }
  2733. /// imaginer le nouvel ordre a partir du parametre forder, numero ou nom de champ
  2734. protected function _guessFieldOrder($forder) {
  2735. // cas ou forder est le nom du champ apres lequel on veut se placer
  2736. if(!is_numeric($forder) && !empty($forder)) {
  2737. $max=selectQueryGetOne('select FORDER FROM DICT WHERE DTAB="'.$this->base.'" AND FIELD="'.$forder.'"');
  2738. if(!empty($max)) $forder=$max['FORDER']+1;
  2739. }
  2740. // on sait pas ou se placer on se met a la fin
  2741. if(empty($forder)) {
  2742. $max=selectQueryGetOne('select FORDER FROM DICT WHERE DTAB="'.$this->base.'" ORDER BY FORDER DESC');
  2743. $forder=$max['FORDER']+1;
  2744. }
  2745. return $forder;
  2746. }
  2747. /// publication de certains fields seulement
  2748. // on depublie tous les champs sauf ceux qui sont dans le tableau en parametre
  2749. function publishOnlyFields($fieldsarray) {
  2750. $fields=implode('","',$fieldsarray);
  2751. updateQuery('UPDATE DICT SET PUBLISHED=0 WHERE DTAB="'.$this->base.'"');
  2752. updateQuery('UPDATE DICT SET PUBLISHED=1 WHERE DTAB="'.$this->base.'" AND FIELD IN ("'.$fields.'")');
  2753. }
  2754. /// Creation d'un champ avec les parameteres en liste pluttot que dans un tableau
  2755. function createField($field,$label,$ftype,$fcount,$forder,$compulsory,$queryable=true,$browsable=true,$translatable=true,$multi=false,
  2756. $published=false,$target='',$options=array()) {
  2757. $ar=array();
  2758. $ar['field']=$field;
  2759. $ar['ftype']=$ftype;
  2760. $ar['fcount']=$fcount;
  2761. $ar['forder'] = $this->_guessFieldOrder($forder);
  2762. $ar['compulsory']=$compulsory;
  2763. $ar['queryable']=$queryable;
  2764. $ar['browsable']=$browsable;
  2765. $ar['translatable']=$translatable;
  2766. $ar['multivalued']=$multi;
  2767. $ar['published']=$published;
  2768. if(empty($label)) $label=$field;
  2769. $ar['label'][TZR_DEFAULT_LANG]=$label;
  2770. $ar['target']=$target;
  2771. $ar['options']=$options;
  2772. return $this->procNewField($ar);
  2773. }
  2774. function editField($ar=NULL){
  2775. }
  2776. function procEditField($ar=NULL){
  2777. }
  2778. /// sauvegarde des changements sur la liste des champs
  2779. function procEditFields($ar=NULL) {
  2780. $p=new XParam($ar,array('batch'=>0));
  2781. $message='';
  2782. $error=false;
  2783. $fields=$p->get('field');
  2784. $compulsory=$p->get('compulsory');
  2785. $queryable=$p->get('queryable');
  2786. $browsable=$p->get('browsable');
  2787. $translatable=$p->get('translatable');
  2788. $multivalued=$p->get('multivalued');
  2789. $published=$p->get('published');
  2790. $tplentry=$p->get('tplentry');
  2791. $forder=$p->get('forder');
  2792. $fcount=$p->get('fcount');
  2793. $addOption=substr($p->get('addOption'), 2); // option additionnelle prefixée par __
  2794. $addOptions=$p->get('addOptions'); // valeurs de l'option additionnelle
  2795. foreach($fields as $field=>$v) {
  2796. $label=$this->desc[$field]->get_labels();
  2797. $ar=array('field'=>$field,
  2798. 'ftype'=>$this->desc[$field]->get_ftype(),
  2799. 'forder'=>$this->desc[$field]->get_forder(),
  2800. 'browsable'=>($browsable[$field]?$browsable[$field]:false),
  2801. 'fcount'=>($fcount[$field]?$fcount[$field]:false),
  2802. 'forder'=>($forder[$field]?$forder[$field]:0),
  2803. 'queryable'=>($queryable[$field]?$queryable[$field]:false),
  2804. 'compulsory'=>($compulsory[$field]?$compulsory[$field]:false),
  2805. 'translatable'=>($translatable[$field]?$translatable[$field]:false),
  2806. 'multivalued'=>($multivalued[$field]?$multivalued[$field]:false),
  2807. 'published'=>($published[$field]?$published[$field]:false),
  2808. 'label'=>$label,
  2809. 'target'=>$this->desc[$field]->get_target(),
  2810. 'options'=>(isset($addOptions[$field][$addOption])?array($addOption=>$addOptions[$field][$addOption]):null));
  2811. $tmp=$this->procEditField($ar);
  2812. $message.=$tmp['message'];
  2813. if($tmp['error']) $error=true;
  2814. }
  2815. return array('message'=>$message,'error'=>$error);
  2816. }
  2817. /// Supprime un champ
  2818. function delField($ar=NULL){
  2819. }
  2820. /// Cherche le premier nom de champo automatique disponible
  2821. function newFieldName() {
  2822. $no=1;
  2823. $found=false;
  2824. while(!$found) {
  2825. $fname=sprintf('F%04d',$no);
  2826. if(!$this->fieldExists($fname)) $found=true;
  2827. else $no++;
  2828. }
  2829. return $fname;
  2830. }
  2831. /// Verifie la présence des infos obligatoires avant création d'un champ et les renseigne si necessaire
  2832. function newFieldDescIsCorrect(&$field,&$ftype,&$fcount,&$forder,&$compulsory,&$queryable,&$browsable,$translatable,&$multivalued,
  2833. &$published,&$target,&$label) {
  2834. if(empty($field)) $field=$this->newFieldName();
  2835. if(isSQLKeyword($field)) return false;
  2836. if(isTZRKeyword($field)) return false;
  2837. if(is_numeric($field)) return false;
  2838. $field=str_replace(' ','',$field);
  2839. if($label[TZR_DEFAULT_LANG]=='') $label[TZR_DEFAULT_LANG]=$field;
  2840. if(XFieldDef::getFCount($ftype)){
  2841. if($fcount<=0 ) $fcount=1;
  2842. } else $fcount=0;
  2843. if(!is_numeric($forder) || $forder<=0) $forder=$this->newFieldOrder();
  2844. if(!XFieldDef::getUseTarget($ftype)) $target=TZR_DEFAULT_TARGET;
  2845. if(!XFieldDef::typeExists($ftype)) return false;
  2846. return true;
  2847. }
  2848. /// Ajoute un champ dans le desc
  2849. function newDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,$target,$labels,$options=array()) {
  2850. $r1=array('FIELD'=>$field,'FTYPE'=>$ftype,'DTAB'=>$this->base,'FCOUNT'=>$fcount,'FORDER'=>$forder);
  2851. $obj=(object)$r1;
  2852. $def=XFieldDef::objectFactory($obj);
  2853. $def->set_compulsory($compulsory);
  2854. $def->set_queryable($queryable);
  2855. $def->set_browsable($browsable);
  2856. $def->set_translatable($translatable);
  2857. $def->set_multivalued($multivalued);
  2858. $def->set_published($published);
  2859. $def->set_labels($labels);
  2860. $def->set_target($target);
  2861. $def->_options->procDialog($def,$options);
  2862. $this->desc[$field]=$def;
  2863. }
  2864. /// Modifie un champ dans le desc
  2865. function changeDesc($field, $ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,$target,$label) {
  2866. $this->delDesc($field);
  2867. $this->newDesc($field,$ftype,$fcount,$forder,$compulsory,$queryable,$browsable,$translatable,$multivalued,$published,$target,$label);
  2868. }
  2869. /// Supprime un champ du desc
  2870. function delDesc($field) {
  2871. unset($this->desc[$field]);
  2872. }
  2873. /// Check la validité d'un champ dans le desc
  2874. function fieldDescIsCorrect($field,&$ftype,&$fcount,&$forder,&$compulsory,&$queryable,&$browsable,&$translatable,&$multivalued,&$published,&$target,&$label) {
  2875. $def=$this->desc[$field];
  2876. if($label[TZR_DEFAULT_LANG]=='') $label[TZR_DEFAULT_LANG]=$def->get_label();
  2877. if(XFieldDef::getFCount($ftype)) {
  2878. if($fcount<1) {
  2879. if($ftype==$def->get_ftype()) $fcount=$def->get_fcount();
  2880. else $fcount=1;
  2881. }
  2882. }else $fcount=0;
  2883. if(!is_numeric($forder) || $forder<1) $forder=$def->get_forder();
  2884. if(!XFieldDef::getUseTarget($ftype)) $target=TZR_DEFAULT_TARGET;
  2885. return true;
  2886. }
  2887. /// Test d'existence d'un champ
  2888. public function fieldExists($f) {
  2889. return isset($this->desc[$f]);
  2890. }
  2891. /// Retourne la liste de champ de type XLinkDef
  2892. public function &getXLinkDefs($limits=NULL,$target=NULL) {
  2893. $links=array();
  2894. foreach($this->desc as $i => &$v) {
  2895. if($v->isObjectLink() && ($target == $v->get_target() || empty($target))) {
  2896. $f=$v->get_field();
  2897. if(empty($limits) || in_array($f,$limits)) $links[]=$f;
  2898. }
  2899. }
  2900. return $links;
  2901. }
  2902. /// Retourne la liste des champs de type oid utilisant la table
  2903. static function fieldsUsingTable($table,$oid=NULL) {
  2904. $ret=array();
  2905. $rs=selectQuery('select * from DICT where FTYPE IN ("'.implode('","',XFieldDef::getObjectLinkTypes()).'") AND TARGET="'.$table.'"');
  2906. while($rs && ($ors=$rs->fetch())){
  2907. $ret[]=$ors['DTAB'].' '.$ors['FIELD'];
  2908. }
  2909. return $ret;
  2910. }
  2911. /// Vide la table
  2912. public function clear($rq=NULL) {
  2913. }
  2914. /// Duplique la source (sans les données)
  2915. public function procDuplicateDataSource($ar=NULL){
  2916. }
  2917. /// Check/repare la source de donnée
  2918. public function chk($ar=NULL) {
  2919. }
  2920. /// Edition des proprietes d'une source
  2921. function editProperties($ar=NULL) {
  2922. $p=new XParam($ar, array('tplentry'=>''));
  2923. $tplentry=$p->get('tplentry');
  2924. $values=(object)array('translate'=>$this->getTranslatable(),'auto_translate'=>$this->getAutoTranslate(),'classname'=>get_class($this));
  2925. $rs=selectQuery('select * from AMSG where MOID="'.$this->boid.'"');
  2926. while($rs && ($ors=$rs->fetch())) $values->bname[$ors['MLANG']]=$ors['MTXT'];
  2927. $options=new XOptions();
  2928. $options->setId($this->boid);
  2929. $options->setOpt(XLabels::getSysLabel('xdatasource','table_name'),'bname','ttext');
  2930. $options->setOpt(XLabels::getSysLabel('xdatasource','translatable'),'translate','list',
  2931. array('values'=>array('1','0',TZR_LANG_FREELANG),
  2932. 'labels'=>array(XLabels::getSysLabel('general','yes','text'),
  2933. XLabels::getSysLabel('general','no','text'),
  2934. XLabels::getSysLabel('xdatasource','freelang','text'))));
  2935. $options->setOpt(XLabels::getSysLabel('xdatasource','automatic_translation'),'auto_translate','boolean');
  2936. $options->setOpt(XLabels::getSysLabel('general','theclass'),'classname','text');
  2937. $optsglob=$options->getDialog($values,NULL,'options');
  2938. $opts=$this->_options->getDialog($this,NULL,'options');
  2939. $result=array('options'=>$opts,'optionsglob'=>$optsglob,'boid'=>$this->boid,'table'=>$this->base);
  2940. return XShell::toScreen1($tplentry,$result);
  2941. }
  2942. /// Sauvegarde des proprietes d'une datasource
  2943. function procEditProperties($ar=NULL) {
  2944. $p=new XParam($ar,array('tplentry'=>''));
  2945. $options=$p->get('options');
  2946. $bname=$options['bname'];
  2947. $translate=$options['translate'];
  2948. $auto_translate=$options['auto_translate'];
  2949. $class=$options['classname'];
  2950. if(!empty($auto_translate)) $translate=1;
  2951. if(empty($class)) $class='XDSTable';
  2952. $this->_options->procDialog($this,$options);
  2953. $xml=$this->_options->toXML($this);
  2954. if ($class == 'XDSTableView') {
  2955. XDSTableView::updateView($this->base, $this->query);
  2956. }
  2957. preparedUpdateQuery('update BASEBASE set TRANSLATABLE=?, AUTO_TRANSLATE=?, BCLASS=?,BPARAM=? where BOID=?',
  2958. array($translate,$auto_translate,$class,$xml,$this->boid));
  2959. XLabels::updateAMsg($this->boid,$bname);
  2960. }
  2961. /// generation du fichier source
  2962. function exportSpec(&$sheet){
  2963. }
  2964. function importSpec(&$sheet,&$message){
  2965. }
  2966. /// Fin v8
  2967. }
  2968. XDataSource::$_sources=array();
  2969. XDataSource::$_sources['XDSTable']=array('SOURCE'=>'Table SQL','CLASSNAME'=>'XDSTable');
  2970. XDataSource::$_sources['XDSTableView']=array('SOURCE'=>'Vue SQL','CLASSNAME'=>'XDSTableView');
  2971. ?>