extrafields.class.php 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005
  1. <?php
  2. /* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
  4. * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
  5. * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
  6. * Copyright (C) 2009-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  7. * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
  8. * Copyright (C) 2013 Florian Henry <forian.henry@open-concept.pro>
  9. * Copyright (C) 2015 Charles-Fr BENKE <charles.fr@benke.fr>
  10. * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  11. * Copyright (C) 2017 Nicolas ZABOURI <info@inovea-conseil.com>
  12. * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. */
  27. /**
  28. * \file htdocs/core/class/extrafields.class.php
  29. * \ingroup core
  30. * \brief File of class to manage extra fields
  31. */
  32. /**
  33. * Class to manage standard extra fields
  34. */
  35. class ExtraFields
  36. {
  37. /**
  38. * @var DoliDB Database handler.
  39. */
  40. public $db;
  41. // type of element (for what object is the extrafield)
  42. // @deprecated
  43. var $attribute_elementtype;
  44. // Array with type of the extra field
  45. // @deprecated
  46. var $attribute_type;
  47. // Array with label of extra field
  48. // @deprecated
  49. var $attribute_label;
  50. // Array with size of extra field
  51. // @deprecated
  52. var $attribute_size;
  53. // array with list of possible values for some types of extra fields
  54. // @deprecated
  55. var $attribute_choice;
  56. // Array to store compute formula for computed fields
  57. // @deprecated
  58. var $attribute_computed;
  59. // Array to store default value
  60. // @deprecated
  61. var $attribute_default;
  62. // Array to store if attribute is unique or not
  63. // @deprecated
  64. var $attribute_unique;
  65. // Array to store if attribute is required or not
  66. // @deprecated
  67. var $attribute_required;
  68. // Array to store parameters of attribute (used in select type)
  69. // @deprecated
  70. var $attribute_param;
  71. // Array to store position of attribute
  72. // @deprecated
  73. var $attribute_pos;
  74. // Array to store if attribute is editable regardless of the document status
  75. // @deprecated
  76. var $attribute_alwayseditable;
  77. // Array to store permission to check
  78. // @deprecated
  79. var $attribute_perms;
  80. // Array to store language file to translate label of values
  81. // @deprecated
  82. var $attribute_langfile;
  83. // Array to store if field is visible by default on list
  84. // @deprecated
  85. var $attribute_list;
  86. // New array to store extrafields definition
  87. var $attributes;
  88. /**
  89. * @var string Error code (or message)
  90. */
  91. public $error='';
  92. var $errno;
  93. public static $type2label=array(
  94. 'varchar'=>'String',
  95. 'text'=>'TextLong',
  96. 'html'=>'HtmlText',
  97. 'int'=>'Int',
  98. 'double'=>'Float',
  99. 'date'=>'Date',
  100. 'datetime'=>'DateAndTime',
  101. 'boolean'=>'Boolean',
  102. 'price'=>'ExtrafieldPrice',
  103. 'phone'=>'ExtrafieldPhone',
  104. 'mail'=>'ExtrafieldMail',
  105. 'url'=>'ExtrafieldUrl',
  106. 'password' => 'ExtrafieldPassword',
  107. 'select' => 'ExtrafieldSelect',
  108. 'sellist' => 'ExtrafieldSelectList',
  109. 'radio' => 'ExtrafieldRadio',
  110. 'checkbox' => 'ExtrafieldCheckBox',
  111. 'chkbxlst' => 'ExtrafieldCheckBoxFromList',
  112. 'link' => 'ExtrafieldLink',
  113. 'separate' => 'ExtrafieldSeparator',
  114. );
  115. /**
  116. * Constructor
  117. *
  118. * @param DoliDB $db Database handler
  119. */
  120. function __construct($db)
  121. {
  122. $this->db = $db;
  123. $this->error = array();
  124. $this->attributes = array();
  125. // For old usage
  126. $this->attribute_elementtype = array();
  127. $this->attribute_type = array();
  128. $this->attribute_label = array();
  129. $this->attribute_size = array();
  130. $this->attribute_computed = array();
  131. $this->attribute_default = array();
  132. $this->attribute_unique = array();
  133. $this->attribute_required = array();
  134. $this->attribute_perms = array();
  135. $this->attribute_langfile = array();
  136. $this->attribute_list = array();
  137. }
  138. /**
  139. * Add a new extra field parameter
  140. *
  141. * @param string $attrname Code of attribute
  142. * @param string $label label of attribute
  143. * @param int $type Type of attribute ('boolean','int','varchar','text','html','date','datehour','price','phone','mail','password','url','select','checkbox','separate',...)
  144. * @param int $pos Position of attribute
  145. * @param string $size Size/length of attribute
  146. * @param string $elementtype Element type. Same value than object->table_element (Example 'member', 'product', 'thirdparty', ...)
  147. * @param int $unique Is field unique or not
  148. * @param int $required Is field required or not
  149. * @param string $default_value Defaulted value (In database. use the default_value feature for default value on screen. Example: '', '0', 'null', 'avalue')
  150. * @param array|string $param Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
  151. * @param int $alwayseditable Is attribute always editable regardless of the document status
  152. * @param string $perms Permission to check
  153. * @param string $list Visibilty ('0'=never visible, '1'=visible on list+forms, '2'=list only, '3'=form only or 'eval string')
  154. * @param string $help Text with help tooltip
  155. * @param string $computed Computed value
  156. * @param string $entity Entity of extrafields (for multicompany modules)
  157. * @param string $langfile Language file
  158. * @param string $enabled Condition to have the field enabled or not
  159. * @return int <=0 if KO, >0 if OK
  160. */
  161. function addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique=0, $required=0, $default_value='', $param='', $alwayseditable=0, $perms='', $list='-1', $help='', $computed='', $entity='', $langfile='', $enabled='1')
  162. {
  163. if (empty($attrname)) return -1;
  164. if (empty($label)) return -1;
  165. if ($elementtype == 'thirdparty') $elementtype='societe';
  166. if ($elementtype == 'contact') $elementtype='socpeople';
  167. // Create field into database except for separator type which is not stored in database
  168. if ($type != 'separate')
  169. {
  170. $result=$this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed, $help);
  171. }
  172. $err1=$this->errno;
  173. if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate')
  174. {
  175. // Add declaration of field into table
  176. $result2=$this->create_label($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $param, $alwayseditable, $perms, $list, $help, $default_value, $computed, $entity, $langfile, $enabled);
  177. $err2=$this->errno;
  178. if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS'))
  179. {
  180. $this->error='';
  181. $this->errno=0;
  182. return 1;
  183. }
  184. else return -2;
  185. }
  186. else
  187. {
  188. return -1;
  189. }
  190. }
  191. /**
  192. * Add a new optional attribute.
  193. * This is a private method. For public method, use addExtraField.
  194. *
  195. * @param string $attrname code of attribute
  196. * @param int $type Type of attribute ('boolean', 'int', 'varchar', 'text', 'html', 'date', 'datehour','price','phone','mail','password','url','select','checkbox', ...)
  197. * @param string $length Size/length of attribute ('5', '24,8', ...)
  198. * @param string $elementtype Element type ('member', 'product', 'thirdparty', 'contact', ...)
  199. * @param int $unique Is field unique or not
  200. * @param int $required Is field required or not
  201. * @param string $default_value Default value for field (in database)
  202. * @param array $param Params for field (ex for select list : array('options'=>array('value'=>'label of option'))
  203. * @param string $perms Permission
  204. * @param string $list Into list view by default
  205. * @param string $computed Computed value
  206. * @return int <=0 if KO, >0 if OK
  207. */
  208. private function create($attrname, $type='varchar', $length=255, $elementtype='member', $unique=0, $required=0, $default_value='',$param='', $perms='', $list='0', $computed='')
  209. {
  210. if ($elementtype == 'thirdparty') $elementtype='societe';
  211. if ($elementtype == 'contact') $elementtype='socpeople';
  212. $table=$elementtype.'_extrafields';
  213. if ($elementtype == 'categorie') $table='categories_extrafields';
  214. if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/",$attrname) && ! is_numeric($attrname))
  215. {
  216. if ($type=='boolean') {
  217. $typedb='int';
  218. $lengthdb='1';
  219. } elseif($type=='price') {
  220. $typedb='double';
  221. $lengthdb='24,8';
  222. } elseif($type=='phone') {
  223. $typedb='varchar';
  224. $lengthdb='20';
  225. } elseif($type=='mail') {
  226. $typedb='varchar';
  227. $lengthdb='128';
  228. } elseif($type=='url') {
  229. $typedb='varchar';
  230. $lengthdb='255';
  231. } elseif (($type=='select') || ($type=='sellist') || ($type=='radio') ||($type=='checkbox') ||($type=='chkbxlst')){
  232. $typedb='varchar';
  233. $lengthdb='255';
  234. } elseif ($type=='link') {
  235. $typedb='int';
  236. $lengthdb='11';
  237. } elseif ($type=='html') {
  238. $typedb='text';
  239. $lengthdb=$length;
  240. } elseif($type=='password') {
  241. $typedb='varchar';
  242. $lengthdb='128';
  243. } else {
  244. $typedb=$type;
  245. $lengthdb=$length;
  246. if ($type == 'varchar' && empty($lengthdb)) $lengthdb='255';
  247. }
  248. $field_desc = array(
  249. 'type'=>$typedb,
  250. 'value'=>$lengthdb,
  251. 'null'=>($required?'NOT NULL':'NULL'),
  252. 'default' => $default_value
  253. );
  254. $result=$this->db->DDLAddField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
  255. if ($result > 0)
  256. {
  257. if ($unique)
  258. {
  259. $sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
  260. $resql=$this->db->query($sql,1,'dml');
  261. }
  262. return 1;
  263. }
  264. else
  265. {
  266. $this->error=$this->db->lasterror();
  267. $this->errno=$this->db->lasterrno();
  268. return -1;
  269. }
  270. }
  271. else
  272. {
  273. return 0;
  274. }
  275. }
  276. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  277. /**
  278. * Add description of a new optional attribute
  279. *
  280. * @param string $attrname code of attribute
  281. * @param string $label label of attribute
  282. * @param int $type Type of attribute ('int', 'varchar', 'text', 'html', 'date', 'datehour', 'float')
  283. * @param int $pos Position of attribute
  284. * @param string $size Size/length of attribute ('5', '24,8', ...)
  285. * @param string $elementtype Element type ('member', 'product', 'thirdparty', ...)
  286. * @param int $unique Is field unique or not
  287. * @param int $required Is field required or not
  288. * @param array|string $param Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
  289. * @param int $alwayseditable Is attribute always editable regardless of the document status
  290. * @param string $perms Permission to check
  291. * @param string $list Visibily
  292. * @param string $help Help on tooltip
  293. * @param string $default Default value (in database. use the default_value feature for default value on screen).
  294. * @param string $computed Computed value
  295. * @param string $entity Entity of extrafields
  296. * @param string $langfile Language file
  297. * @param string $enabled Condition to have the field enabled or not
  298. * @return int <=0 if KO, >0 if OK
  299. */
  300. private function create_label($attrname, $label='', $type='', $pos=0, $size=0, $elementtype='member', $unique=0, $required=0, $param='', $alwayseditable=0, $perms='', $list='-1', $help='', $default='', $computed='',$entity='', $langfile='', $enabled='1')
  301. {
  302. // phpcs:enable
  303. global $conf,$user;
  304. if ($elementtype == 'thirdparty') $elementtype='societe';
  305. if ($elementtype == 'contact') $elementtype='socpeople';
  306. // Clean parameters
  307. if (empty($pos)) $pos=0;
  308. if (empty($list)) $list='0';
  309. if (empty($required)) $required=0;
  310. if (empty($unique)) $unique=0;
  311. if (empty($alwayseditable)) $alwayseditable=0;
  312. if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname) && ! is_numeric($attrname))
  313. {
  314. if (is_array($param) && count($param) > 0)
  315. {
  316. $params = serialize($param);
  317. }
  318. elseif (strlen($param) > 0)
  319. {
  320. $params = trim($param);
  321. }
  322. else
  323. {
  324. $params='';
  325. }
  326. $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
  327. $sql.= " name,";
  328. $sql.= " label,";
  329. $sql.= " type,";
  330. $sql.= " pos,";
  331. $sql.= " size,";
  332. $sql.= " entity,";
  333. $sql.= " elementtype,";
  334. $sql.= " fieldunique,";
  335. $sql.= " fieldrequired,";
  336. $sql.= " param,";
  337. $sql.= " alwayseditable,";
  338. $sql.= " perms,";
  339. $sql.= " langs,";
  340. $sql.= " list,";
  341. $sql.= " fielddefault,";
  342. $sql.= " fieldcomputed,";
  343. $sql.= " fk_user_author,";
  344. $sql.= " fk_user_modif,";
  345. $sql.= " datec,";
  346. $sql.= " enabled,";
  347. $sql.= " help";
  348. $sql.= " )";
  349. $sql.= " VALUES('".$attrname."',";
  350. $sql.= " '".$this->db->escape($label)."',";
  351. $sql.= " '".$this->db->escape($type)."',";
  352. $sql.= " ".$pos.",";
  353. $sql.= " '".$this->db->escape($size)."',";
  354. $sql.= " ".($entity===''?$conf->entity:$entity).",";
  355. $sql.= " '".$this->db->escape($elementtype)."',";
  356. $sql.= " ".$unique.",";
  357. $sql.= " ".$required.",";
  358. $sql.= " '".$this->db->escape($params)."',";
  359. $sql.= " ".$alwayseditable.",";
  360. $sql.= " ".($perms?"'".$this->db->escape($perms)."'":"null").",";
  361. $sql.= " ".($langfile?"'".$this->db->escape($langfile)."'":"null").",";
  362. $sql.= " '".$this->db->escape($list)."',";
  363. $sql.= " ".($default?"'".$this->db->escape($default)."'":"null").",";
  364. $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").",";
  365. $sql .= " " . (is_object($user) ? $user->id : 0). ",";
  366. $sql .= " " . (is_object($user) ? $user->id : 0). ",";
  367. $sql .= "'" . $this->db->idate(dol_now()) . "',";
  368. $sql.= " ".($enabled?"'".$this->db->escape($enabled)."'":"1").",";
  369. $sql.= " ".($help?"'".$this->db->escape($help)."'":"null");
  370. $sql.=')';
  371. dol_syslog(get_class($this)."::create_label", LOG_DEBUG);
  372. if ($this->db->query($sql))
  373. {
  374. return 1;
  375. }
  376. else
  377. {
  378. $this->error=$this->db->lasterror();
  379. $this->errno=$this->db->lasterrno();
  380. return -1;
  381. }
  382. }
  383. }
  384. /**
  385. * Delete an optional attribute
  386. *
  387. * @param string $attrname Code of attribute to delete
  388. * @param string $elementtype Element type ('member', 'product', 'thirdparty', 'contact', ...)
  389. * @return int < 0 if KO, 0 if nothing is done, 1 if OK
  390. */
  391. function delete($attrname, $elementtype='member')
  392. {
  393. if ($elementtype == 'thirdparty') $elementtype='societe';
  394. if ($elementtype == 'contact') $elementtype='socpeople';
  395. $table=$elementtype.'_extrafields';
  396. if ($elementtype == 'categorie') $table='categories_extrafields';
  397. $error=0;
  398. if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
  399. {
  400. $result=$this->delete_label($attrname,$elementtype);
  401. if ($result < 0)
  402. {
  403. $this->error=$this->db->lasterror();
  404. $error++;
  405. }
  406. if (! $error)
  407. {
  408. $sql = "SELECT COUNT(rowid) as nb";
  409. $sql.= " FROM ".MAIN_DB_PREFIX."extrafields";
  410. $sql.= " WHERE elementtype = '".$elementtype."'";
  411. $sql.= " AND name = '".$attrname."'";
  412. //$sql.= " AND entity IN (0,".$conf->entity.")"; Do not test on entity here. We want to see if there is still on field remaning in other entities before deleting field in table
  413. $resql = $this->db->query($sql);
  414. if ($resql)
  415. {
  416. $obj = $this->db->fetch_object($resql);
  417. if ($obj->nb <= 0)
  418. {
  419. $result=$this->db->DDLDropField(MAIN_DB_PREFIX.$table,$attrname); // This also drop the unique key
  420. if ($result < 0)
  421. {
  422. $this->error=$this->db->lasterror();
  423. $error++;
  424. }
  425. }
  426. }
  427. }
  428. return $result;
  429. }
  430. else
  431. {
  432. return 0;
  433. }
  434. }
  435. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  436. /**
  437. * Delete description of an optional attribute
  438. *
  439. * @param string $attrname Code of attribute to delete
  440. * @param string $elementtype Element type ('member', 'product', 'thirdparty', ...)
  441. * @return int < 0 if KO, 0 if nothing is done, 1 if OK
  442. */
  443. private function delete_label($attrname, $elementtype='member')
  444. {
  445. // phpcs:enable
  446. global $conf;
  447. if ($elementtype == 'thirdparty') $elementtype='societe';
  448. if ($elementtype == 'contact') $elementtype='socpeople';
  449. if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
  450. {
  451. $sql = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
  452. $sql.= " WHERE name = '".$attrname."'";
  453. $sql.= " AND entity IN (0,".$conf->entity.')';
  454. $sql.= " AND elementtype = '".$elementtype."'";
  455. dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
  456. $resql=$this->db->query($sql);
  457. if ($resql)
  458. {
  459. return 1;
  460. }
  461. else
  462. {
  463. print dol_print_error($this->db);
  464. return -1;
  465. }
  466. }
  467. else
  468. {
  469. return 0;
  470. }
  471. }
  472. /**
  473. * Modify type of a personalized attribute
  474. *
  475. * @param string $attrname Name of attribute
  476. * @param string $label Label of attribute
  477. * @param string $type Type of attribute ('boolean', 'int', 'varchar', 'text', 'html', 'date', 'datehour','price','phone','mail','password','url','select','checkbox', ...)
  478. * @param int $length Length of attribute
  479. * @param string $elementtype Element type ('member', 'product', 'thirdparty', 'contact', ...)
  480. * @param int $unique Is field unique or not
  481. * @param int $required Is field required or not
  482. * @param int $pos Position of attribute
  483. * @param array $param Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
  484. * @param int $alwayseditable Is attribute always editable regardless of the document status
  485. * @param string $perms Permission to check
  486. * @param string $list Visibility
  487. * @param string $help Help on tooltip
  488. * @param string $default Default value (in database. use the default_value feature for default value on screen).
  489. * @param string $computed Computed value
  490. * @param string $entity Entity of extrafields
  491. * @param string $langfile Language file
  492. * @param string $enabled Condition to have the field enabled or not
  493. * @param int $totalizable Is extrafield totalizable on list
  494. * @return int >0 if OK, <=0 if KO
  495. */
  496. function update($attrname, $label, $type, $length, $elementtype, $unique=0, $required=0, $pos=0, $param='', $alwayseditable=0, $perms='', $list='', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0)
  497. {
  498. if ($elementtype == 'thirdparty') $elementtype='societe';
  499. if ($elementtype == 'contact') $elementtype='socpeople';
  500. $table=$elementtype.'_extrafields';
  501. if ($elementtype == 'categorie') $table='categories_extrafields';
  502. if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
  503. {
  504. if ($type=='boolean') {
  505. $typedb='int';
  506. $lengthdb='1';
  507. } elseif($type=='price') {
  508. $typedb='double';
  509. $lengthdb='24,8';
  510. } elseif($type=='phone') {
  511. $typedb='varchar';
  512. $lengthdb='20';
  513. } elseif($type=='mail') {
  514. $typedb='varchar';
  515. $lengthdb='128';
  516. } elseif($type=='url') {
  517. $typedb='varchar';
  518. $lengthdb='255';
  519. } elseif (($type=='select') || ($type=='sellist') || ($type=='radio') || ($type=='checkbox') || ($type=='chkbxlst')) {
  520. $typedb='varchar';
  521. $lengthdb='255';
  522. } elseif ($type == 'html') {
  523. $typedb='text';
  524. } elseif ($type=='link') {
  525. $typedb='int';
  526. $lengthdb='11';
  527. } elseif($type=='password') {
  528. $typedb='varchar';
  529. $lengthdb='50';
  530. } else {
  531. $typedb=$type;
  532. $lengthdb=$length;
  533. }
  534. $field_desc = array('type'=>$typedb, 'value'=>$lengthdb, 'null'=>($required?'NOT NULL':'NULL'), 'default'=>$default);
  535. if ($type != 'separate') // No table update when separate type
  536. {
  537. $result=$this->db->DDLUpdateField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
  538. }
  539. if ($result > 0 || $type == 'separate')
  540. {
  541. if ($label)
  542. {
  543. $result=$this->update_label($attrname,$label,$type,$length,$elementtype,$unique,$required,$pos,$param,$alwayseditable,$perms,$list,$help,$default,$computed,$entity,$langfile,$enabled, $totalizable);
  544. }
  545. if ($result > 0)
  546. {
  547. $sql='';
  548. if ($unique)
  549. {
  550. $sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
  551. }
  552. else
  553. {
  554. $sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." DROP INDEX uk_".$table."_".$attrname;
  555. }
  556. dol_syslog(get_class($this).'::update', LOG_DEBUG);
  557. $resql=$this->db->query($sql,1,'dml');
  558. return 1;
  559. }
  560. else
  561. {
  562. $this->error=$this->db->lasterror();
  563. return -1;
  564. }
  565. }
  566. else
  567. {
  568. $this->error=$this->db->lasterror();
  569. return -1;
  570. }
  571. }
  572. else
  573. {
  574. return 0;
  575. }
  576. }
  577. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  578. /**
  579. * Modify description of personalized attribute
  580. *
  581. * @param string $attrname Name of attribute
  582. * @param string $label Label of attribute
  583. * @param string $type Type of attribute
  584. * @param int $size Length of attribute
  585. * @param string $elementtype Element type ('member', 'product', 'thirdparty', ...)
  586. * @param int $unique Is field unique or not
  587. * @param int $required Is field required or not
  588. * @param int $pos Position of attribute
  589. * @param array $param Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
  590. * @param int $alwayseditable Is attribute always editable regardless of the document status
  591. * @param string $perms Permission to check
  592. * @param string $list Visiblity
  593. * @param string $help Help on tooltip.
  594. * @param string $default Default value (in database. use the default_value feature for default value on screen).
  595. * @param string $computed Computed value
  596. * @param string $entity Entity of extrafields
  597. * @param string $langfile Language file
  598. * @param string $enabled Condition to have the field enabled or not
  599. * @param int $totalizable Is extrafield totalizable on list
  600. * @return int <=0 if KO, >0 if OK
  601. */
  602. private function update_label($attrname,$label,$type,$size,$elementtype,$unique=0,$required=0,$pos=0,$param='',$alwayseditable=0,$perms='',$list='0',$help='',$default='',$computed='',$entity='',$langfile='',$enabled='1', $totalizable=0)
  603. {
  604. // phpcs:enable
  605. global $conf, $user;
  606. dol_syslog(get_class($this)."::update_label ".$attrname.", ".$label.", ".$type.", ".$size.", ".$elementtype.", ".$unique.", ".$required.", ".$pos.", ".$alwayseditable.", ".$perms.", ".$list.", ".$default.", ".$computed.", ".$entity.", ".$langfile.", ".$enabled.", ".$totalizable);
  607. // Clean parameters
  608. if ($elementtype == 'thirdparty') $elementtype='societe';
  609. if ($elementtype == 'contact') $elementtype='socpeople';
  610. if (empty($pos)) $pos=0;
  611. if (empty($list)) $list='0';
  612. if (empty($totalizable)) {
  613. $totalizable = 0;
  614. }
  615. if (empty($required)) $required=0;
  616. if (empty($unique)) $unique=0;
  617. if (empty($alwayseditable)) $alwayseditable=0;
  618. if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
  619. {
  620. $this->db->begin();
  621. if (is_array($param) && count($param) > 0)
  622. {
  623. $params = serialize($param);
  624. }
  625. elseif (strlen($param) > 0)
  626. {
  627. $params = trim($param);
  628. }
  629. else
  630. {
  631. $params='';
  632. }
  633. if ($entity === '' || $entity != '0')
  634. {
  635. // We dont want on all entities, we delete all and current
  636. $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
  637. $sql_del.= " WHERE name = '".$attrname."'";
  638. $sql_del.= " AND entity IN (0, ".($entity===''?$conf->entity:$entity).")";
  639. $sql_del.= " AND elementtype = '".$elementtype."'";
  640. }
  641. else
  642. {
  643. // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity)
  644. $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
  645. $sql_del.= " WHERE name = '".$attrname."'";
  646. $sql_del.= " AND entity = 0";
  647. $sql_del.= " AND elementtype = '".$elementtype."'";
  648. }
  649. $resql1=$this->db->query($sql_del);
  650. $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
  651. $sql.= " name,"; // This is code
  652. $sql.= " entity,";
  653. $sql.= " label,";
  654. $sql.= " type,";
  655. $sql.= " size,";
  656. $sql.= " elementtype,";
  657. $sql.= " fieldunique,";
  658. $sql.= " fieldrequired,";
  659. $sql.= " perms,";
  660. $sql.= " langs,";
  661. $sql.= " pos,";
  662. $sql.= " alwayseditable,";
  663. $sql.= " param,";
  664. $sql.= " list,";
  665. $sql.= " totalizable,";
  666. $sql.= " fielddefault,";
  667. $sql.= " fieldcomputed,";
  668. $sql.= " fk_user_author,";
  669. $sql.= " fk_user_modif,";
  670. $sql.= " datec,";
  671. $sql.= " enabled,";
  672. $sql.= " help";
  673. $sql.= ") VALUES (";
  674. $sql.= "'".$attrname."',";
  675. $sql.= " ".($entity===''?$conf->entity:$entity).",";
  676. $sql.= " '".$this->db->escape($label)."',";
  677. $sql.= " '".$this->db->escape($type)."',";
  678. $sql.= " '".$this->db->escape($size)."',";
  679. $sql.= " '".$this->db->escape($elementtype)."',";
  680. $sql.= " ".$unique.",";
  681. $sql.= " ".$required.",";
  682. $sql.= " ".($perms?"'".$this->db->escape($perms)."'":"null").",";
  683. $sql.= " ".($langfile?"'".$this->db->escape($langfile)."'":"null").",";
  684. $sql.= " ".$pos.",";
  685. $sql.= " '".$this->db->escape($alwayseditable)."',";
  686. $sql.= " '".$this->db->escape($params)."',";
  687. $sql.= " '".$this->db->escape($list)."', ";
  688. $sql.= " ".$totalizable.",";
  689. $sql.= " ".(($default!='')?"'".$this->db->escape($default)."'":"null").",";
  690. $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").",";
  691. $sql .= " " . $user->id . ",";
  692. $sql .= " " . $user->id . ",";
  693. $sql .= "'" . $this->db->idate(dol_now()) . "',";
  694. $sql .= "'" . $this->db->escape($enabled). "',";
  695. $sql.= " ".($help?"'".$this->db->escape($help)."'":"null");
  696. $sql.= ")";
  697. $resql2=$this->db->query($sql);
  698. if ($resql1 && $resql2)
  699. {
  700. $this->db->commit();
  701. return 1;
  702. }
  703. else
  704. {
  705. $this->db->rollback();
  706. print dol_print_error($this->db);
  707. return -1;
  708. }
  709. }
  710. else
  711. {
  712. return 0;
  713. }
  714. }
  715. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  716. /**
  717. * Load array this->attributes, or old this->attribute_xxx like attribute_label, attribute_type, ...
  718. *
  719. * @param string $elementtype Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...).
  720. * @param boolean $forceload Force load of extra fields whatever is option MAIN_EXTRAFIELDS_DISABLED. Deprecated. Should not be required.
  721. * @return array Array of attributes keys+label for all extra fields.
  722. */
  723. function fetch_name_optionals_label($elementtype,$forceload=false)
  724. {
  725. // phpcs:enable
  726. global $conf;
  727. if (empty($elementtype)) return array();
  728. if ($elementtype == 'thirdparty') $elementtype='societe';
  729. if ($elementtype == 'contact') $elementtype='socpeople';
  730. if ($elementtype == 'order_supplier') $elementtype='commande_fournisseur';
  731. $array_name_label=array();
  732. // To avoid conflicts with external modules. TODO Remove this.
  733. if (!$forceload && !empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) return $array_name_label;
  734. // Set array of label of entity
  735. // TODO Remove completely loading of label. This should be done by presentation.
  736. $labelmulticompany=array();
  737. if (!empty($conf->multicompany->enabled))
  738. {
  739. $sql_entity_name='SELECT rowid, label FROM '.MAIN_DB_PREFIX.'entity WHERE rowid in (0,'.$conf->entity.')';
  740. $resql_entity_name=$this->db->query($sql_entity_name);
  741. if ($resql_entity_name)
  742. {
  743. while ($obj = $this->db->fetch_object($resql_entity_name))
  744. {
  745. $labelmulticompany[$obj->rowid]=$obj->label;
  746. }
  747. }
  748. }
  749. // We should not have several time this log. If we have, there is some optimization to do by calling a simple $object->fetch_optionals() that include cache management.
  750. dol_syslog("fetch_name_optionals_label elementtype=".$elementtype);
  751. $sql = "SELECT rowid,name,label,type,size,elementtype,fieldunique,fieldrequired,param,pos,alwayseditable,perms,langs,list,totalizable,fielddefault,fieldcomputed,entity,enabled,help";
  752. $sql.= " FROM ".MAIN_DB_PREFIX."extrafields";
  753. $sql.= " WHERE entity IN (0,".$conf->entity.")";
  754. if ($elementtype) $sql.= " AND elementtype = '".$elementtype."'"; // Filed with object->table_element
  755. $sql.= " ORDER BY pos";
  756. $resql=$this->db->query($sql);
  757. if ($resql)
  758. {
  759. if ($this->db->num_rows($resql))
  760. {
  761. while ($tab = $this->db->fetch_object($resql))
  762. {
  763. // We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
  764. if ($tab->type != 'separate')
  765. {
  766. $array_name_label[$tab->name]=$tab->label;
  767. }
  768. // Old usage
  769. $this->attribute_type[$tab->name]=$tab->type;
  770. $this->attribute_label[$tab->name]=$tab->label;
  771. $this->attribute_size[$tab->name]=$tab->size;
  772. $this->attribute_elementtype[$tab->name]=$tab->elementtype;
  773. $this->attribute_default[$tab->name]=$tab->fielddefault;
  774. $this->attribute_computed[$tab->name]=$tab->fieldcomputed;
  775. $this->attribute_unique[$tab->name]=$tab->fieldunique;
  776. $this->attribute_required[$tab->name]=$tab->fieldrequired;
  777. $this->attribute_param[$tab->name]=($tab->param ? unserialize($tab->param) : '');
  778. $this->attribute_pos[$tab->name]=$tab->pos;
  779. $this->attribute_alwayseditable[$tab->name]=$tab->alwayseditable;
  780. $this->attribute_perms[$tab->name]=(strlen($tab->perms) == 0 ? 1 : $tab->perms);
  781. $this->attribute_langfile[$tab->name]=$tab->langs;
  782. $this->attribute_list[$tab->name]=$tab->list;
  783. $this->attribute_totalizable[$tab->name]=$tab->totalizable;
  784. $this->attribute_entityid[$tab->name]=$tab->entity;
  785. $this->attribute_entitylabel[$tab->name]=(empty($labelmulticompany[$tab->entity])?'Entity'.$tab->entity:$labelmulticompany[$tab->entity]);
  786. // New usage
  787. $this->attributes[$tab->elementtype]['type'][$tab->name]=$tab->type;
  788. $this->attributes[$tab->elementtype]['label'][$tab->name]=$tab->label;
  789. $this->attributes[$tab->elementtype]['size'][$tab->name]=$tab->size;
  790. $this->attributes[$tab->elementtype]['elementtype'][$tab->name]=$tab->elementtype;
  791. $this->attributes[$tab->elementtype]['default'][$tab->name]=$tab->fielddefault;
  792. $this->attributes[$tab->elementtype]['computed'][$tab->name]=$tab->fieldcomputed;
  793. $this->attributes[$tab->elementtype]['unique'][$tab->name]=$tab->fieldunique;
  794. $this->attributes[$tab->elementtype]['required'][$tab->name]=$tab->fieldrequired;
  795. $this->attributes[$tab->elementtype]['param'][$tab->name]=($tab->param ? unserialize($tab->param) : '');
  796. $this->attributes[$tab->elementtype]['pos'][$tab->name]=$tab->pos;
  797. $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name]=$tab->alwayseditable;
  798. $this->attributes[$tab->elementtype]['perms'][$tab->name]=(strlen($tab->perms) == 0 ? 1 : $tab->perms);
  799. $this->attributes[$tab->elementtype]['langfile'][$tab->name]=$tab->langs;
  800. $this->attributes[$tab->elementtype]['list'][$tab->name]=$tab->list;
  801. $this->attributes[$tab->elementtype]['totalizable'][$tab->name]=$tab->totalizable;
  802. $this->attributes[$tab->elementtype]['entityid'][$tab->name]=$tab->entity;
  803. $this->attributes[$tab->elementtype]['entitylabel'][$tab->name]=(empty($labelmulticompany[$tab->entity])?'Entity'.$tab->entity:$labelmulticompany[$tab->entity]);
  804. $this->attributes[$tab->elementtype]['enabled'][$tab->name]=$tab->enabled;
  805. $this->attributes[$tab->elementtype]['help'][$tab->name]=$tab->help;
  806. $this->attributes[$tab->elementtype]['loaded']=1;
  807. }
  808. }
  809. if ($elementtype) $this->attributes[$elementtype]['loaded']=1; // If nothing found, we also save tag 'loaded'
  810. }
  811. else
  812. {
  813. $this->error=$this->db->lasterror();
  814. dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
  815. }
  816. return $array_name_label;
  817. }
  818. /**
  819. * Return HTML string to put an input field into a page
  820. * Code very similar with showInputField of common object
  821. *
  822. * @param string $key Key of attribute
  823. * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value)
  824. * @param string $moreparam To add more parametes on html input tag
  825. * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names)
  826. * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names)
  827. * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric)
  828. * @param int $objectid Current object id
  829. * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data
  830. * @return string
  831. */
  832. function showInputField($key, $value, $moreparam='', $keysuffix='', $keyprefix='', $morecss='', $objectid=0, $extrafieldsobjectkey='')
  833. {
  834. global $conf,$langs,$form;
  835. if (! is_object($form))
  836. {
  837. require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
  838. $form=new Form($this->db);
  839. }
  840. $out='';
  841. $keyprefix = $keyprefix.'options_'; // Because we work on extrafields
  842. if (! empty($extrafieldsobjectkey))
  843. {
  844. $label=$this->attributes[$extrafieldsobjectkey]['label'][$key];
  845. $type=$this->attributes[$extrafieldsobjectkey]['type'][$key];
  846. $size=$this->attributes[$extrafieldsobjectkey]['size'][$key];
  847. $default=$this->attributes[$extrafieldsobjectkey]['default'][$key];
  848. $computed=$this->attributes[$extrafieldsobjectkey]['computed'][$key];
  849. $unique=$this->attributes[$extrafieldsobjectkey]['unique'][$key];
  850. $required=$this->attributes[$extrafieldsobjectkey]['required'][$key];
  851. $param=$this->attributes[$extrafieldsobjectkey]['param'][$key];
  852. $perms=dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1);
  853. $langfile=$this->attributes[$extrafieldsobjectkey]['langfile'][$key];
  854. $list=dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1);
  855. $totalizable=$this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
  856. $help=$this->attributes[$extrafieldsobjectkey]['help'][$key];
  857. $hidden=(empty($list) ? 1 : 0); // If empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
  858. }
  859. else // Old usage
  860. {
  861. $label=$this->attribute_label[$key];
  862. $type =$this->attribute_type[$key];
  863. $size =$this->attribute_size[$key];
  864. $elementtype=$this->attribute_elementtype[$key]; // Seems not used
  865. $default=$this->attribute_default[$key];
  866. $computed=$this->attribute_computed[$key];
  867. $unique=$this->attribute_unique[$key];
  868. $required=$this->attribute_required[$key];
  869. $param=$this->attribute_param[$key];
  870. $langfile=$this->attribute_langfile[$key];
  871. $list=$this->attribute_list[$key];
  872. $totalizable=$this->attribute_totalizable[$key];
  873. $hidden=(empty($list) ? 1 : 0); // If empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
  874. }
  875. if ($computed)
  876. {
  877. if (! preg_match('/^search_/', $keyprefix)) return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
  878. else return '';
  879. }
  880. if (empty($morecss))
  881. {
  882. if ($type == 'date')
  883. {
  884. $morecss = 'minwidth100imp';
  885. }
  886. elseif ($type == 'datetime')
  887. {
  888. $morecss = 'minwidth200imp';
  889. }
  890. elseif (in_array($type,array('int','integer','double','price')))
  891. {
  892. $morecss = 'maxwidth75';
  893. }
  894. elseif ($type == 'password')
  895. {
  896. $morecss='maxwidth100';
  897. }
  898. elseif ($type == 'url')
  899. {
  900. $morecss='minwidth400';
  901. }
  902. elseif ($type == 'boolean')
  903. {
  904. $morecss='';
  905. }
  906. else
  907. {
  908. if (round($size) < 12)
  909. {
  910. $morecss = 'minwidth100';
  911. }
  912. else if (round($size) <= 48)
  913. {
  914. $morecss = 'minwidth200';
  915. }
  916. else
  917. {
  918. $morecss = 'minwidth400';
  919. }
  920. }
  921. }
  922. if (in_array($type,array('date','datetime')))
  923. {
  924. $tmp=explode(',',$size);
  925. $newsize=$tmp[0];
  926. $showtime = in_array($type,array('datetime')) ? 1 : 0;
  927. // Do not show current date when field not required (see selectDate() method)
  928. if (!$required && $value == '') $value = '-1';
  929. // TODO Must also support $moreparam
  930. $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
  931. }
  932. elseif (in_array($type,array('int','integer')))
  933. {
  934. $tmp=explode(',',$size);
  935. $newsize=$tmp[0];
  936. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$newsize.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>';
  937. }
  938. elseif (preg_match('/varchar/', $type))
  939. {
  940. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$size.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>';
  941. }
  942. elseif (in_array($type, array('mail', 'phone', 'url')))
  943. {
  944. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>';
  945. }
  946. elseif ($type == 'text')
  947. {
  948. if (! preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field
  949. {
  950. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  951. $doleditor=new DolEditor($keyprefix.$key.$keysuffix,$value,'',200,'dolibarr_notes','In',false,false,false,ROWS_5,'90%');
  952. $out=$doleditor->Create(1);
  953. }
  954. else
  955. {
  956. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>';
  957. }
  958. }
  959. elseif ($type == 'html')
  960. {
  961. if (! preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field
  962. {
  963. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  964. $doleditor=new DolEditor($keyprefix.$key.$keysuffix,$value,'',200,'dolibarr_notes','In',false,false,! empty($conf->fckeditor->enabled) && $conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_5,'90%');
  965. $out=$doleditor->Create(1);
  966. }
  967. else
  968. {
  969. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>';
  970. }
  971. }
  972. elseif ($type == 'boolean')
  973. {
  974. $checked='';
  975. if (!empty($value)) {
  976. $checked=' checked value="1" ';
  977. } else {
  978. $checked=' value="1" ';
  979. }
  980. $out='<input type="checkbox" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam?$moreparam:'').'>';
  981. }
  982. elseif ($type == 'price')
  983. {
  984. if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
  985. $value=price($value);
  986. }
  987. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> '.$langs->getCurrencySymbol($conf->currency);
  988. }
  989. elseif ($type == 'double')
  990. {
  991. if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
  992. $value=price($value);
  993. }
  994. $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> ';
  995. }
  996. elseif ($type == 'select')
  997. {
  998. $out = '';
  999. if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
  1000. {
  1001. include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
  1002. $out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
  1003. }
  1004. $out.='<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>';
  1005. $out.='<option value="0">&nbsp;</option>';
  1006. foreach ($param['options'] as $key => $val)
  1007. {
  1008. if ((string) $key == '') continue;
  1009. list($val, $parent) = explode('|', $val);
  1010. $out.='<option value="'.$key.'"';
  1011. $out.= (((string) $value == (string) $key)?' selected':'');
  1012. $out.= (!empty($parent)?' parent="'.$parent.'"':'');
  1013. $out.='>';
  1014. if ($langfile && $val) $out.=$langs->trans($val);
  1015. else $out.=$val;
  1016. $out.='</option>';
  1017. }
  1018. $out.='</select>';
  1019. }
  1020. elseif ($type == 'sellist')
  1021. {
  1022. $out = '';
  1023. if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
  1024. {
  1025. include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
  1026. $out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
  1027. }
  1028. $out.='<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>';
  1029. if (is_array($param['options']))
  1030. {
  1031. $param_list=array_keys($param['options']);
  1032. $InfoFieldList = explode(":", $param_list[0]);
  1033. $parentName='';
  1034. $parentField='';
  1035. // 0 : tableName
  1036. // 1 : label field name
  1037. // 2 : key fields name (if differ of rowid)
  1038. // 3 : key field parent (for dependent lists)
  1039. // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
  1040. $keyList=(empty($InfoFieldList[2])?'rowid':$InfoFieldList[2].' as rowid');
  1041. if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4]))
  1042. {
  1043. if (strpos($InfoFieldList[4], 'extra.') !== false)
  1044. {
  1045. $keyList='main.'.$InfoFieldList[2].' as rowid';
  1046. } else {
  1047. $keyList=$InfoFieldList[2].' as rowid';
  1048. }
  1049. }
  1050. if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3]))
  1051. {
  1052. list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
  1053. $keyList.= ', '.$parentField;
  1054. }
  1055. $fields_label = explode('|',$InfoFieldList[1]);
  1056. if (is_array($fields_label))
  1057. {
  1058. $keyList .=', ';
  1059. $keyList .= implode(', ', $fields_label);
  1060. }
  1061. $sqlwhere='';
  1062. $sql = 'SELECT '.$keyList;
  1063. $sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0];
  1064. if (!empty($InfoFieldList[4]))
  1065. {
  1066. // can use curent entity filter
  1067. if (strpos($InfoFieldList[4], '$ENTITY$')!==false) {
  1068. $InfoFieldList[4]=str_replace('$ENTITY$',$conf->entity,$InfoFieldList[4]);
  1069. }
  1070. // can use SELECT request
  1071. if (strpos($InfoFieldList[4], '$SEL$')!==false) {
  1072. $InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]);
  1073. }
  1074. // current object id can be use into filter
  1075. if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) {
  1076. $InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]);
  1077. } else {
  1078. $InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]);
  1079. }
  1080. //We have to join on extrafield table
  1081. if (strpos($InfoFieldList[4], 'extra')!==false)
  1082. {
  1083. $sql.= ' as main, '.MAIN_DB_PREFIX .$InfoFieldList[0].'_extrafields as extra';
  1084. $sqlwhere.= ' WHERE extra.fk_object=main.'.$InfoFieldList[2]. ' AND '.$InfoFieldList[4];
  1085. }
  1086. else
  1087. {
  1088. $sqlwhere.= ' WHERE '.$InfoFieldList[4];
  1089. }
  1090. }
  1091. else
  1092. {
  1093. $sqlwhere.= ' WHERE 1=1';
  1094. }
  1095. // Some tables may have field, some other not. For the moment we disable it.
  1096. if (in_array($InfoFieldList[0],array('tablewithentity')))
  1097. {
  1098. $sqlwhere.= ' AND entity = '.$conf->entity;
  1099. }
  1100. $sql.=$sqlwhere;
  1101. //print $sql;
  1102. $sql .= ' ORDER BY ' . implode(', ', $fields_label);
  1103. dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
  1104. $resql = $this->db->query($sql);
  1105. if ($resql)
  1106. {
  1107. $out.='<option value="0">&nbsp;</option>';
  1108. $num = $this->db->num_rows($resql);
  1109. $i = 0;
  1110. while ($i < $num)
  1111. {
  1112. $labeltoshow='';
  1113. $obj = $this->db->fetch_object($resql);
  1114. // Several field into label (eq table:code|libelle:rowid)
  1115. $notrans = false;
  1116. $fields_label = explode('|',$InfoFieldList[1]);
  1117. if (is_array($fields_label))
  1118. {
  1119. $notrans = true;
  1120. foreach ($fields_label as $field_toshow)
  1121. {
  1122. $labeltoshow.= $obj->$field_toshow.' ';
  1123. }
  1124. }
  1125. else
  1126. {
  1127. $labeltoshow=$obj->{$InfoFieldList[1]};
  1128. }
  1129. $labeltoshow=dol_trunc($labeltoshow,45);
  1130. if ($value == $obj->rowid)
  1131. {
  1132. foreach ($fields_label as $field_toshow)
  1133. {
  1134. $translabel=$langs->trans($obj->$field_toshow);
  1135. if ($translabel!=$obj->$field_toshow) {
  1136. $labeltoshow=dol_trunc($translabel,18).' ';
  1137. }else {
  1138. $labeltoshow=dol_trunc($obj->$field_toshow,18).' ';
  1139. }
  1140. }
  1141. $out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
  1142. }
  1143. else
  1144. {
  1145. if (! $notrans)
  1146. {
  1147. $translabel=$langs->trans($obj->{$InfoFieldList[1]});
  1148. if ($translabel!=$obj->{$InfoFieldList[1]}) {
  1149. $labeltoshow=dol_trunc($translabel,18);
  1150. }
  1151. else {
  1152. $labeltoshow=dol_trunc($obj->{$InfoFieldList[1]},18);
  1153. }
  1154. }
  1155. if (empty($labeltoshow)) $labeltoshow='(not defined)';
  1156. if ($value==$obj->rowid)
  1157. {
  1158. $out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
  1159. }
  1160. if (!empty($InfoFieldList[3]) && $parentField)
  1161. {
  1162. $parent = $parentName.':'.$obj->{$parentField};
  1163. }
  1164. $out.='<option value="'.$obj->rowid.'"';
  1165. $out.= ($value==$obj->rowid?' selected':'');
  1166. $out.= (!empty($parent)?' parent="'.$parent.'"':'');
  1167. $out.='>'.$labeltoshow.'</option>';
  1168. }
  1169. $i++;
  1170. }
  1171. $this->db->free($resql);
  1172. }
  1173. else {
  1174. print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
  1175. }
  1176. }
  1177. $out.='</select>';
  1178. }
  1179. elseif ($type == 'checkbox')
  1180. {
  1181. $value_arr=explode(',',$value);
  1182. $out=$form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options'])?null:$param['options']), $value_arr, '', 0, '', 0, '100%');
  1183. }
  1184. elseif ($type == 'radio')
  1185. {
  1186. $out='';
  1187. foreach ($param['options'] as $keyopt => $val)
  1188. {
  1189. $out.='<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'');
  1190. $out.=' value="'.$keyopt.'"';
  1191. $out.=' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
  1192. $out.= ($value==$keyopt?'checked':'');
  1193. $out.='/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$val.'</label><br>';
  1194. }
  1195. }
  1196. elseif ($type == 'chkbxlst')
  1197. {
  1198. if (is_array($value)) {
  1199. $value_arr = $value;
  1200. }
  1201. else {
  1202. $value_arr = explode(',', $value);
  1203. }
  1204. if (is_array($param['options'])) {
  1205. $param_list = array_keys($param['options']);
  1206. $InfoFieldList = explode(":", $param_list[0]);
  1207. $parentName='';
  1208. $parentField='';
  1209. // 0 : tableName
  1210. // 1 : label field name
  1211. // 2 : key fields name (if differ of rowid)
  1212. // 3 : key field parent (for dependent lists)
  1213. // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
  1214. $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid');
  1215. if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) {
  1216. list ( $parentName, $parentField ) = explode('|', $InfoFieldList[3]);
  1217. $keyList .= ', ' . $parentField;
  1218. }
  1219. if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4])) {
  1220. if (strpos($InfoFieldList[4], 'extra.') !== false) {
  1221. $keyList = 'main.' . $InfoFieldList[2] . ' as rowid';
  1222. } else {
  1223. $keyList = $InfoFieldList[2] . ' as rowid';
  1224. }
  1225. }
  1226. $fields_label = explode('|', $InfoFieldList[1]);
  1227. if (is_array($fields_label)) {
  1228. $keyList .= ', ';
  1229. $keyList .= implode(', ', $fields_label);
  1230. }
  1231. $sqlwhere = '';
  1232. $sql = 'SELECT ' . $keyList;
  1233. $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
  1234. if (! empty($InfoFieldList[4])) {
  1235. // can use SELECT request
  1236. if (strpos($InfoFieldList[4], '$SEL$')!==false) {
  1237. $InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]);
  1238. }
  1239. // current object id can be use into filter
  1240. if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) {
  1241. $InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]);
  1242. } else {
  1243. $InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]);
  1244. }
  1245. // We have to join on extrafield table
  1246. if (strpos($InfoFieldList[4], 'extra') !== false) {
  1247. $sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra';
  1248. $sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4];
  1249. } else {
  1250. $sqlwhere .= ' WHERE ' . $InfoFieldList[4];
  1251. }
  1252. } else {
  1253. $sqlwhere .= ' WHERE 1=1';
  1254. }
  1255. // Some tables may have field, some other not. For the moment we disable it.
  1256. if (in_array($InfoFieldList[0], array ('tablewithentity')))
  1257. {
  1258. $sqlwhere .= ' AND entity = ' . $conf->entity;
  1259. }
  1260. // $sql.=preg_replace('/^ AND /','',$sqlwhere);
  1261. // print $sql;
  1262. $sql .= $sqlwhere;
  1263. dol_syslog(get_class($this) . '::showInputField type=chkbxlst',LOG_DEBUG);
  1264. $resql = $this->db->query($sql);
  1265. if ($resql) {
  1266. $num = $this->db->num_rows($resql);
  1267. $i = 0;
  1268. $data=array();
  1269. while ( $i < $num ) {
  1270. $labeltoshow = '';
  1271. $obj = $this->db->fetch_object($resql);
  1272. $notrans = false;
  1273. // Several field into label (eq table:code|libelle:rowid)
  1274. $fields_label = explode('|', $InfoFieldList[1]);
  1275. if (is_array($fields_label)) {
  1276. $notrans = true;
  1277. foreach ( $fields_label as $field_toshow ) {
  1278. $labeltoshow .= $obj->$field_toshow . ' ';
  1279. }
  1280. } else {
  1281. $labeltoshow = $obj->{$InfoFieldList[1]};
  1282. }
  1283. $labeltoshow = dol_trunc($labeltoshow, 45);
  1284. if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
  1285. foreach ( $fields_label as $field_toshow ) {
  1286. $translabel = $langs->trans($obj->$field_toshow);
  1287. if ($translabel != $obj->$field_toshow) {
  1288. $labeltoshow = dol_trunc($translabel, 18) . ' ';
  1289. } else {
  1290. $labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' ';
  1291. }
  1292. }
  1293. $data[$obj->rowid]=$labeltoshow;
  1294. } else {
  1295. if (! $notrans) {
  1296. $translabel = $langs->trans($obj->{$InfoFieldList[1]});
  1297. if ($translabel != $obj->{$InfoFieldList[1]}) {
  1298. $labeltoshow = dol_trunc($translabel, 18);
  1299. } else {
  1300. $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
  1301. }
  1302. }
  1303. if (empty($labeltoshow))
  1304. $labeltoshow = '(not defined)';
  1305. if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
  1306. $data[$obj->rowid]=$labeltoshow;
  1307. }
  1308. if (! empty($InfoFieldList[3]) && $parentField) {
  1309. $parent = $parentName . ':' . $obj->{$parentField};
  1310. }
  1311. $data[$obj->rowid]=$labeltoshow;
  1312. }
  1313. $i ++;
  1314. }
  1315. $this->db->free($resql);
  1316. $out=$form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
  1317. } else {
  1318. print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>';
  1319. }
  1320. }
  1321. }
  1322. elseif ($type == 'link')
  1323. {
  1324. $param_list=array_keys($param['options']); // $param_list='ObjectName:classPath'
  1325. $showempty=(($required && $default != '')?0:1);
  1326. $out=$form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty);
  1327. }
  1328. elseif ($type == 'password')
  1329. {
  1330. // If prefix is 'search_', field is used as a filter, we use a common text field.
  1331. $out='<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
  1332. $out.='<input autocomplete="new-password" type="'.($keyprefix=='search_'?'text':'password').'" class="flat '.$morecss.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'>';
  1333. }
  1334. if (!empty($hidden)) {
  1335. $out='<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
  1336. }
  1337. /* Add comments
  1338. if ($type == 'date') $out.=' (YYYY-MM-DD)';
  1339. elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
  1340. */
  1341. return $out;
  1342. }
  1343. /**
  1344. * Return HTML string to put an output field into a page
  1345. *
  1346. * @param string $key Key of attribute
  1347. * @param string $value Value to show
  1348. * @param string $moreparam To add more parameters on html input tag (only checkbox use html input for output rendering)
  1349. * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data
  1350. * @return string Formated value
  1351. */
  1352. function showOutputField($key, $value, $moreparam='', $extrafieldsobjectkey='')
  1353. {
  1354. global $conf,$langs;
  1355. if (! empty($extrafieldsobjectkey))
  1356. {
  1357. $label=$this->attributes[$extrafieldsobjectkey]['label'][$key];
  1358. $type=$this->attributes[$extrafieldsobjectkey]['type'][$key];
  1359. $size=$this->attributes[$extrafieldsobjectkey]['size'][$key];
  1360. $default=$this->attributes[$extrafieldsobjectkey]['default'][$key];
  1361. $computed=$this->attributes[$extrafieldsobjectkey]['computed'][$key];
  1362. $unique=$this->attributes[$extrafieldsobjectkey]['unique'][$key];
  1363. $required=$this->attributes[$extrafieldsobjectkey]['required'][$key];
  1364. $param=$this->attributes[$extrafieldsobjectkey]['param'][$key];
  1365. $perms=dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1);
  1366. $langfile=$this->attributes[$extrafieldsobjectkey]['langfile'][$key];
  1367. $list=dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1);
  1368. $help=$this->attributes[$extrafieldsobjectkey]['help'][$key];
  1369. $hidden=(empty($list) ? 1 : 0); // If $list empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
  1370. }
  1371. else // Old usage
  1372. {
  1373. $label=$this->attribute_label[$key];
  1374. $type=$this->attribute_type[$key];
  1375. $size=$this->attribute_size[$key];
  1376. $default=$this->attribute_default[$key];
  1377. $computed=$this->attribute_computed[$key];
  1378. $unique=$this->attribute_unique[$key];
  1379. $required=$this->attribute_required[$key];
  1380. $param=$this->attribute_param[$key];
  1381. $perms=dol_eval($this->attribute_perms[$key], 1);
  1382. $langfile=$this->attribute_langfile[$key];
  1383. $list=dol_eval($this->attribute_list[$key], 1);
  1384. $help=''; // Not supported with old syntax
  1385. $hidden=(empty($list) ? 1 : 0); // If $list empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
  1386. }
  1387. if ($hidden) return ''; // This is a protection. If field is hidden, we should just not call this method.
  1388. // If field is a computed field, value must become result of compute
  1389. if ($computed)
  1390. {
  1391. // Make the eval of compute string
  1392. //var_dump($computed);
  1393. $value = dol_eval($computed, 1, 0);
  1394. }
  1395. $showsize=0;
  1396. if ($type == 'date')
  1397. {
  1398. $showsize=10;
  1399. $value=dol_print_date($value, 'day');
  1400. }
  1401. elseif ($type == 'datetime')
  1402. {
  1403. $showsize=19;
  1404. $value=dol_print_date($value, 'dayhour');
  1405. }
  1406. elseif ($type == 'int')
  1407. {
  1408. $showsize=10;
  1409. }
  1410. elseif ($type == 'double')
  1411. {
  1412. if (!empty($value)) {
  1413. $value=price($value);
  1414. }
  1415. }
  1416. elseif ($type == 'boolean')
  1417. {
  1418. $checked='';
  1419. if (!empty($value)) {
  1420. $checked=' checked ';
  1421. }
  1422. $value='<input type="checkbox" '.$checked.' '.($moreparam?$moreparam:'').' readonly disabled>';
  1423. }
  1424. elseif ($type == 'mail')
  1425. {
  1426. $value=dol_print_email($value, 0, 0, 0, 64, 1, 1);
  1427. }
  1428. elseif ($type == 'url')
  1429. {
  1430. $value=dol_print_url($value,'_blank',32,1);
  1431. }
  1432. elseif ($type == 'phone')
  1433. {
  1434. $value=dol_print_phone($value, '', 0, 0, '', '&nbsp;', 1);
  1435. }
  1436. elseif ($type == 'price')
  1437. {
  1438. $value=price($value, 0, $langs, 0, 0, -1, $conf->currency);
  1439. }
  1440. elseif ($type == 'select')
  1441. {
  1442. if ($langfile && $param['options'][$value]) $value=$langs->trans($param['options'][$value]);
  1443. else $value=$param['options'][$value];
  1444. }
  1445. elseif ($type == 'sellist')
  1446. {
  1447. $param_list=array_keys($param['options']);
  1448. $InfoFieldList = explode(":", $param_list[0]);
  1449. $selectkey="rowid";
  1450. $keyList='rowid';
  1451. if (count($InfoFieldList)>=3)
  1452. {
  1453. $selectkey = $InfoFieldList[2];
  1454. $keyList=$InfoFieldList[2].' as rowid';
  1455. }
  1456. $fields_label = explode('|',$InfoFieldList[1]);
  1457. if(is_array($fields_label)) {
  1458. $keyList .=', ';
  1459. $keyList .= implode(', ', $fields_label);
  1460. }
  1461. $sql = 'SELECT '.$keyList;
  1462. $sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0];
  1463. if (strpos($InfoFieldList[4], 'extra')!==false)
  1464. {
  1465. $sql.= ' as main';
  1466. }
  1467. if ($selectkey=='rowid' && empty($value)) {
  1468. $sql.= " WHERE ".$selectkey."=0";
  1469. } elseif ($selectkey=='rowid') {
  1470. $sql.= " WHERE ".$selectkey."=".$this->db->escape($value);
  1471. }else {
  1472. $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
  1473. }
  1474. //$sql.= ' AND entity = '.$conf->entity;
  1475. dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
  1476. $resql = $this->db->query($sql);
  1477. if ($resql)
  1478. {
  1479. $value=''; // value was used, so now we reste it to use it to build final output
  1480. $obj = $this->db->fetch_object($resql);
  1481. // Several field into label (eq table:code|libelle:rowid)
  1482. $fields_label = explode('|',$InfoFieldList[1]);
  1483. if(is_array($fields_label) && count($fields_label)>1)
  1484. {
  1485. foreach ($fields_label as $field_toshow)
  1486. {
  1487. $translabel='';
  1488. if (!empty($obj->$field_toshow)) {
  1489. $translabel=$langs->trans($obj->$field_toshow);
  1490. }
  1491. if ($translabel!=$field_toshow) {
  1492. $value.=dol_trunc($translabel,18).' ';
  1493. }else {
  1494. $value.=$obj->$field_toshow.' ';
  1495. }
  1496. }
  1497. }
  1498. else
  1499. {
  1500. $translabel='';
  1501. if (!empty($obj->{$InfoFieldList[1]})) {
  1502. $translabel=$langs->trans($obj->{$InfoFieldList[1]});
  1503. }
  1504. if ($translabel!=$obj->{$InfoFieldList[1]}) {
  1505. $value=dol_trunc($translabel,18);
  1506. }else {
  1507. $value=$obj->{$InfoFieldList[1]};
  1508. }
  1509. }
  1510. }
  1511. else dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
  1512. }
  1513. elseif ($type == 'radio')
  1514. {
  1515. $value=$param['options'][$value];
  1516. }
  1517. elseif ($type == 'checkbox')
  1518. {
  1519. $value_arr=explode(',',$value);
  1520. $value='';
  1521. $toprint=array();
  1522. if (is_array($value_arr))
  1523. {
  1524. foreach ($value_arr as $keyval=>$valueval) {
  1525. $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$param['options'][$valueval].'</li>';
  1526. }
  1527. }
  1528. $value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
  1529. }
  1530. elseif ($type == 'chkbxlst')
  1531. {
  1532. $value_arr = explode(',', $value);
  1533. $param_list = array_keys($param['options']);
  1534. $InfoFieldList = explode(":", $param_list[0]);
  1535. $selectkey = "rowid";
  1536. $keyList = 'rowid';
  1537. if (count($InfoFieldList) >= 3) {
  1538. $selectkey = $InfoFieldList[2];
  1539. $keyList = $InfoFieldList[2] . ' as rowid';
  1540. }
  1541. $fields_label = explode('|', $InfoFieldList[1]);
  1542. if (is_array($fields_label)) {
  1543. $keyList .= ', ';
  1544. $keyList .= implode(', ', $fields_label);
  1545. }
  1546. $sql = 'SELECT ' . $keyList;
  1547. $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
  1548. if (strpos($InfoFieldList[4], 'extra') !== false) {
  1549. $sql .= ' as main';
  1550. }
  1551. // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
  1552. // $sql.= ' AND entity = '.$conf->entity;
  1553. dol_syslog(get_class($this) . ':showOutputField:$type=chkbxlst',LOG_DEBUG);
  1554. $resql = $this->db->query($sql);
  1555. if ($resql) {
  1556. $value = ''; // value was used, so now we reste it to use it to build final output
  1557. $toprint=array();
  1558. while ( $obj = $this->db->fetch_object($resql) ) {
  1559. // Several field into label (eq table:code|libelle:rowid)
  1560. $fields_label = explode('|', $InfoFieldList[1]);
  1561. if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
  1562. if (is_array($fields_label) && count($fields_label) > 1) {
  1563. foreach ( $fields_label as $field_toshow ) {
  1564. $translabel = '';
  1565. if (! empty($obj->$field_toshow)) {
  1566. $translabel = $langs->trans($obj->$field_toshow);
  1567. }
  1568. if ($translabel != $field_toshow) {
  1569. $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>';
  1570. } else {
  1571. $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->$field_toshow.'</li>';
  1572. }
  1573. }
  1574. } else {
  1575. $translabel = '';
  1576. if (! empty($obj->{$InfoFieldList[1]})) {
  1577. $translabel = $langs->trans($obj->{$InfoFieldList[1]});
  1578. }
  1579. if ($translabel != $obj->{$InfoFieldList[1]}) {
  1580. $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>';
  1581. } else {
  1582. $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->{$InfoFieldList[1]}.'</li>';
  1583. }
  1584. }
  1585. }
  1586. }
  1587. $value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
  1588. } else {
  1589. dol_syslog(get_class($this) . '::showOutputField error ' . $this->db->lasterror(), LOG_WARNING);
  1590. }
  1591. }
  1592. elseif ($type == 'link')
  1593. {
  1594. $out='';
  1595. // Only if something to display (perf)
  1596. if ($value) // If we have -1 here, pb is into sert, not into ouptu
  1597. {
  1598. $param_list=array_keys($param['options']); // $param_list='ObjectName:classPath'
  1599. $InfoFieldList = explode(":", $param_list[0]);
  1600. $classname=$InfoFieldList[0];
  1601. $classpath=$InfoFieldList[1];
  1602. if (! empty($classpath))
  1603. {
  1604. dol_include_once($InfoFieldList[1]);
  1605. if ($classname && class_exists($classname))
  1606. {
  1607. $object = new $classname($this->db);
  1608. $object->fetch($value);
  1609. $value=$object->getNomUrl(3);
  1610. }
  1611. }
  1612. else
  1613. {
  1614. dol_syslog('Error bad setup of extrafield', LOG_WARNING);
  1615. return 'Error bad setup of extrafield';
  1616. }
  1617. }
  1618. }
  1619. elseif ($type == 'text')
  1620. {
  1621. $value=dol_htmlentitiesbr($value);
  1622. }
  1623. elseif ($type == 'html')
  1624. {
  1625. $value=dol_htmlentitiesbr($value);
  1626. }
  1627. elseif ($type == 'password')
  1628. {
  1629. $value=dol_trunc(preg_replace('/./i','*',$value), 8, 'right', 'UTF-8', 1);
  1630. }
  1631. else
  1632. {
  1633. $showsize=round($size);
  1634. if ($showsize > 48) $showsize=48;
  1635. }
  1636. //print $type.'-'.$size;
  1637. $out=$value;
  1638. return $out;
  1639. }
  1640. /**
  1641. * Return tag to describe alignement to use for this extrafield
  1642. *
  1643. * @param string $key Key of attribute
  1644. * @param string $extrafieldsobjectkey If defined, use the new method to get extrafields data
  1645. * @return string Formated value
  1646. */
  1647. function getAlignFlag($key, $extrafieldsobjectkey='')
  1648. {
  1649. global $conf,$langs;
  1650. if (! empty($extrafieldsobjectkey)) $type=$this->attributes[$extrafieldsobjectkey]['type'][$key];
  1651. else $type=$this->attribute_type[$key];
  1652. $align='';
  1653. if ($type == 'date')
  1654. {
  1655. $align="center";
  1656. }
  1657. elseif ($type == 'datetime')
  1658. {
  1659. $align="center";
  1660. }
  1661. elseif ($type == 'int')
  1662. {
  1663. $align="right";
  1664. }
  1665. elseif ($type == 'double')
  1666. {
  1667. $align="right";
  1668. }
  1669. elseif ($type == 'boolean')
  1670. {
  1671. $align="center";
  1672. }
  1673. elseif ($type == 'radio')
  1674. {
  1675. $align="center";
  1676. }
  1677. elseif ($type == 'checkbox')
  1678. {
  1679. $align="center";
  1680. }
  1681. elseif ($type == 'price')
  1682. {
  1683. $align="right";
  1684. }
  1685. return $align;
  1686. }
  1687. /**
  1688. * Return HTML string to print separator extrafield
  1689. *
  1690. * @param string $key Key of attribute
  1691. * @param string $object Object
  1692. * @return string HTML code with line for separator
  1693. */
  1694. function showSeparator($key, $object)
  1695. {
  1696. global $langs;
  1697. $out = '<tr class="trextrafieldseparator trextrafieldseparator'.$key.'"><td colspan="2"><strong>';
  1698. $out.= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
  1699. $out.= '</strong></td></tr>';
  1700. return $out;
  1701. }
  1702. /**
  1703. * Fill array_options property of object by extrafields value (using for data sent by forms)
  1704. *
  1705. * @param array $extralabels $array of extrafields (@deprecated)
  1706. * @param object $object Object
  1707. * @param string $onlykey Only following key is filled. When we make update of only one extrafield ($action = 'update_extras'), calling page must must set this to avoid to have other extrafields being reset.
  1708. * @return int 1 if array_options set, 0 if no value, -1 if error (field required missing for example)
  1709. */
  1710. function setOptionalsFromPost($extralabels, &$object, $onlykey='')
  1711. {
  1712. global $_POST, $langs;
  1713. $nofillrequired='';// For error when required field left blank
  1714. $error_field_required = array();
  1715. if (is_array($this->attributes[$object->table_element]['label'])) $extralabels=$this->attributes[$object->table_element]['label'];
  1716. if (is_array($extralabels))
  1717. {
  1718. // Get extra fields
  1719. foreach ($extralabels as $key => $value)
  1720. {
  1721. if (! empty($onlykey) && $key != $onlykey) continue;
  1722. $key_type = $this->attributes[$object->table_element]['type'][$key];
  1723. if ($key_type == 'separate') continue;
  1724. $enabled = 1;
  1725. if (isset($this->attributes[$object->table_element]['list'][$key]))
  1726. {
  1727. $enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1);
  1728. }
  1729. $perms = 1;
  1730. if (isset($this->attributes[$object->table_element]['perms'][$key]))
  1731. {
  1732. $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1);
  1733. }
  1734. if (empty($enabled)) continue;
  1735. if (empty($perms)) continue;
  1736. if ($this->attributes[$object->table_element]['required'][$key]) // Value is required
  1737. {
  1738. // Check if empty without using GETPOST, value can be alpha, int, array, etc...
  1739. if ((! is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $_POST["options_".$key] != '0')
  1740. || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key])))
  1741. {
  1742. //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
  1743. $nofillrequired++;
  1744. $error_field_required[] = $langs->transnoentitiesnoconv($value);
  1745. }
  1746. }
  1747. if (in_array($key_type,array('date')))
  1748. {
  1749. // Clean parameters
  1750. // TODO GMT date in memory must be GMT so we should add gm=true in parameters
  1751. $value_key=dol_mktime(0, 0, 0, $_POST["options_".$key."month"], $_POST["options_".$key."day"], $_POST["options_".$key."year"]);
  1752. }
  1753. elseif (in_array($key_type,array('datetime')))
  1754. {
  1755. // Clean parameters
  1756. // TODO GMT date in memory must be GMT so we should add gm=true in parameters
  1757. $value_key=dol_mktime($_POST["options_".$key."hour"], $_POST["options_".$key."min"], 0, $_POST["options_".$key."month"], $_POST["options_".$key."day"], $_POST["options_".$key."year"]);
  1758. }
  1759. else if (in_array($key_type,array('checkbox','chkbxlst')))
  1760. {
  1761. $value_arr=GETPOST("options_".$key, 'array'); // check if an array
  1762. if (!empty($value_arr)) {
  1763. $value_key=implode($value_arr,',');
  1764. }else {
  1765. $value_key='';
  1766. }
  1767. }
  1768. else if (in_array($key_type,array('price','double')))
  1769. {
  1770. $value_arr=GETPOST("options_".$key, 'alpha');
  1771. $value_key=price2num($value_arr);
  1772. }
  1773. else
  1774. {
  1775. $value_key=GETPOST("options_".$key);
  1776. }
  1777. $object->array_options["options_".$key]=$value_key;
  1778. }
  1779. if ($nofillrequired) {
  1780. $langs->load('errors');
  1781. setEventMessages($langs->trans('ErrorFieldsRequired').' : '.implode(', ',$error_field_required), null, 'errors');
  1782. return -1;
  1783. }
  1784. else {
  1785. return 1;
  1786. }
  1787. }
  1788. else {
  1789. return 0;
  1790. }
  1791. }
  1792. /**
  1793. * return array_options array of data of extrafields value of object sent by a search form
  1794. *
  1795. * @param array|string $extrafieldsobjectkey array of extrafields (old usage) or value of object->table_element (new usage)
  1796. * @param string $keyprefix Prefix string to add into name and id of field (can be used to avoid duplicate names)
  1797. * @param string $keysuffix Suffix string to add into name and id of field (can be used to avoid duplicate names)
  1798. * @return array|int array_options set or 0 if no value
  1799. */
  1800. function getOptionalsFromPost($extrafieldsobjectkey, $keyprefix='', $keysuffix='')
  1801. {
  1802. global $_POST;
  1803. if (is_string($extrafieldsobjectkey) && is_array($this->attributes[$extrafieldsobjectkey]['label']))
  1804. {
  1805. $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
  1806. }
  1807. else
  1808. {
  1809. $extralabels = $extrafieldsobjectkey;
  1810. }
  1811. if (is_array($extralabels))
  1812. {
  1813. $array_options = array();
  1814. // Get extra fields
  1815. foreach ($extralabels as $key => $value)
  1816. {
  1817. $key_type = '';
  1818. if (is_string($extrafieldsobjectkey))
  1819. {
  1820. $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
  1821. }
  1822. if (in_array($key_type,array('date','datetime')))
  1823. {
  1824. // Clean parameters
  1825. $value_key=dol_mktime($_POST[$keysuffix."options_".$key.$keyprefix."hour"], $_POST[$keysuffix."options_".$key.$keyprefix."min"], 0, $_POST[$keysuffix."options_".$key.$keyprefix."month"], $_POST[$keysuffix."options_".$key.$keyprefix."day"], $_POST[$keysuffix."options_".$key.$keyprefix."year"]);
  1826. }
  1827. else if (in_array($key_type,array('checkbox', 'chkbxlst')))
  1828. {
  1829. $value_arr=GETPOST($keysuffix."options_".$key.$keyprefix);
  1830. // Make sure we get an array even if there's only one checkbox
  1831. $value_arr=(array) $value_arr;
  1832. $value_key=implode(',', $value_arr);
  1833. }
  1834. else if (in_array($key_type,array('price','double')))
  1835. {
  1836. $value_arr=GETPOST($keysuffix."options_".$key.$keyprefix);
  1837. $value_key=price2num($value_arr);
  1838. }
  1839. else
  1840. {
  1841. $value_key=GETPOST($keysuffix."options_".$key.$keyprefix);
  1842. }
  1843. $array_options[$keysuffix."options_".$key]=$value_key; // No keyprefix here. keyprefix is used only for read.
  1844. }
  1845. return $array_options;
  1846. }
  1847. return 0;
  1848. }
  1849. }