PageRenderTime 61ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/class.xlink2def.inc

https://github.com/jcplat/console-seolan
PHP | 1346 lines | 1173 code | 67 blank | 106 comment | 383 complexity | 8832a09277f978b3a47c7deaaed31133 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. define('XLINK2DEF_MAXLINKS',3);
  3. define('XLINK2DEF_MAXPOPUPLINKS',100);
  4. define('XLINK2DEF_MAXLINKEDFIELD',1);
  5. @require_once 'pack.autocomplete.inc';
  6. /// Gestion des champs Lien entre les objets des tables
  7. class XLink2Def extends XFieldDef {
  8. public $filter='';
  9. public $query='';
  10. public $boxsizxe=6;
  11. public $usedefault=true;
  12. public $checkbox=true;
  13. public $doublebox=false;
  14. public $checkbox_limit=30;
  15. public $autocomplete=true;
  16. public $autocomplete_limit=200;
  17. public $generate_link = true;
  18. public $checkbox_cols=3;
  19. private $_cache=array();
  20. protected $modsUsingTable=NULL;
  21. public $query_formats=array('classic','listbox-one','listbox','autocomplete');
  22. public $advanceeditbatch=true;
  23. public $display_format='';
  24. public $linkedfields1=NULL;
  25. protected $fieldlist=NULL;
  26. function __construct($obj=NULL) {
  27. parent::__construct($obj);
  28. }
  29. function cacheable() { return false; }
  30. function clearCache(){ $this->_cache=array(); }
  31. function initOptions() {
  32. parent::initOptions();
  33. $this->_options->delOpt('dependency');
  34. $this->_options->delOpt('aliasmodule');
  35. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','sourcemodule'),'sourcemodule','module',array('emptyok'=>true));
  36. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','usedefault'), "usedefault", "boolean", array(),true);
  37. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','filter'), 'filter', 'text',array('rows'=>2,'cols'=>60));
  38. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','query'), 'query', 'text',array('rows'=>2,'cols'=>60));
  39. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','display_format'), 'display_format', 'text');
  40. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','checkbox'), 'checkbox', 'boolean');
  41. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','checkbox_limit'), 'checkbox_limit', 'text');
  42. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','checkbox_cols'), 'checkbox_cols', 'text');
  43. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','autocomplete'), 'autocomplete', 'boolean',NULL,true);
  44. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','autocomplete_limit'), 'autocomplete_limit', 'text',NULL,200);
  45. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','doublebox'), 'doublebox', 'boolean',NULL,false);
  46. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','boxsize'), 'boxsize', 'text', NULL, 6);
  47. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','grouplist'), 'grouplist', 'boolean', NULL, false);
  48. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','generate_link'), 'generate_link', 'boolean',NULL, true);
  49. for($i=1; $i<=XLINK2DEF_MAXLINKEDFIELD; $i++) {
  50. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','linkedfield').' '.$i, 'linkedfields'.$i, 'field', array('table'=>$this->table, 'compulsory'=>false, 'type'=>array('XLink2Def')), '');
  51. }
  52. }
  53. /**
  54. * Génère le formulaire d'édition des options du champs
  55. * @see XOptions::getDialog()
  56. */
  57. function getOptions($block='opt') {
  58. return XLinkDef::getOptions($block);
  59. }
  60. function get_sqlValue($value) {
  61. // Fabrique une valeur de colonne pour SQL à partir d'une valeur issue de PHP
  62. // $value est ici un tableau. 1 seul valeur si champ single value, n valeurs si multi value
  63. if ( !is_array($value) ) return $value;
  64. $nb = count($value);
  65. if ( $nb == 0 ) return '';
  66. if ( (!$this->get_multivalued()) || ($nb==1) ) {
  67. return $value;
  68. }
  69. else {
  70. $val = '||';
  71. for ($i=0;$i<$nb;$i++) {
  72. $val .= $value[$i] . '||';
  73. }
  74. return $val;
  75. }
  76. }
  77. function my_export($value, $options=NULL) {
  78. return $value;
  79. }
  80. function &getValues($filter2, $options=array()) {
  81. $mod=&$options['mod'];
  82. $max=$options['max'];
  83. $lang=XShell::getLangUser();
  84. $lang_data=XShell::getLangData();
  85. $result=array();
  86. if($this->target==TZR_DEFAULT_TARGET || !XDataSource::sourceExists($this->target)) return $result;
  87. // Liste des champs à recuperer
  88. list($myliste,$my_flist,$first)=$this->getFieldList($options,false);
  89. // Création de la requete
  90. $textfilter2=(count($myliste)>0)?'concat(':'';
  91. $fromcomp='';
  92. $i=0;
  93. foreach($myliste as $fn=>$obj){
  94. $i++;
  95. if($filter2){
  96. if(in_array($obj->get_ftype(),array('XTextDef','XShortTextDef','XRichTextDef')))
  97. $textfilter2.='ifnull('.$this->target.'.'.$fn.',""),\' \',';
  98. elseif($obj->isObjectLink() && !empty($obj->target) && $obj->target!='%'){
  99. $tablealias=$obj->target.'_'.$i;
  100. $fromcomp.=' left outer join '.$obj->target.' as '.$tablealias.' on '.$tablealias.'.KOID='.$this->target.'.'.$fn.' and '.$tablealias.'.LANG="'.TZR_DEFAULT_LANG.'" ';
  101. $rslink=&cacheSelectQuery('select * from DICT where PUBLISHED=1 and DTAB="'.$obj->target.'" and FTYPE="XShortTextDef" ORDER BY FORDER');
  102. while($rslink && ($orslink=$rslink->fetch())) $textfilter2.='ifnull('.$tablealias.'.'.$orslink['FIELD'].',""),\' \',';
  103. $rslink->CloseCursor();
  104. }elseif($obj->get_ftype()=='XStringSetDef'){
  105. $tablealias='SETS_'.$i;
  106. $fromcomp.=' LEFT OUTER JOIN SETS AS '.$tablealias.' ON '.$tablealias.'.SOID='.$this->target.'.'.$fn.' AND '.
  107. $tablealias.'.SLANG="'.TZR_DEFAULT_LANG.'" AND '.$tablealias.'.STAB="'.$this->target.'" AND '.$tablealias.'.FIELD="'.$fn.'" ';
  108. $textfilter2.='IFNULL('.$tablealias.'.STXT,""),\' \',';
  109. }
  110. }
  111. }
  112. if($textfilter2) $textfilter2 ='('.substr($textfilter2,0,-5).')'.' LIKE "%'.$filter2.'%") AND ';
  113. $filter=$this->filter;
  114. if(!empty($options['filter'])) $filter='('.$options['filter'].')';
  115. if(!empty($filter)) $filter.=' AND ';
  116. $rs2=selectQuery('select distinct '.$my_flist.' FROM '.$this->target.' '.$fromcomp.
  117. ' WHERE '.$textfilter2.' '.$filter.' '.$this->target.'.LANG="'.TZR_DEFAULT_LANG.'" '.
  118. (!empty($myliste)?'order by '.$this->target.'.'.implode(','.$this->target.'.',array_keys($myliste)):''));
  119. // Generation de la boite de saisie
  120. $state='ok';
  121. $tot=0;
  122. $opts=array('_published'=>'all', '_charset'=>$options['_charset']);
  123. while($ors2=$rs2->fetch()) {
  124. if(!empty($max) && $tot>$max){
  125. $state='toomuch';
  126. break;
  127. }
  128. $my_oid=$ors2['KOID'];
  129. if(!empty($mod) && $mod->object_sec && Kernel::getTable($my_oid)==$mod->table && !$mod->secure($my_oid,':ro')) continue;
  130. $result[$my_oid]=trim($this->format_display($myliste,$ors2,$opts,null,'text'));
  131. $tot++;
  132. }
  133. return array('values'=>$result,'state'=>$state);;
  134. }
  135. function sqltype() {
  136. return 'text';
  137. }
  138. /**
  139. * Affichage du champ lien, appel rDisplay sur la cible
  140. * (traitement multivalue dans xfielddef)
  141. * ! effet de bord : si l'objet est introuvable, supprime tous les liens vers cet objet
  142. * sauf si XDbIni[disable_xlinkclean] est positionné à 1
  143. * @param KOID $value unique dans la table cible ou 'UNPUBLISHED',
  144. * @param array $options [
  145. * string _format application/excel, application/prince
  146. * string _charset charset passé au rDisplay
  147. * mixed target_fields tableau des champs ramenés ou 'all' (rDisplay selectedfields)
  148. * boolean nocache n'utilise pas le cache
  149. * boolean nofollowlinks retourne juste l'oid sans appel au rdisplay
  150. * ]
  151. * @return XFieldVal
  152. */
  153. function my_display(&$value, &$options) {
  154. $_format = @$options['_format'];
  155. $LANG_DATA = XShell::getLangData();
  156. $lang = XShell::getLangUser();
  157. $olddisplayformat=NULL;
  158. // Verifie le cache
  159. if(isset($this->_cache[$value]) && @$options['nocache']!==true) {
  160. $r=clone $this->_cache[$value];
  161. return $r;
  162. }
  163. // OID valide
  164. $r=&$this->_newXFieldVal($options);
  165. if(empty($value) || strpos($value,'VOID:')) return $r;
  166. // l'oid sans la cible
  167. if(!empty($options['nofollowlinks'])) {
  168. $r->raw=$value;
  169. $r->html='';
  170. return $r;
  171. }
  172. // Table existe
  173. $target=Kernel::getTable($value);
  174. if(!XSystem::tableExists($target)) return $r;
  175. // Droit sur le module source de données
  176. if($this->sourcemodule){
  177. $mod=XModule::objectFactory($this->sourcemodule);
  178. if($mod->object_sec && !$mod->secure($value,':ro') || !$mod->object_sec && !$mod->secure('',':ro')) return $r;
  179. }
  180. $target_ds=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$target);
  181. if(!empty($options['target_options'])) $targetopts=$options['target_options'];
  182. else $targetopts=array();
  183. if(!empty($options['_charset'])) $targetopts['_charset']=$options['_charset'];
  184. else $targetopts['_charset'] = XLang::getCharset();
  185. // Liste des champs à recuperer
  186. if(@$options['display_format']){
  187. $olddisplayformat=$this->display_format;
  188. $this->display_format=$options['display_format'];
  189. }
  190. if(strpos($this->display_format,'%_')!==false){
  191. preg_match_all('/%_([a-z0-9_]+)/i',$this->display_format,$fmtfields);
  192. $fmtfields=$fmtfields[1];
  193. }else{
  194. $fmtfields=array();
  195. }
  196. if(isset($options['target_fields'])) $targetopts['selectedfields']=$options['target_fields'];
  197. else $targetopts['selectedfields']=$target_ds->getPublished(false);
  198. $targetopts['selectedfields']=array_merge($fmtfields,$targetopts['selectedfields']);
  199. // Recupere les champs de l'objet cible
  200. $values=&$target_ds->rDisplay($value, array(), false, $LANG_DATA, $lang, $targetopts);
  201. $cnt=count($values['fields_object']);
  202. if (XShell::admini_mode())
  203. $cnt = max($cnt, $this->getNbPublishedFields());
  204. // Si l'oid n'existe plus, on met à jour la table pour supprimer l'oid partout ou il est present et on retourne un objet sans valeur
  205. if(!is_array($values) && $values!='UNPUBLISHED' && XDbIni::get('disable_xlinkclean','val')!=1) {
  206. // Si la table est traduisible et qu'on est pas dans la langue par defaut, on verifie si l'oid existe dans au moins une langue
  207. if($target_ds->isTranslatable() && $LANG_DATA!=TZR_DEFAULT_LANG){
  208. $nb=countSelectQuery('SELECT count(*) FROM '.$this->target.' WHERE KOID="'.$value.'"');
  209. if($nb) return $r;
  210. }
  211. // Multivalué, traite tous les cas possibles (%||oid||%, oid||% et %||oid)
  212. $tolog=($target_ds->toLog() && $this->table!='LOGS');
  213. if($this->multivalued){
  214. $l=strlen($value);
  215. // %||oid||%
  216. if($tolog) {
  217. $rs=selectQuery('select KOID from '.$this->table.' where '.$this->field.' like "%||'.$value.'||%"');
  218. while($rs && ($ors=$rs->fetch())) XLogs::update('update',$ors['KOID'],'remove oid '.$value.' from '.$this->field);
  219. }
  220. if(!$tolog || $rs->rowCount()>0) {
  221. updateQuery('update '.$this->table.' set UPD=UPD,'.$this->field.'=REPLACE('.$this->field.',"||'.$value.'||","||") '.
  222. 'where '.$this->field.' like "%||'.$value.'||%"');
  223. }
  224. // oid||%
  225. if($tolog) {
  226. $rs=selectQuery('select KOID from '.$this->table.' where '.$this->field.' like "'.$value.'||%"');
  227. while($rs && ($ors=$rs->fetch())) XLogs::update('update',$ors['KOID'],'remove oid '.$value.' from '.$this->field);
  228. }
  229. if(!$tolog || $rs->rowCount()>0) {
  230. updateQuery('update '.$this->table.' set UPD=UPD,'.$this->field.'=SUBSTR('.$this->field.','.($l+3).') '.
  231. 'where '.$this->field.' like "'.$value.'||%"');
  232. }
  233. // %||oid
  234. if($tolog) {
  235. $rs=selectQuery('select KOID from '.$this->table.' where '.$this->field.' like "%||'.$value.'||%"');
  236. while($rs && ($ors=$rs->fetch())) XLogs::update('update',$ors['KOID'],'remove oid '.$value.' from '.$this->field);
  237. }
  238. if(!$tolog || $rs->rowCount()>0) {
  239. updateQuery('update '.$this->table.' set UPD=UPD,'.$this->field.'=SUBSTR('.$this->field.',1,LENGTH('.$this->field.')-'.($l+2).') '.
  240. 'where '.$this->field.' like "%||'.$value.'"');
  241. }
  242. }
  243. if($tolog) {
  244. $rs=selectQuery('select KOID from '.$this->table.' where '.$this->field.'="'.$value.'"');
  245. while($rs && ($ors=$rs->fetch())) XLogs::update('update',$ors['KOID'],'remove oid '.$value.' from '.$this->field);
  246. }
  247. if(!$tolog || $rs->rowCount()>0) updateQuery('update '.$this->table.' set UPD=UPD,'.$this->field.'="" where '.$this->field.'="'.$value.'"');
  248. $r->raw='';
  249. return $r;
  250. }elseif($values=='UNPUBLISHED'){
  251. $r->raw='';
  252. return $r;
  253. }
  254. // Prepare le html
  255. $display='';
  256. if(!empty($this->display_format)){
  257. if(strpos($this->display_format,'%_')!==false){
  258. $display=$this->display_format;
  259. foreach($fmtfields as $f) $display=str_replace('%_'.$f,$values['o'.$f]->html,$display);
  260. }else{
  261. $htmls=array();
  262. foreach($values['fields_object'] as $f) $htmls[]=$f->html;
  263. $display=@vsprintf($this->display_format,array_pad($htmls,substr_count($this->display_format,'%'),''));
  264. }
  265. }
  266. if(empty($this->display_format) || $display===false){
  267. for($i=0;$i<$this->getNbPublishedFields();$i++) {
  268. if(!isset($values['fields_object'][$i])) break;
  269. if($i==0) $display.=$values['fields_object'][$i]->html;
  270. else $display.=' '.$values['fields_object'][$i]->html;
  271. }
  272. }
  273. // Ajoute les liens vers l'objet dans le html si necessaire
  274. $r->html=$display;
  275. if(XShell::admini_mode() && $this->generate_link){
  276. if($this->modsUsingTable===NULL){
  277. if($this->sourcemodule) $this->modsUsingTable=array($mod->_moid=>$mod->modulename);
  278. else $this->modsUsingTable=XModule::modulesUsingTable($target,false,true,true,true);
  279. }
  280. if(!empty($this->modsUsingTable)) {
  281. $url=$GLOBALS['TZR_SESSION_MANAGER']::admin_url(false,true);
  282. if($_format!='application/prince' && $_format!='application/excel') {
  283. if(count($this->modsUsingTable)>1) {
  284. $mi=0;
  285. foreach($this->modsUsingTable as $mod=>&$label) {
  286. $mi++;
  287. if($mi<=XLINK2DEF_MAXLINKS) {
  288. if($mi==1) $r->html.=' [';
  289. else $r->html.='|';
  290. $r->html.='<a class="cv8-ajaxlink" href="'.$url.'&moid='.$mod.'&function=goto1&oid='.$value.'" title="'.$label.'">'.$mi.'</a>';
  291. }
  292. }
  293. if($mi>0) $r->html.=']';
  294. } else {
  295. reset($this->modsUsingTable);
  296. $v1=each($this->modsUsingTable);
  297. $r->html='<a class="cv8-ajaxlink" href="'.$url.'&moid='.$v1['key'].'&function=goto1&oid='.$value.'" title="'.$v1['value'].'">'
  298. .preg_replace('@<a([^>]*)>([^<]*)</a>@i','$2',$r->html).'</a>';
  299. }
  300. }
  301. }
  302. }
  303. $r->title=$display;
  304. $r->link=$values;
  305. $r->raw=$value;
  306. $this->_cache[$value]=$r;
  307. if($olddisplayformat) $this->display_format=$olddisplayformat;
  308. return $r;
  309. }
  310. function my_browse(&$value, &$options) {
  311. $r= &$this->_newXFieldVal($options);
  312. if(!empty($options['nofollowlinks'])) {
  313. $r->raw=$value;
  314. $r->html='';
  315. return $r;
  316. }
  317. return $this->my_display($value, $options);
  318. }
  319. /// mise en forme des valeurs (selon options)
  320. /// a partir des raw values, formatte le texte pour l'oid associé
  321. function formatItems(&$value,&$rs, $myliste, $sourcemodule=NULL) {
  322. // est ce que l'on doit ajouter les groupes de champs
  323. // la liste est groupée sur le premier champ du lien
  324. if ($this->grouplist) {
  325. if (count($myliste) <= 1)
  326. $this->groupliste == false;
  327. else {
  328. $fields = array_keys($myliste);
  329. $groupField = $fields[0];
  330. $groupListe[$groupField] = array_shift($myliste);
  331. }
  332. }
  333. $items = array();
  334. // ???
  335. $opts=array('_published'=>'all');
  336. $i=0;
  337. while($rs && $ors=$rs->fetch()) {
  338. $i++;
  339. $koid=$ors['KOID'];
  340. if(isset($sourcemodule) && $sourcemodule->object_sec && !$sourcemodule->secure($koid,':ro')) continue;
  341. if ($this->grouplist && $currentGroup != $ors[$groupField]) {
  342. $currentGroup = $ors[$groupField];
  343. $groupLabel = $this->format_display($groupListe,$ors,$opts,null,'text');
  344. $items[] = array('koid'=>NULL, 'label'=>$grouplabel, 'type'=>'group');
  345. $i++;
  346. }
  347. $display=$this->format_display($myliste,$ors,$opts,null,'text');
  348. $item = array('koid'=>$koid, 'label'=>$display, 'type'=>'item', 'selected'=>false);
  349. if((is_array($value) && isset($value[$koid])) || ($koid==$value))
  350. $item['selected']=true;
  351. $items[] = $item;
  352. }
  353. return $items;
  354. }
  355. /// construit la requete de chargement des valeurs
  356. /// paramètres optionnels : target_fields, filter, _published
  357. function getRawValues(&$value, &$options){
  358. $p=new XParam($options,array());
  359. $lang_data=XShell::getLangData();
  360. $queryfilter = NULL;
  361. $queryorder = NULL;
  362. // cas ou il y a une requete qui donne l'ensemble des valeurs
  363. if(!empty($this->query)) {
  364. preg_match('/^SELECT (.+) FROM .+( WHERE (.*))?( ORDER BY .*)?$/Ui', $this->query, $matches);
  365. if(!isset($options['target_fields']) && $matches[1]!='*') $options['target_fields'] = explode(',', $matches[1]);
  366. $queryfilter=$matches[3];
  367. $queryorder=$matches[4];
  368. }
  369. // liste des champs à lire
  370. list($myliste,$my_flist,$first)=$this->getFieldList($options);
  371. // Construction de la requete
  372. $dstarget = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->target);
  373. if (!$dstarget->isTranslatable())
  374. $lang_data=TZR_DEFAULT_LANG;
  375. if(!empty($options['filter'])) $filter='('.$options['filter'].')';
  376. else $filter=$this->filter;
  377. if(!empty($queryfilter)) {
  378. if(!empty($filter)) $filter.=' AND ';
  379. $filter.=$queryfilter;
  380. }
  381. if($dstarget->publishedMode($p) == 'public'){
  382. if(!empty($filter)) $filter .= ' AND ';
  383. $filter .= ' PUBLISH = 1 ';
  384. }
  385. if(!empty($filter)) $filter.=' AND ';
  386. $maxrecords=max($this->checkbox_limit, $this->autocomplete_limit)+1;
  387. $rs2=selectQuery('SELECT DISTINCT '.$my_flist.' FROM '.$this->target.' WHERE '.$filter.' LANG="'.$lang_data.'"'.
  388. ($queryorder?$queryorder:($first?' ORDER BY '.$first:'')).' LIMIT '.$maxrecords);
  389. return $rs2;
  390. }
  391. /// Un champ de type Lien n'est en edit que sur la langue par defaut.
  392. function my_edit(&$value,&$options) {
  393. /* controles affichage des valeurs possibles */
  394. if($this->target==TZR_DEFAULT_TARGET){
  395. return $this->my_display($value,$options);
  396. }
  397. $sourcemodule = NULL;
  398. if($this->sourcemodule){
  399. $sourcemodule=XModule::objectFactory($this->sourcemodule);
  400. if($sourcemodule->object_sec && !$sourcemodule->secure('',':list') || !$sourcemodule->object_sec && !$sourcemodule->secure('',':ro')) return;
  401. }
  402. // valeur en retour
  403. $r=$this->_newXFieldVal($options);
  404. $r->raw=$value;
  405. if(!XDataSource::sourceExists($this->target)) {
  406. $r->html='';
  407. return $r;
  408. }
  409. $format=@$options['fmt'];
  410. // Noms des champs de formulaire
  411. if(isset($options['intable'])) {
  412. $o=$options['intable'];
  413. $fname=$this->field.'['.$o.']';
  414. $hiddenname=$this->field.'_HID['.$o.']';
  415. } elseif(!empty($options['fieldname'])) {
  416. $fname=$options['fieldname'];
  417. $hiddenname=$options['fieldname'].'_HID';
  418. } else {
  419. $fname=$this->field;
  420. $hiddenname=$this->field.'_HID';
  421. }
  422. // Liste des champs de la cible
  423. if(isset($options['display_format'])){
  424. $olddisplayformat=$this->display_format;
  425. $this->display_format=$options['display_format'];
  426. }
  427. list($myliste,$my_flist,$first)=$this->getFieldList($options);
  428. //
  429. $rs = $this->getRawValues($value, $options);
  430. // html du champ selon format de saisie
  431. $nb=($rs?$rs->rowCount():0);
  432. // dans cette version, on ne génère que des selects
  433. $this->checkbox_limit = 0;
  434. $this->autocomplete_limit = 99999;
  435. $this->doublebox = false;
  436. $checkbox=($nb<=$this->checkbox_limit || $format=='checkbox') && $format!='listbox' && $this->checkbox && empty($options['simple']);
  437. $autocomplete=($nb>=$this->autocomplete_limit && $this->autocomplete);
  438. $doublebox=($this->multivalued && $this->doublebox && empty($options['simple']));
  439. if($checkbox)$this->getCheckboxes($value,$options,$r,$rs,$fname,$hiddenname,$myliste);
  440. elseif($autocomplete) $this->getAutocomplete($value,$options,$r,$rs,$fname,$hiddenname,$myliste);
  441. elseif($doublebox) $this->getDoubleSelect($value,$options,$r,$rs,$fname,$hiddenname,$myliste);
  442. else $this->getSelect($value,$options,$r,$rs,$fname,$hiddenname,$myliste, $sourcemodule);
  443. if($olddisplayformat) $this->display_format=$olddisplayformat;
  444. return $r;
  445. }
  446. // Edition du champ sous la forme d'une liste déroulante
  447. function getSelect(&$value,&$options,&$r,&$rs,$fname,$hiddenname,$myliste, $sourcemodule) {
  448. $qf=@$options['query_format'];
  449. $items = $this->formatItems($value, $rs, $myliste, $sourcemodule);
  450. $r->html = '';
  451. $i = 0;
  452. // on transforme en options et on ajoute le select ... plus le reste
  453. foreach($items as $item){
  454. $i++;
  455. if ($item['type'] == 'group')
  456. $r->html .= '<optgroup label="'.$item['label'].'">';
  457. else{
  458. $r->html.='<option value="'.$item['koid'].'"'.($item['selected']?' selected' :'').'>'.$item['label'].'</option>';
  459. $r->collection = $item['label'];
  460. $r->oidcollection = $item['koid'];
  461. if ($item['selected']){
  462. $r->text = $item['label'];
  463. }
  464. }
  465. }
  466. if($qf){
  467. // cas des recherches ?
  468. $labelin=@$options['labelin'];
  469. $format=@$options['fmt'];
  470. if(empty($format)) $format=@$options['qfmt'];
  471. if(empty($format)) $format=$this->query_format;
  472. if(empty($labelin)) $first='<option value="">----</option>';
  473. elseif(empty($first) || $format=='listbox') $first='<option value="">'.$this->label.'</option>';
  474. else{
  475. $first.='<option value="">'.XLabels::getSysLabel('xfielddef','n/a').'</option>';
  476. $r->html=str_replace('" selected>','">',$r->html);
  477. }
  478. $i++;
  479. if($i<2 || $format=='listbox-one') $r->html='<select name="'.$fname.'" id="'.$fname.'">'.$first.$r->html.'</select>';
  480. else $r->html='<select name="'.$fname.'[]" id="'.$fname.'" size="'.min($i,$this->boxsize).'" multiple>'.$first.$r->html.'</select>';
  481. }else{
  482. // cas std
  483. //$r->html = ''; empêche l'édition par lot de fonctionner ??
  484. $r->varid=XShell::uniqId().$this->table.$this->field;
  485. if(!$this->compulsory || !$this->usedefault) {
  486. $r->html='<option value="">----</option>'.$r->html;
  487. $i++;
  488. }
  489. if($this->multivalued) $cplt='name="'.$fname.'[]" size="'.min($i,$this->boxsize).'" multiple';
  490. else $cplt='name="'.$fname.'"';
  491. $cplt .= ' data-value="'.(is_array($value)?implode('||', array_keys($value)):$value).'" ';
  492. $r->html='<select '.$cplt.' id="'.$r->varid.'" onblur="TZR.isIdValid(\''.$r->varid.'\');">'.$r->html.'</select>';
  493. if($this->compulsory) {
  494. $r->html.='<script type="text/javascript">TZR.addValidator(["'.$r->varid.'","compselect","'.addslashes($this->label).'","'.XIni::get('error_color').'",'.'"XLinkDef"]);</script>';
  495. }
  496. $url=TZR_AJAX8.'?class=xlink2def&function=xlink2def_getValues&_silent=1';
  497. XLogs::notice(get_class($this), "::(getLinked) recherche des champs liens pour {$this->field}");
  498. // recherche des paramètres des champs liens (dans cette version : un seul)
  499. $linkedfields = $this->getLinkedfields();
  500. if (!empty($linkedfields)){
  501. $uniqid = XShell::uniqId();
  502. $revs = array();
  503. foreach($linkedfields as &$linkedfield){
  504. $linkedfield->fmoid = $options['fmoid'];
  505. $linkedfield->url = $url;
  506. $linkedfield->uniqid = $uniqid;
  507. $linkedfield->varid = $uniqid.$this->table.$linkedfield->field;
  508. $linkedfield->table = $this->table;
  509. XLogs::notice(get_class($this), "(getLinked) {$this->field} <= {$linkedfield->ofield->field}");
  510. $revs[] = (object)array('ofield'=>$linkedfield->ofield, 'linkedfields'=>$linkedfield->ofield->getLinkedFields($this->field));
  511. unset($linkedfield->ofield);
  512. }
  513. $linkedfields = json_encode($linkedfields);
  514. $linkdesc = '{field:"'.$fname.'", fmoid:'.$options['fmoid'].', url:"'.$url.'", uniqid:"'.$uniqid.'", varid:"'.$r->varid.'", table:"'.$this->table.'"}, '.$linkedfields.'';
  515. $r->html.='<script type="text/javascript">TZR.linkedfields.add('.$linkdesc.');</script>';
  516. // pour chaque champs lié ajout recherche et ajout de la "reciproque"
  517. $linkedfields2 = array();
  518. foreach($revs as $rev){
  519. $ofield = $rev->ofield;
  520. $ofield->varid = $uniqid.$this->table.$ofield->field;
  521. $linkedfield2 = $rev->linkedfields[0];
  522. $linkedfield2->fmoid = $options['fmoid'];
  523. $linkedfield2->url = $url;
  524. $linkedfield2->uniqid = $uniqid; // verifier ne sert pas ...
  525. $linkedfield2->varid = $uniqid.$this->table.$linkedfield2->field;
  526. $linkedfield2->table = $this->table;
  527. unset($linkedfield2->ofield);
  528. $linkedfields2[] = $linkedfield2;
  529. $linkedfields2 = json_encode($linkedfields2);
  530. $linkdesc2 = '{field:"'.$ofield->field.'", fmoid:'.$options['fmoid'].', url:"'.$url.'", uniqid:"'.$uniqid.'", varid:"'.$ofield->varid.'", table:"'.$this->table.'"}, '.$linkedfields2.'';
  531. // echo("<br>{$this->field} => {$linkedfield2->field} $linkdesc2 ");
  532. $r->html.='<script type="text/javascript">TZR.linkedfields.add('.$linkdesc2.');</script>';
  533. }
  534. }
  535. }
  536. }
  537. /// récuperation des paramètres sur les champs liés
  538. function getLinkedfields($linkedfield=NULL){
  539. $linkedfields = array();
  540. if ($linkedfield == NULL)
  541. $linkedfield = $this->linkedfields1;
  542. $myds = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->table);
  543. if (empty($linkedfield) || !$myds->fieldExists($linkedfield))
  544. return array();
  545. $fd = $myds->desc[$linkedfield];
  546. $linkdesc = self::getLinkedFieldDesc($fd, $this->target);
  547. if ($linkdesc != NULL)
  548. $linkedfields[] = (object)array('ofield'=>$fd,'field'=>$fd->field, 'query'=>(object)array('queryfield'=>$linkdesc->queryfield));
  549. else{
  550. $linkdesc = self::getLinkedFieldDesc($this, $fd->target);
  551. if ($linkdesc == NULL)
  552. return array();
  553. else
  554. $linkedfields[] = (object)array('ofield'=>$fd, 'field'=>$fd->field, 'query'=>(object)array('table'=>$linkdesc->target, 'queryfield'=>$linkdesc->queryfield));
  555. }
  556. return $linkedfields;
  557. }
  558. ///
  559. protected static function getLinkedFieldDesc($fd, $target){
  560. $linkdesc = NULL;
  561. if (!empty($fd->target)){
  562. $ds = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$fd->target);
  563. $links = $ds->getFieldsList(XFieldDef::getObjectLinkTypes());
  564. foreach($links as $fn){
  565. if ($ds->desc[$fn]->target == $target){
  566. return(object)array('field'=>$fd->field, 'target'=>$fd->target, 'queryfield'=>$fn, 'fieldobject'=>$fd);
  567. }
  568. }
  569. }
  570. return NULL;
  571. }
  572. /// Recherche
  573. function my_query($value,$options=NULL) {
  574. $format=@$options['fmt'];
  575. if(empty($format)) $format=@$options['qfmt'];
  576. if(empty($format)) $format=$this->query_format;
  577. $searchmode=@$options['searchmode'];
  578. $fname=(isset($options['fieldname'])?$options['fieldname']:$this->field);
  579. $hiddenname=$fname.'_HID';
  580. $r=$this->_newXFieldVal($options,true);
  581. $r->raw=$value;
  582. if($this->target==TZR_DEFAULT_TARGET) {
  583. $r->html.='<input name="'.$fname.'" size="30" type="text" value="'.$value.'">';
  584. return $r;
  585. }
  586. // Liste des champs de la cible
  587. if($options['display_format']){
  588. $olddisplayformat=$this->display_format;
  589. $this->display_format=$options['display_format'];
  590. }
  591. list($myliste,$my_flist,$first)=$this->getFieldList($options);
  592. $options['query_format']=1;
  593. if($format=='autocomplete'){
  594. $this->getAutocomplete($value,$options,$r,$rs,$fname,$hiddenname,$myliste);
  595. return $r;
  596. }
  597. // Construction de la requete
  598. $filter=array();
  599. if(!empty($options['filter'])) $filter[]='('.$options['filter'].')';
  600. elseif(!empty($this->filter)) $filter[]='('.$this->filter.')';
  601. if(!empty($this->query)) {
  602. $inclause=array();
  603. $rs=selectQuery($this->query);
  604. while($rs && ($ors=$rs->fetch())) $inclause[]="'".$ors['KOID']."'";
  605. $filter[]='(KOID IN ('.implode(',',$inclause).'))';
  606. }
  607. if($searchmode=='simple') {
  608. $allvalues=array();
  609. $selectquery=@$options['select'];
  610. if(!empty($selectquery)) $allvalues=$this->_getUsedValues(NULL,$selectquery);
  611. else $allvalues=$this->_getUsedValues("LANG='".TZR_DEFAULT_LANG."'");
  612. $filter[]='(KOID IN ("'.implode('","',array_keys($allvalues)).'"))';
  613. }
  614. if(!empty($filter)) $filter=implode(' AND ',$filter).' AND ';
  615. else $filter='';
  616. $rs2=cacheSelectQuery("select distinct $my_flist from ".$this->target." where $filter LANG='".TZR_DEFAULT_LANG."'".
  617. ' '.($first ? "order by $first":""));
  618. // Format de la saisie
  619. if($rs2) $nb=$rs2->rowCount();
  620. if ($nb >= $this->autocomplete_limit && $this->autocomplete && !$this->multivalue) {
  621. $this->getAutocomplete($value,$options,$r,$rs2,$fname,$hiddenname,$myliste);
  622. return $r;
  623. }
  624. $checkbox=(($nb<=$this->checkbox_limit || $format=='checkbox') && $format!='listbox' && $format!='listbox-one' && $this->checkbox);
  625. if($this->get_multivalued() && $format!='listbox-one'){
  626. $varid=$r->varid;
  627. $op=$options['op'];
  628. $medit='<input class="radio" type="radio" name="'.$fname.'_op" value="AND" id="'.$varid.'-AND" checked>'.
  629. '<label for="'.$varid.'-AND">'.XLabels::getSysLabel('xfielddef.xlinkdef_allterms').'</label>&nbsp;&nbsp;'.
  630. '<input class="radio" type="radio" name="'.$fname.'_op" value="OR" id="'.$varid.'-OR"'.($op=='OR'?' checked':'').'>'.
  631. '<label for="'.$varid.'-OR">'.XLabels::getSysLabel('xfielddef.xlinkdef_leastaterm').'</label><br>';
  632. }else{
  633. $medit='';
  634. }
  635. if($checkbox) $this->getCheckboxes($value,$options,$r,$rs2,$fname,$hiddenname,$myliste);
  636. else $this->getSelect($value,$options,$r,$rs2,$fname,$hiddenname,$myliste);
  637. $r->html=$medit.$r->html;
  638. if($olddisplayformat) $this->display_format=$olddisplayformat;
  639. return $r;
  640. }
  641. function my_quickquery($value,$options=NULL) {
  642. $oldc=$this->checkbox;
  643. $oldd=$this->doublebox;
  644. $olda=$this->autocomplete;
  645. $this->checkbox=false;
  646. $this->doublebox=false;
  647. $this->autocomplete=true;
  648. $ret=$this->query($value, $options);
  649. $ret->html.='<input type="hidden" value="'.$this->field.'" name="_FIELDS['.$this->field.']">';
  650. $this->checkbox=$oldc;
  651. $this->doublebox=$oldd;
  652. $this->autocomplete=$olda;
  653. return $ret;
  654. }
  655. function post_edit($value,$options,&$computed_fields=NULL){
  656. $r=$this->_newXFieldVal($options);
  657. $oid=$options['oid'];
  658. $ischeckbox=(@$options[$this->field.'_HID']=='checkbox')||(@$options[$this->field.'_FMT']=='checkbox');
  659. if($ischeckbox) {
  660. $nvalue=array();
  661. // Attention éviter les liens vers lui-même
  662. foreach($value as $soid => $set) {
  663. if($soid!='Foo' && $soid!=$oid) $nvalue[]=$soid;
  664. }
  665. $value=$nvalue;
  666. }else{
  667. if(is_array($value)){
  668. foreach($value as $i=>$foo){
  669. if(empty($foo)) unset($value[$i]);
  670. }
  671. }
  672. }
  673. if(!empty($this->exif_source) && empty($value)){
  674. $value=array();
  675. $meta=$this->getMetaValue($computed_fields,array('IPTC','EXIF','XMP'),true);
  676. if(!is_array($meta->raw)) $meta->raw=array($meta->raw);
  677. $opt=array('srcField'=>$this->flabel);
  678. if($this->isAutorizedToAdd($options)) $opt['create']=true;
  679. foreach($meta->raw as $i=>$v){
  680. if(!is_string($v)) continue;
  681. $ret=$this->my_import($v,$opt);
  682. $value[]=$ret['value'][0];
  683. }
  684. }
  685. if($value==$oid) $value=NULL;
  686. $r->raw=$value;
  687. // Edition par lot sur champ multivalué
  688. if(!empty($options['editbatch']) && $this->multivalued){
  689. $p=new XParam($ar,NULL);
  690. $op=$p->get($this->field.'_op');
  691. $old=explode('||',$options['old']->raw);
  692. if($op=='+') $r->raw=array_unique(array_merge($r->raw,$old));
  693. elseif($op=='-') $r->raw=array_diff($old,$r->raw);
  694. }
  695. // Trace
  696. $old=@$options['old'];
  697. if(!empty($old)){
  698. if(is_array($r->raw)) $v=implode('||',$r->raw);
  699. else $v=$r->raw;
  700. $r1=&$this->display($v,$options);
  701. if($r1->html!=$old->html) $this->trace($options['old'],$r, '['.$old->html.'] -> ['.$r1->html.']');
  702. }
  703. return $r;
  704. }
  705. /// Autorise l'ajout d'une entrée à la volée
  706. public function isAutorizedToAdd(&$options){
  707. if($this->sourcemodule){
  708. if(empty($this->cache->modules[$this->sourcemodule])){
  709. $this->cache->modules[$this->sourcemodule]=XModule::objectFactory($this->sourcemodule);
  710. }
  711. return $this->cache->modules[$this->sourcemodule]->secure('',':rw');
  712. }elseif(!empty($options['fmoid'])){
  713. if(empty($this->cache->modules[$options['fmoid']])){
  714. $this->cache->modules[$options['fmoid']]=XModule::objectFactory($options['fmoid']);
  715. }
  716. return $this->cache->modules[$options['fmoid']]->secure($options['oid'],':rwv');
  717. }
  718. return false;
  719. }
  720. function post_query(&$o,$options=NULL) {
  721. $p=new XParam($options,array());
  722. $ischeckbox=($o->hid=='checkbox') || ($o->fmt=='checkbox');
  723. if($ischeckbox && is_array($o->value)) {
  724. $nvalue=array();
  725. foreach($o->value as $soid => $set) {
  726. $nvalue[]=$soid;
  727. }
  728. $o->value=$nvalue;
  729. }
  730. return parent::post_query($o,$options);
  731. }
  732. function search($value,$options=NULL){
  733. if($this->target!='%'){
  734. if(!is_array($value)) $value=array($value);
  735. $cond=array();
  736. $x=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->target);
  737. if(!empty($options['target_fields'])) $pub=$options['target_fields'];
  738. else $pub=$x->getPublished(false);
  739. foreach($value as $v) $cond[]='concat('.implode('," ",',$pub).') like "%'.addslashes($v).'%"';
  740. if(!empty($cond)) return $this->field.' in (select KOID from '.$this->target.' where '.implode($cond,' or ').')';
  741. else return '';
  742. }
  743. }
  744. function getNbPublishedFields(){
  745. if(!XShell::admini_mode()) return 99;
  746. if($this->target=='%' || empty($this->target)) return 2;
  747. if(strpos($this->display_format,'%')!==false) return 99;
  748. if(empty($this->published_fields_in_admin)){
  749. $tablexset=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->target);
  750. $this->published_fields_in_admin=$tablexset->published_fields_in_admin;
  751. }
  752. return $this->published_fields_in_admin;
  753. }
  754. /// Formate l'affichage d'un lien
  755. function format_display(&$myliste,&$ors,&$opt,$nbpublishedfields=NULL,$prop='html'){
  756. reset($myliste);
  757. $display='';
  758. $htmls=array();
  759. $replace=false;
  760. if(!empty($this->display_format) && strpos($this->display_format,'%_')!==false){
  761. $replace=true;
  762. $display=$this->display_format;
  763. }
  764. foreach($myliste as $k=>$f){
  765. $o=$f->display($ors[$k],$opt);
  766. $t=$o->$prop;
  767. if($replace) $display=str_replace('%_'.$k,$t,$display);
  768. else $htmls[]=$t;
  769. }
  770. if(!$replace){
  771. if(!empty($this->display_format)) $display=@vsprintf($this->display_format,array_pad($htmls,substr_count($this->display_format,'%'),''));
  772. else $display=implode(' ',$htmls);
  773. }
  774. return $display;
  775. }
  776. /// Ecriture dans un fichier excel
  777. function writeXLS(&$xl,$i,$j,&$value,$format=0,&$ss=NULL) {
  778. $t=str_replace('&nbsp;', ' ', $value->toText());
  779. $t=preg_replace('/\[.*\]/', '', $t);
  780. convert_charset($t,TZR_INTERNAL_CHARSET,'UTF-8');
  781. $xl->setCellValueByColumnAndRow($j,$i,$t);
  782. if(is_array($format)) $xl->getStyleByColumnAndRow($j,$i)->applyFromArray($format);
  783. }
  784. /// Sous fonction pour l'import de données vers une table
  785. /// Options : srcField (string) => champ à utiliser dans la table cible pour creer le lien (si vide la valeur doit etre un oid)
  786. /// create (true/false) => creation automatique des fiches cible non existante (false par defaut)
  787. /// separator (string) => séparateur pour des valeurs multiples (| par defaut)
  788. /// forcekoid (true/false) => force la génération de l'oid à partir de la valeur (false par defaut)
  789. function my_import($value,&$options){
  790. $separator=(string)$options['separator'];
  791. if(empty($separator)) $separator='|';
  792. $create=(string)$options['create'];
  793. $forcekoid=(string)$options['forcekoid'];
  794. $srcField=(string)$options['srcField'];
  795. $message='';
  796. if($value!=''){
  797. if(empty($srcField) && !Kernel::isAMultipleKoid($value)){
  798. $ors=selectQueryGetOne('select FIELD from DICT where DTAB="'.$this->target.'" and PUBLISHED=1 order by forder limit 1');
  799. @$srcField=$ors['FIELD'];
  800. }
  801. if($srcField){
  802. $ret=array();
  803. cp1252_replace($value);
  804. $valueslist=explode($separator,$value);
  805. $ret=array();
  806. foreach($valueslist as $v){
  807. $v=trim($v);
  808. if($v!=''){
  809. $filter=$this->filter;
  810. if(!empty($options['filter'])) $filter='('.$options['filter'].')';
  811. if(!empty($filter)) $filter.=' AND ';
  812. $rs=selectQuery('SELECT KOID FROM '.$this->target.' WHERE '.$filter.' UPPER('.$srcField.')="'.strtoupper(addslashes($v)).'"');
  813. if($rs && $ors=$rs->fetch()){
  814. $ret[]=$ors['KOID'];
  815. }else{ // la target n'existe pas
  816. if(!empty($create) && $create!='false'){
  817. $toinsert=array();
  818. if(!empty($forcekoid) && $forcekoid!='false'){
  819. $toinsert['newoid']=$this->target.':'.strtoupper(preg_replace('/([^a-z0-9]+)/','',rewriteToAscii($v)));
  820. }
  821. $xset=&XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$this->target);
  822. $toinsert['tplentry']=TZR_RETURN_DATA;
  823. $toinsert['PUBLISH']=1;
  824. $toinsert[$srcField]=$v;
  825. $mess=$xset->procInput($toinsert);
  826. $message.=$this->field.' : "'.$v.'" created<br/>';
  827. $ret[]=$mess['oid'];
  828. }else{
  829. $message.='<u>Warning</u> : '.$this->field.' : "'.$v.'" doesn\'t exist<br/>';
  830. }
  831. }
  832. }
  833. }
  834. }else{
  835. $ret=$value;
  836. }
  837. }
  838. return array('message'=>$message,'value'=>$ret);
  839. }
  840. /// creation d'un index si c'est un champ mono value
  841. function chk(&$msg) {
  842. parent::chk($msg);
  843. if(!$this->get_multivalued()) {
  844. // ajout d'un index sur les champs non multivalues
  845. if (!countSelectQuery('SHOW INDEX FROM '.$this->table.' where Column_name="'.$this->field.'"')) {
  846. updateQuery('ALTER TABLE '.$this->table.' ADD INDEX '.$this->field.'('.$this->field.'(40))');
  847. }
  848. // verification que le champ n'inclue pas de ||
  849. $rs=selectQuery('SELECT KOID,LANG,'.$this->field.' FROM '.$this->table.' WHERE '.$this->field.' like "%||%"');
  850. while($rs && ($ors=$rs->fetch())) {
  851. $oid='';
  852. $value=$ors[$this->field];
  853. $values=explode('||',$value);
  854. foreach($values as $value){
  855. if(!empty($value) && Kernel::objectExists($value)){
  856. $oid=$value;
  857. break;
  858. }
  859. }
  860. updateQuery('UPDATE '.$this->table.' SET UPD=UPD,'.$this->field.'="'.$oid.'" WHERE KOID="'.$ors['KOID'].'" AND LANG="'.$ors['LANG'].'"');
  861. }
  862. $rs->closeCursor();
  863. }
  864. return true;
  865. }
  866. // Edition du champ sous la forme d'une double liste déroulante
  867. function getDoubleSelect(&$value,&$options,&$r,&$rs,$fname,$hiddenname,$myliste){
  868. if($this->sourcemodule){
  869. $mod=XModule::objectFactory($this->sourcemodule);
  870. if($mod->object_sec && !$mod->secure('',':list') || !$mod->object_sec && !$mod->secure('',':ro')) return;
  871. }
  872. $oidcollection=$collection=$opts=array();
  873. $varid=getUniqID('v');
  874. $unselectedname=preg_replace('/^([^\[]+)/','$1_unselected',$fname);
  875. $edit1='<select name="'.$unselectedname.'" size="'.$this->boxsize.'" multiple ondblclick="TZR.doubleAdd('.
  876. 'this.form.elements[\''.$unselectedname.'\'],this.form.elements[\''.$fname.'[]\'],true)" class="doublebox">';
  877. $edit2='<select name="'.$fname.'[]" size="'.$this->boxsize.'" multiple id="'.$varid.'" ondblclick="TZR.doubleAdd(this.form.elements[\''.$fname.'[]\'],'.
  878. 'this.form.elements[\''.$unselectedname.'\'],true)" class="doublebox">';
  879. $order = 0;
  880. if ($this->grouplist) { // la liste est groupée sur le premier champ du lien
  881. if (count($myliste) <= 1)
  882. $this->groupliste == false;
  883. else {
  884. $fields = array_keys($myliste);
  885. $groupField = $fields[0];
  886. $groupListe[$groupField] = array_shift($myliste);
  887. $groupid = 0;
  888. }
  889. }
  890. while($ors=$rs->fetch()) {
  891. $order++;
  892. $koid=$ors['KOID'];
  893. if($mod && $mod->object_sec && !$mod->secure($koid,':ro')) continue;
  894. $selected=isset($value[$koid]);
  895. if ($this->grouplist && $currentGroup != $ors[$groupField]) {
  896. $currentGroup = $ors[$groupField];
  897. $groupid++;
  898. $groupLabel = $this->format_display($groupListe,$ors,$opts,null,'text');
  899. $edit1 .= '<optgroup label="'.$groupLabel.'" id="unselected_'.$fname.'_'.$groupid.'">';
  900. $edit2 .= '<optgroup label="'.$groupLabel.'" id="'.$fname.'_'.$groupid.'">';
  901. }
  902. $display=$this->format_display($myliste,$ors,$opts,null,'text');
  903. if(!$selected) $edit1.='<option value="'.$koid.'" order="'.$order.'">'.$display.'</option>';
  904. else $edit2.='<option value="'.$koid.'" order="'.$order.'">'.$display.'</option>';
  905. if($selected) $r->text.=$display;
  906. $oidcollection[]=$koid;
  907. $collection[]=$display;
  908. }
  909. $edit1.='</select>';
  910. $edit2.='</select>';
  911. $buttons='<input type="button" value=">>" onclick="TZR.doubleAdd(this.form.elements[\''.$unselectedname.'\'],'.
  912. 'this.form.elements[\''.$fname.'[]\'],true)"><br/>'.
  913. '<input type="button" value="<<" onclick="TZR.doubleAdd(this.form.elements[\''.$fname.'[]\'],'.
  914. 'this.form.elements[\''.$unselectedname.'\'],true)">';
  915. $hidd='<input type="hidden" name="'.$hiddenname.'" value="doublebox"/>';
  916. $color=XIni::get('error_color');
  917. if($this->compulsory) $t1="TZR.addValidator(['$varid',/(.+)/,'".addslashes($this->label)."','$color','XLinkDef']);";
  918. else $t1="TZR.addValidator(['$varid','','".addslashes($this->label)."','$color','XLinkDef']);";
  919. $js="<script type=\"text/javascript\">if(typeof(TZR)!='undefined') { $t1 }</script>";
  920. $edit='<table class="doublebox"><tr><td>'.$edit1.'</td><td class="button">'.$buttons.$hidd.'</td><td>'.$edit2.'</td></tr></table>'.$js;
  921. $r->oidcollection=$oidcollection;
  922. $r->collection=$collection;
  923. $r->html=$edit;
  924. }
  925. /// Edition du champ sous la forme de boite à cocher (checkbox/radio)
  926. function getCheckboxes(&$value,&$options,&$r,&$rs,$fname,$hiddenname,$myliste){
  927. if($this->sourcemodule){
  928. $mod=XModule::objectFactory($this->sourcemodule);
  929. if($mod->object_sec && !$mod->secure('',':list') || !$mod->object_sec && !$mod->secure('',':ro')) return;
  930. }
  931. $qf=@$options['query_format'];
  932. if($this->multivalued || ($qf==1)) $typebox='checkbox';
  933. else $typebox='radio';
  934. $my_compulsory=($this->compulsory || $options['compulsory']) && !$qf;
  935. $cols=0;
  936. $edit='<input type="hidden" name="'.$hiddenname.'" value="'.$typebox.'"/>';
  937. $edit.='<table class="tzr-checkboxtable">';
  938. $edit.='<tr>';
  939. if($typebox!='radio') $edit.='<input type="hidden" name="'.$fname.'[0]" value="Foo"/>';
  940. if(!$my_compulsory && ($typebox=='radio')) {
  941. $varid=getUniqID('v');
  942. $edit.='<td><input type="'.$typebox.'" class="checkbox" name="'.$fname.'" value="" id="'.$varid.'"/>'.
  943. '<label for="'.$varid.'">'.XLabels::getSysLabel('general','empty_menu').'</label></td>';
  944. $cols++;
  945. }
  946. $listvarid=array();
  947. $opts=array('_published'=>'all');
  948. if ($this->grouplist) { // la liste est groupée sur le premier champ du lien
  949. if (count($myliste) <= 1)
  950. $this->groupliste == false;
  951. else {
  952. $fields = array_keys($myliste);
  953. $groupField = $fields[0];
  954. $groupListe[$groupField] = array_shift($myliste);
  955. }
  956. }
  957. if($cols>=$this->checkbox_cols) {
  958. $edit.='</tr><tr>';
  959. $cols=0;
  960. }
  961. while($ors=$rs->fetch()) {
  962. $koid=$ors['KOID'];
  963. if($mod && $mod->object_sec && !$mod->secure($koid,':ro')) continue;
  964. if ($this->grouplist && $currentGroup != $ors[$groupField]) {
  965. $currentGroup = $ors[$groupField];
  966. $edit .= '</td></tr><tr><td colspan="'.$this->checkbox_cols.'">';
  967. $edit .= $this->format_display($groupListe,$ors,$opts,null,'html');
  968. $edit .= '</td></tr><tr>';
  969. $cols=0;
  970. }
  971. $edit.='<td>';
  972. $koid=$ors['KOID'];
  973. $varid=uniqid('v');
  974. $listvarid[]=$varid;
  975. $display=$this->format_display($myliste,$ors,$opts);
  976. if($this->multivalued || ($qf==1)){
  977. $checked=isset($value[$koid]);
  978. }elseif($my_compulsory && empty($value) && $this->usedefault) {
  979. $checked=true;
  980. $value=$koid;
  981. }else{
  982. $checked=($koid==$value);
  983. }
  984. if($typebox=='checkbox')
  985. $edit.='<input type="checkbox" class="radio" id="'.$varid.'" name="'.$fname.'['.$koid.']" '.($checked?' checked ':'').
  986. '/> <label for="'.$varid.'">'.$display.'</label></td>';
  987. else
  988. $edit.='<input type="radio" class="radio" id="'.$varid.'" name="'.$fname.'" value="'.$koid.'" '.
  989. ($checked?' checked ':'').'/> <label for="'.$varid.'">'.$display.'</label></td>';
  990. $cols++;
  991. if($checked) $r->text.=$display;
  992. if($cols>=$this->checkbox_cols) {
  993. $edit.='</tr><tr>';
  994. $cols=0;
  995. }
  996. $oidcollection[]=$koid;
  997. $collection[]=$display;
  998. }
  999. $edit.='</tr></table>';
  1000. if(!empty($my_compulsory) && !empty($listvarid)) {
  1001. $color=XIni::get('error_color');
  1002. $edit.="<script type=\"text/javascript\">if(typeof(TZR)!='undefined') { TZR.addValidator(['".$listvarid[0]."','','".
  1003. addslashes($this->label)."','$color','XLinkDef','',['".implode("','",$listvarid)."']]); }</script>";
  1004. }
  1005. $r->oidcollection=$oidcollection;
  1006. $r->collection=$collection;
  1007. $r->varid=$listvarid[0];
  1008. $r->html=$edit;
  1009. }
  1010. // Edition du champ sous la forme d'une zone d'autocomplétion
  1011. function getAutocomplete(&$value,&$options,&$r,&$rs,$fname,$hiddenname,$myliste){
  1012. if(is_array($value)){
  1013. $v=array_keys($value);
  1014. $v=$v[0];
  1015. }else $v=$value;
  1016. $qf=@$options['query_format'];
  1017. $lang=XShell::getLangUser();
  1018. $lang_data=XShell::getLangData();
  1019. if(isset($options['target_fields'])){
  1020. $fieldslist=implode(',',$options['target_fields']);
  1021. $pubonly=false;
  1022. }else{
  1023. $fieldslist='';
  1024. $pubonly=true;
  1025. }
  1026. if($qf) $varid=$fname.'_id';
  1027. else $varid=getUniqID('v');
  1028. $textid='_INPUT'.$varid;
  1029. $edit=$mborder=$callback=$js=$fmt='';
  1030. if(!$qf && $this->compulsory) {
  1031. $mborder='tzr-input-compulsory';
  1032. if(!$this->multivalued) $fmt=' onblur="TZR.isIdValid(\''.$varid.'\')" ';
  1033. $js='<script type="text/javascript">'.
  1034. 'TZR.addValidator(["'.$varid.'",/.+:.+/,"'.addslashes($this->label).'","'.XIni::get('error_color').'","XLinkDef","'.$textid.'"]);</script>';
  1035. }
  1036. if (XShell::admini_mode() && !$qf && empty($this->filter) && empty($this->query) && !empty($this->sourcemodule) && $this->isAutorizedToAdd($options)){
  1037. $urlnew = $GLOBALS['TZR_SESSION_MANAGER']::admin_url(true,true).'&moid='.$this->sourcemodule.'&function=insert&template=xmodtable/popinsert.html&tplentry=br&tabsmode=1&varid='.$varid;
  1038. $newico = XLabels::getSysLabel('general','new');
  1039. } else {
  1040. $newico = $urlnew = '';
  1041. }
  1042. if(!$qf && $this->multivalued){
  1043. if(is_array($value)) $v=array_keys($value);
  1044. else $v=$value;
  1045. $delico=XLabels::getSysLabel('general','delete');
  1046. $callback=',TZR.autoCompleteMultipleValue';
  1047. $edit.='<input id="'.$varid.'" autocomplete="off" name="foo" value="" type="hidden">';
  1048. $edit.='<input autocomplete="off" id="'.$textid.'" name="_INPUT'.$fname.'" size="30" type="text" '.$fmt.' class="tzr-link '.$mborder.'">';
  1049. if ($urlnew != ''){
  1050. $edit .= '<a href="#" onclick="TZR.openPopup(\''.$urlnew.'\'); return false;">'.$newico.'</a>';
  1051. }
  1052. $edit.='<table id="table'.$varid.'"><tr style="display:none;"><td><a href="#" onclick="TZR.delLine(this);return false;">'.$delico.'</a><input type="hidden" name="'.$fname.'[]" value=""></td><td></td></tr>';
  1053. $r->text='';
  1054. if(!empty($v)){
  1055. if(!is_array($v)) $v=array($v);
  1056. foreach($v as $oid){
  1057. $target=Kernel::getTable($oid);
  1058. if(XSystem::tableExists($target)) {
  1059. $t=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$target);
  1060. $rs2=selectQuery('select * from '.$target.' where KOID="'.$oid.'"');
  1061. $ors2=$rs2->fetch();
  1062. if($ors2) {
  1063. $myopts=array();
  1064. if(!empty($options['_charset'])) $myopts['_charset']=$options['_charset'];
  1065. $display=$this->format_display($myliste,$ors2,$myopts,NULL,'text');
  1066. }
  1067. }
  1068. $display=trim($display);
  1069. $r->text.=$display.' ';
  1070. $edit.='<tr><td><a href="#" onclick="TZR.delLine(this);return false;">'.$delico.'</a><input type="hidden" name="'.$fname.'[]" value="'.$oid.'" '.
  1071. '</td><td>'.$display.'</td></tr>';
  1072. }
  1073. $r->text=substr($r->text,0,-1);
  1074. }
  1075. $edit.='</table>';
  1076. }else{
  1077. $display='';
  1078. if($v){
  1079. $target=Kernel::getTable($v);
  1080. if(XSystem::tableExists($target)) {
  1081. $t=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$target);
  1082. $rs2=selectQuery('select * from '.$target.' where KOID="'.$v.'"');
  1083. $ors2=$rs2->fetch();
  1084. if($ors2) {
  1085. $myopts=array();
  1086. if(!empty($options['_charset'])) $myopts['_charset']=$options['_charset'];
  1087. $display=$this->format_display($myliste,$ors2,$myopts,NULL,'text');
  1088. }
  1089. }
  1090. $display=trim($display);
  1091. }
  1092. $r->text=$display;
  1093. $edit.='<input id="'.$varid.'" autocomplete="off" name="'.$fname.'" value="'.$v.'" type="hidden">';
  1094. $edit.='<input autocomplete="off" id="'.$textid.'" name="_INPUT'.$fname.'" size="30" type="text" value="'.$display.'" '.$fmt.
  1095. ' class="tzr-link '.$mborder.'">';
  1096. if ($urlnew != ''){
  1097. $edit .= '<a href="#" onclick="TZR.openPopup(\''.$urlnew.'\'); return false;">'.$newico.'</a>';
  1098. }
  1099. }
  1100. $url=TZR_AJAX8.'?class=xlink2def&function=xlink2def_autocomplete&_silent=1';
  1101. $edit.='<script type="text/javascript" language="javascript">TZR.addAutoComplete("'.$url.'","'.$varid.'","'.$options['fmoid'].'",'.
  1102. '"'.$this->table.'","'.$this->field.'","'.$fieldslist.'"'.$callback.');</script>'.$js;
  1103. $r->oidcollection=$oidcollection;
  1104. $r->collection=$collection;
  1105. $r->varid=$varid;
  1106. $r->html=$edit;
  1107. }
  1108. /// retourne la liste des champs de la cible à utliser + le premier champ
  1109. function &getFieldList(&$options,$addpublished=true){
  1110. $maxmi=$this->getNbPublishedFields();
  1111. $order='FORDER';
  1112. $sup='';
  1113. $idx='';
  1114. if(strpos($this->display_format,'%_')!==false){
  1115. preg_match_all('/%_([a-z0-9_]+)/i',$this->d

Large files files are truncated, but you can click here to view the full file