dao_multicompany.class.php 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. <?php
  2. /* Copyright (C) 2009-2023 Regis Houssin <regis.houssin@inodbox.com>
  3. * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. /**
  20. * \file /multicompany/dao_multicompany.class.php
  21. * \ingroup multicompany
  22. * \brief File Class multicompany
  23. */
  24. require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
  25. require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
  26. /**
  27. * \class DaoMulticompany
  28. * \brief Class of the module multicompany
  29. */
  30. class DaoMulticompany extends CommonObject
  31. {
  32. public $element = 'entity'; // !< Id that identify managed objects
  33. public $table_element = 'entity'; // !< Name of table without prefix where object is stored
  34. public $id;
  35. public $label;
  36. public $description;
  37. public $address;
  38. public $zip;
  39. public $town;
  40. public $currency_code;
  41. public $language_code;
  42. public $options=array();
  43. public $options_json;
  44. public $entity=array();
  45. public $entities=array();
  46. public $fk_tables=array();
  47. public $visible;
  48. public $active;
  49. public $currency;
  50. public $language;
  51. /**
  52. * Constructor
  53. *
  54. * @param DoliDB $db Database handler
  55. */
  56. public function __construct($db)
  57. {
  58. $this->db = $db;
  59. $this->fk_tables = array(
  60. 'societe' => array(
  61. 'key' => 'fk_soc',
  62. 'childs' => array(
  63. 'societe_address',
  64. 'societe_commerciaux',
  65. 'societe_log',
  66. 'societe_prices',
  67. 'societe_remise',
  68. 'societe_remise_except',
  69. 'societe_rib',
  70. 'socpeople'
  71. )
  72. ),
  73. 'product' => array(
  74. 'key' => 'fk_product',
  75. 'childs' => array(
  76. 'product_ca',
  77. 'product_lang',
  78. 'product_price',
  79. 'product_stock',
  80. 'product_fournisseur_price' => array(
  81. 'key' => 'fk_product_fournisseur',
  82. 'childs' => array('product_fournisseur_price_log')
  83. ),
  84. )
  85. ),
  86. 'projet' => array(
  87. 'key' => 'fk_projet',
  88. 'childs' => array(
  89. 'projet_task' => array(
  90. 'key' => 'fk_task',
  91. 'childs' => array('projet_task_time')
  92. )
  93. )
  94. )
  95. );
  96. }
  97. /**
  98. * Fetch entity
  99. *
  100. * @param int $id
  101. * @return int
  102. */
  103. public function fetch($id)
  104. {
  105. global $user;
  106. //clearCache('mc_entity_' . $id); // for debug only!
  107. if ($cache = getCache('mc_entity_' . $id)) {
  108. foreach ($cache as $key => $value) {
  109. $this->$key = $value;
  110. }
  111. } else {
  112. $sql = "SELECT rowid, label, description, options, visible, active";
  113. $sql.= " FROM ".MAIN_DB_PREFIX."entity";
  114. $sql.= " WHERE rowid = ".$id;
  115. $resql = $this->db->query($sql);
  116. if (!empty($resql)) {
  117. if ($this->db->num_rows($resql)) {
  118. $obj = $this->db->fetch_object($resql);
  119. $this->id = $obj->rowid;
  120. $this->label = $obj->label;
  121. $this->description = $obj->description;
  122. $this->options = (!empty($obj->options) ? json_decode($obj->options, true) : array());
  123. $this->visible = $obj->visible;
  124. $this->active = $obj->active;
  125. $this->fetch_optionals();
  126. $cache = array(
  127. 'id' => $this->id,
  128. 'label' => $this->label,
  129. 'description' => $this->description,
  130. 'options' => $this->options,
  131. 'visible' => $this->visible,
  132. 'active' => $this->active,
  133. 'array_options' => $this->array_options
  134. );
  135. setCache('mc_entity_' . $this->id, $cache);
  136. } else {
  137. $this->error .= $this->db->lasterror();
  138. return -2;
  139. }
  140. $this->db->free($resql);
  141. } else {
  142. $this->error .= $this->db->lasterror();
  143. return -3;
  144. }
  145. }
  146. if (!empty($user->login)) {
  147. $this->getConstants();
  148. }
  149. return 1;
  150. }
  151. /**
  152. * Create entity
  153. *
  154. * @param User $user Object of user that ask creation
  155. * @param int $call_trigger false = no, true = yes
  156. * @return int >= 0 if OK, < 0 if KO
  157. */
  158. public function create(User $user, $call_trigger = true)
  159. {
  160. global $conf;
  161. $error=0;
  162. // Clean parameters
  163. $this->label = trim($this->label);
  164. $this->description = trim($this->description);
  165. $this->options_json = json_encode($this->options);
  166. dol_syslog(get_class($this)."::create ".$this->label);
  167. $this->db->begin();
  168. $now=dol_now();
  169. $sql = "INSERT INTO ".MAIN_DB_PREFIX."entity (";
  170. $sql.= "label";
  171. $sql.= ", description";
  172. $sql.= ", datec";
  173. $sql.= ", fk_user_creat";
  174. $sql.= ", options";
  175. $sql.= ", visible";
  176. $sql.= ", active";
  177. $sql.= ") VALUES (";
  178. $sql.= "'".$this->db->escape($this->label)."'";
  179. $sql.= ", '".$this->db->escape($this->description)."'";
  180. $sql.= ", '".$this->db->idate($now)."'";
  181. $sql.= ", ".$user->id;
  182. $sql.= ", '".$this->db->escape($this->options_json)."'";
  183. $sql.= ", ".(!empty($this->visible)?$this->db->escape($this->visible):0);
  184. $sql.= ", ".(!empty($this->active)?$this->db->escape($this->active):0);
  185. $sql.= ")";
  186. dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG);
  187. $resql = $this->db->query($sql);
  188. if (!empty($resql)) {
  189. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."entity");
  190. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
  191. $result = $this->insertExtraFields();
  192. if ($result < 0) {
  193. $error ++;
  194. }
  195. }
  196. dol_syslog(get_class($this)."::Create success id=".$this->id);
  197. } else {
  198. $error++;
  199. }
  200. if (empty($error) && $call_trigger) {
  201. // Call trigger
  202. $result = $this->call_trigger('MULTICOMPANY_CREATE', $user);
  203. if ($result < 0) $error++;
  204. // End call triggers
  205. }
  206. if (empty($error)) {
  207. $this->db->commit();
  208. return $this->id;
  209. } else {
  210. $this->error .= $this->db->lasterror();
  211. dol_syslog(get_class($this)."::Create echec ".$this->error);
  212. $this->db->rollback();
  213. return -1;
  214. }
  215. }
  216. /**
  217. * Update entity
  218. *
  219. * @param int $id Id of entity (deprecated, use 0 here and call update on an object loaded by a fetch)
  220. * @param User $user User who requests the update
  221. * @param int $call_trigger false = no, true = yes
  222. * @return int <0 if KO, >=0 if OK
  223. */
  224. public function update($id, User $user, $call_trigger = true)
  225. {
  226. global $conf;
  227. $error=0;
  228. if (empty($id)) {
  229. $id = $this->id;
  230. }
  231. // Clean parameters
  232. $this->label = trim($this->label);
  233. $this->description = trim($this->description);
  234. $this->options_json = json_encode($this->options);
  235. dol_syslog(get_class($this)."::update id=".$id." label=".$this->label);
  236. $this->db->begin();
  237. $sql = "UPDATE ".MAIN_DB_PREFIX."entity SET";
  238. $sql.= " label = '" . $this->db->escape($this->label) ."'";
  239. $sql.= ", description = '" . $this->db->escape($this->description) ."'";
  240. $sql.= ", options = '" . $this->db->escape($this->options_json) ."'";
  241. $sql.= " WHERE rowid = " . $id;
  242. dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG);
  243. $resql = $this->db->query($sql);
  244. if (!empty($resql)) {
  245. dol_syslog(get_class($this)."::Update success id=".$id);
  246. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
  247. $result = $this->insertExtraFields();
  248. if ($result < 0) {
  249. $error ++;
  250. }
  251. }
  252. } else {
  253. $error++;
  254. }
  255. if (empty($error) && $call_trigger) {
  256. // Call trigger
  257. $result = $this->call_trigger('MULTICOMPANY_MODIFY', $user);
  258. if ($result < 0) $error++;
  259. // End call triggers
  260. }
  261. if (empty($error)) {
  262. $this->db->commit();
  263. clearCache('mc_entity_' . $id);
  264. clearCache('mc_constants_' . $id);
  265. return 1;
  266. } else {
  267. $this->error .= $this->db->lasterror();
  268. dol_syslog(get_class($this)."::Update echec ".$this->error, LOG_ERR);
  269. $this->db->rollback();
  270. return -1;
  271. }
  272. }
  273. /**
  274. * Delete entity
  275. *
  276. * @param int $id Id of entity to delete
  277. * @param int $call_trigger false = no, true = yes
  278. * @return int <0 if KO, >0 if OK
  279. */
  280. public function delete($id, $call_trigger = true)
  281. {
  282. global $user;
  283. $error=0;
  284. $this->db->begin();
  285. if (empty($error) && !empty($call_trigger)) {
  286. // Call trigger
  287. $result = $this->call_trigger('MULTICOMPANY_DELETE', $user);
  288. if ($result < 0) $error++;
  289. // End call triggers
  290. }
  291. if (empty($error)) {
  292. $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
  293. $sql.= " WHERE entity = " . $id;
  294. dol_syslog(get_class($this)."::Delete sql=".$sql, LOG_DEBUG);
  295. if ($this->db->query($sql)) {
  296. // TODO remove records of all tables
  297. } else {
  298. $error++;
  299. $this->error .= $this->db->lasterror();
  300. dol_syslog(get_class($this)."::Delete erreur -1 ".$this->error, LOG_ERR);
  301. }
  302. }
  303. // Removed extrafields
  304. if (empty($error)) {
  305. $result = $this->deleteExtraFields();
  306. if ($result < 0) {
  307. $error++;
  308. dol_syslog(get_class($this)."::delete error -2 ".$this->error, LOG_ERR);
  309. }
  310. }
  311. if (empty($error)) {
  312. $sql = "DELETE FROM ".MAIN_DB_PREFIX."entity";
  313. $sql.= " WHERE rowid = " . $id;
  314. dol_syslog(get_class($this)."::Delete sql=".$sql, LOG_DEBUG);
  315. if (!$this->db->query($sql)) {
  316. $error++;
  317. $this->error .= $this->db->lasterror();
  318. dol_syslog(get_class($this)."::Delete erreur -1 ".$this->error, LOG_ERR);
  319. }
  320. }
  321. if (empty($error)) {
  322. dol_syslog(get_class($this)."::Delete success id=".$id);
  323. $this->db->commit();
  324. clearCache('mc_entity_' . $id);
  325. clearCache('mc_constants_' . $id);
  326. return 1;
  327. } else {
  328. dol_syslog(get_class($this)."::Delete echec ".$this->error);
  329. $this->db->rollback();
  330. return -1;
  331. }
  332. }
  333. /**
  334. *
  335. *
  336. */
  337. public function getConstants()
  338. {
  339. // Unset when use multifetching
  340. unset($this->country_id);
  341. unset($this->country_code);
  342. unset($this->currency_code);
  343. unset($this->language_code);
  344. unset($this->name);
  345. unset($this->zip);
  346. unset($this->address);
  347. unset($this->town);
  348. unset($this->state_id);
  349. $key = 'mc_constants_' . $this->id;
  350. //clearCache('mc_constants_' . $this->id); // for debug only!
  351. if ($cache = getCache($key)) {
  352. foreach ($cache as $key => $value) {
  353. $this->$key = $value;
  354. }
  355. } else {
  356. $cache=array();
  357. $sql = "SELECT ";
  358. $sql.= $this->db->decrypt('name')." as name";
  359. $sql.= ", ".$this->db->decrypt('value')." as value";
  360. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  361. $sql.= " WHERE entity = ".$this->id;
  362. $sql.= " AND ".$this->db->decrypt('name')." LIKE 'MAIN_%'";
  363. $resql = $this->db->query($sql);
  364. if (!empty($resql)) {
  365. $num=$this->db->num_rows($resql);
  366. $i=0;
  367. while ($i < $num) {
  368. $obj = $this->db->fetch_object($resql);
  369. if ($obj->name === 'MAIN_INFO_SOCIETE_COUNTRY') {
  370. $tmp = explode(':', $obj->value);
  371. $this->country_id = $tmp[0];
  372. $cache['country_id'] = $this->country_id;
  373. $this->country_code = $tmp[1];
  374. $cache['country_code'] = $this->country_code;
  375. } else if ($obj->name === 'MAIN_MONNAIE') {
  376. $this->currency_code = $obj->value;
  377. $cache['currency_code'] = $this->currency_code;
  378. } else if ($obj->name === 'MAIN_LANG_DEFAULT') {
  379. $this->language_code = $obj->value;
  380. $cache['language_code'] = $this->language_code;
  381. } else if ($obj->name === 'MAIN_INFO_SOCIETE_NOM') {
  382. $this->name = $obj->value;
  383. $cache['name'] = $this->name;
  384. } else if ($obj->name === 'MAIN_INFO_SOCIETE_ZIP') {
  385. $this->zip = $obj->value;
  386. $cache['zip'] = $this->zip;
  387. } else if ($obj->name === 'MAIN_INFO_SOCIETE_ADDRESS') {
  388. $this->address = $obj->value;
  389. $cache['address'] = $this->address;
  390. } else if ($obj->name === 'MAIN_INFO_SOCIETE_TOWN') {
  391. $this->town = $obj->value;
  392. $cache['town'] = $this->town;
  393. } else if ($obj->name === 'MAIN_INFO_SOCIETE_STATE') {
  394. $this->state_id = $obj->value;
  395. $cache['state_id'] = $this->state_id;
  396. }
  397. $constname = $obj->name;
  398. $this->$constname = $obj->value;
  399. $cache[$constname] = $this->$constname;
  400. $i++;
  401. }
  402. setCache($key, $cache);
  403. $this->db->free($resql);
  404. } else {
  405. return -1;
  406. }
  407. }
  408. return 1;
  409. }
  410. /**
  411. * Remove all records of an entity
  412. *
  413. * @param int $id Entity id
  414. * @return int
  415. */
  416. private function deleteEntityRecords($id)
  417. {
  418. $error=1;
  419. $this->db->begin();
  420. $tables = $this->db->DDLListTables($this->db->database_name);
  421. if (is_array($tables) && !empty($tables)) {
  422. foreach($tables as $table) {
  423. $fields = $this->db->DDLInfoTable($table);
  424. foreach ($fields as $field) {
  425. if (is_array($field) && in_array('entity', $field)) {
  426. $tablewithoutprefix = str_replace(MAIN_DB_PREFIX, '', $table);
  427. $objIds = $this->getIdByForeignKey($tablewithoutprefix, $id);
  428. if (!empty($objIds)) {
  429. if (array_key_exists($tablewithoutprefix, $this->fk_tables)) {
  430. // Level 0
  431. $foreignKey = $this->fk_tables[$tablewithoutprefix]['key'];
  432. foreach($this->fk_tables[$tablewithoutprefix]['childs'] as $childTable => $child) {
  433. // Level 1
  434. if (!is_int($childTable) && is_array($child)) {
  435. echo 'childTableLevel1='.$childTable.'<br>';
  436. $objLevel1Ids = array();
  437. foreach($objIds as $rowid) {
  438. $ret = $this->getIdByForeignKey($childTable, $rowid, $foreignKey);
  439. if (!empty($ret)){
  440. $objLevel1Ids = array_merge($objLevel1Ids, $ret);
  441. }
  442. }
  443. sort($objLevel1Ids);
  444. //var_dump($objLevel1Ids);
  445. // Level 2
  446. foreach($child['childs'] as $childLevel2) {
  447. echo 'childTableLevel2='.$childLevel2.'<br>';
  448. foreach($objLevel1Ids as $rowid) {
  449. $sql = "DELETE FROM " . MAIN_DB_PREFIX . $childLevel2;
  450. $sql.= " WHERE " . $child['key'] . " = " . $rowid;
  451. //echo $sql.'<br>';
  452. //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG);
  453. /*if (!$this->db->query($sql)) {
  454. $error++;
  455. $this->error .= $this->db->lasterror();
  456. dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR);
  457. }*/
  458. }
  459. }
  460. foreach($objIds as $rowid) {
  461. $sql = "DELETE FROM " . MAIN_DB_PREFIX . $childTable;
  462. $sql.= " WHERE " . $foreignKey . " = " . $rowid;
  463. //echo $sql.'<br>';
  464. //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG);
  465. /*if (!$this->db->query($sql)) {
  466. $error++;
  467. $this->error .= $this->db->lasterror();
  468. dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR);
  469. }*/
  470. }
  471. } else {
  472. foreach($objIds as $rowid) {
  473. $sql = "DELETE FROM " . MAIN_DB_PREFIX . $child;
  474. $sql.= " WHERE " . $foreignKey . " = " . $rowid;
  475. //echo $sql.'<br>';
  476. //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG);
  477. /*if (!$this->db->query($sql)) {
  478. $error++;
  479. $this->error .= $this->db->lasterror();
  480. dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR);
  481. }*/
  482. }
  483. }
  484. }
  485. echo 'with childs = '.$table.'<br>';
  486. } else {
  487. echo 'without childs = '.$table.'<br>';
  488. }
  489. }
  490. }
  491. }
  492. }
  493. if (empty($error)) {
  494. dol_syslog(get_class($this)."::deleteEntityRecords success entity=".$id);
  495. $this->db->commit();
  496. return 1;
  497. } else {
  498. dol_syslog(get_class($this)."::deleteEntityRecords echec ".$this->error);
  499. $this->db->rollback();
  500. return -1;
  501. }
  502. }
  503. return 0;
  504. }
  505. /**
  506. * Get all rowid from a table by couple foreign key / id
  507. *
  508. * @param string $table
  509. * @param int $id
  510. * @param string $foreignkey
  511. * @param string $fieldname
  512. * @return int[]
  513. */
  514. private function getIdByForeignKey($table, $id, $foreignkey = 'entity', $fieldname = 'rowid')
  515. {
  516. $objIds=array();
  517. $foreignkey = (!empty($foreignkey) ? $foreignkey : 'entity');
  518. $fieldname = (!empty($fieldname) ? $fieldname : 'rowid');
  519. $sql = "SELECT " . $fieldname . " FROM " . MAIN_DB_PREFIX . $table;
  520. $sql.= " WHERE " . $foreignkey . " = " . $id;
  521. //echo $sql.'<br>';
  522. $resql = $this->db->query($sql);
  523. if (!empty($resql)) {
  524. $i = 0;
  525. $num = $this->db->num_rows($resql);
  526. while ($i < $num) {
  527. $obj = $this->db->fetch_object($resql);
  528. $objIds[] = $obj->$fieldname;
  529. $i++;
  530. }
  531. $this->db->free($resql);
  532. } else {
  533. $this->error = $this->db->lasterror();
  534. return -1;
  535. }
  536. return $objIds;
  537. }
  538. /**
  539. * Set status of an entity
  540. *
  541. * @param int $id Id of entity
  542. * @param string $type Type of status (visible or active)
  543. * @param string $value Value of status (0: disable, 1: enable)
  544. * @return int
  545. */
  546. public function setEntity($id, $type='active', $value)
  547. {
  548. $this->db->begin();
  549. $sql = "UPDATE ".MAIN_DB_PREFIX."entity";
  550. $sql.= " SET " . $this->db->escape($type) . " = " . (int) $value;
  551. $sql.= " WHERE rowid = " . (int) $id;
  552. dol_syslog(get_class($this)."::setEntity sql=".$sql, LOG_DEBUG);
  553. $resql = $this->db->query($sql);
  554. if (!empty($resql)) {
  555. $this->db->commit();
  556. clearCache($id);
  557. return 1;
  558. } else {
  559. $this->error = $this->db->lasterror();
  560. $this->db->rollback();
  561. return -1;
  562. }
  563. }
  564. /**
  565. * List of entities
  566. *
  567. * @param int $login If use in login page or not
  568. * @param array $exclude Entity ids to exclude
  569. * @param bool $onlyactive sort only active entities
  570. * @param bool $onlyvisible sort only visible entities
  571. * @param int $onlyids Return only ids of objects (consume less memory)
  572. * @return void
  573. */
  574. public function getEntities($login = false, $exclude = false, $onlyactive = false, $onlyvisible = false, $onlyids = false)
  575. {
  576. global $conf, $user;
  577. $this->entities=array();
  578. if (!empty($login) || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) || (!empty($user->admin) && empty($user->entity))) {
  579. $sql = "SELECT DISTINCT(rowid), rang"; // Distinct parce que si user dans plusieurs groupes d'une entité, la liste d'entités de la petite terre affiche plusieurs fois la même entité
  580. $sql.= " FROM ".MAIN_DB_PREFIX."entity";
  581. if (!empty($user->admin) && empty($user->entity) && is_array($exclude) && !empty($exclude)) {
  582. $exclude = implode(",", $exclude);
  583. $sql.= " WHERE rowid NOT IN (" . $exclude .")";
  584. if (!empty($onlyactive)) {
  585. $sql.= " AND active = 1";
  586. }
  587. } elseif (!empty($onlyactive)) {
  588. $sql.= " WHERE active = 1";
  589. }
  590. if (!empty($onlyvisible)) {
  591. $sql.= " AND visible = 1";
  592. }
  593. if (empty($login)) {
  594. $sql.= " ORDER BY rowid";
  595. } else {
  596. $sql.= " ORDER BY rang ASC, rowid ASC";
  597. }
  598. } else {
  599. $sql = "SELECT DISTINCT(entity) as rowid"; // Distinct parce que si user dans plusieurs groupes d'une entité, la liste d'entités de la petite terre affiche plusieurs fois la même entité
  600. $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user";
  601. $sql.= " WHERE fk_user = ".$user->id;
  602. $sql.= " ORDER BY entity";
  603. }
  604. $resql = $this->db->query($sql);
  605. if (!empty($resql)) {
  606. $num = $this->db->num_rows($resql);
  607. $i = 0;
  608. while ($i < $num) {
  609. $obj = $this->db->fetch_object($resql);
  610. if (empty($onlyids)) {
  611. $objectstatic = new self($this->db);
  612. $ret = $objectstatic->fetch($obj->rowid);
  613. $this->entities[$i] = $objectstatic;
  614. } else {
  615. $this->entities[$i] = $obj->rowid;
  616. }
  617. $i++;
  618. }
  619. $this->db->free($resql);
  620. return 1;
  621. } else {
  622. $this->error = $this->db->lasterror();
  623. return -1;
  624. }
  625. }
  626. /**
  627. * Check user $userid belongs to at least one group created into entity $id
  628. *
  629. * @param int $entity
  630. * @param int $userid
  631. * @return int
  632. */
  633. public function verifyRight($entity, $userid)
  634. {
  635. global $conf;
  636. $tmpuser=new User($this->db);
  637. $tmpuser->fetch($userid);
  638. //$tmpuser->fetch($userid, '', '',0, $entity); // TODO check compatibility with DAV authentication
  639. if (!empty($tmpuser->id)) {
  640. if (empty($tmpuser->entity)) {
  641. return 1; // superadmin always allowed
  642. }
  643. if ($tmpuser->entity == $entity && $tmpuser->admin) {
  644. return 1; // entity admin allowed
  645. }
  646. if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
  647. if ($tmpuser->entity == $entity) {
  648. return 1; // user allowed if belong to entity
  649. }
  650. } else {
  651. $sql = "SELECT count(rowid) as nb";
  652. $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user";
  653. $sql.= " WHERE fk_user=".$userid;
  654. $sql.= " AND entity=".$entity;
  655. //echo $sql;
  656. dol_syslog(get_class($this)."::verifyRight sql=".$sql, LOG_DEBUG);
  657. $resql = $this->db->query($sql);
  658. if (!empty($resql)) {
  659. $obj = $this->db->fetch_object($resql);
  660. $this->db->free($resql);
  661. return $obj->nb; // user allowed if at least in one group
  662. } else {
  663. $this->error = $this->db->lasterror();
  664. return -1;
  665. }
  666. }
  667. }
  668. return 0;
  669. }
  670. /**
  671. * Get constants values of an entity
  672. *
  673. * @param int $entity Entity id
  674. * @param string $constname Specific contant
  675. * @return array Array of constants
  676. */
  677. public function getEntityConfig($entity, $constname=null)
  678. {
  679. $const=array();
  680. $sql = "SELECT ".$this->db->decrypt('value')." as value";
  681. $sql.= ", ".$this->db->decrypt('name')." as name";
  682. $sql.= " FROM ".MAIN_DB_PREFIX."const";
  683. $sql.= " WHERE entity = " . $entity;
  684. if (!empty($constname)) {
  685. if (preg_match('/\_\*$/', $constname)) {
  686. $constname = str_replace('*', '', $constname);
  687. $sql.= " AND ".$this->db->decrypt('name')." LIKE '" . $this->db->escape($constname) ."%'";
  688. } else {
  689. $sql.= " AND ".$this->db->decrypt('name')." = '" . $this->db->escape($constname) ."'";
  690. }
  691. }
  692. dol_syslog(get_class($this)."::getEntityConfig sql=".$sql, LOG_DEBUG);
  693. $resql = $this->db->query($sql);
  694. if (!empty($resql)) {
  695. $i = 0;
  696. $num = $this->db->num_rows($resql);
  697. while ($i < $num) {
  698. $obj = $this->db->fetch_object($resql);
  699. $const[$obj->name] = $obj->value;
  700. $i++;
  701. }
  702. $this->db->free($resql);
  703. } else {
  704. $this->error = $this->db->lasterror();
  705. return -1;
  706. }
  707. return $const;
  708. }
  709. /**
  710. * Get group rights by entity
  711. *
  712. * @param int $group
  713. * @param int $entity
  714. * @return array[]
  715. */
  716. public function getGroupRightsByEntity($group, $entity)
  717. {
  718. $permsgroupbyentity = array();
  719. $sql = "SELECT DISTINCT r.id, r.libelle, r.module, gr.entity";
  720. $sql.= " FROM ".MAIN_DB_PREFIX."rights_def as r,";
  721. $sql.= " ".MAIN_DB_PREFIX."usergroup_rights as gr";
  722. $sql.= " WHERE gr.fk_id = r.id";
  723. $sql.= " AND gr.entity = " . (int) $entity;
  724. $sql.= " AND gr.fk_usergroup = " . (int) $group;
  725. dol_syslog(get_class($this)."::getGroupRightsByEntity sql=".$sql, LOG_DEBUG);
  726. $resql = $this->db->query($sql);
  727. if (!empty($resql)) {
  728. $num = $this->db->num_rows($resql);
  729. $i = 0;
  730. while ($i < $num) {
  731. $obj = $this->db->fetch_object($resql);
  732. array_push($permsgroupbyentity, $obj->id);
  733. $i++;
  734. }
  735. $this->db->free($resql);
  736. return $permsgroupbyentity;
  737. } else {
  738. $this->error = $this->db->lasterror();
  739. return -1;
  740. }
  741. }
  742. /**
  743. * Get list of groups
  744. *
  745. * @return array
  746. */
  747. public function getListOfGroups()
  748. {
  749. $ret=array();
  750. $sql = "SELECT g.rowid";
  751. $sql.= " FROM ".MAIN_DB_PREFIX."usergroup as g";
  752. $sql.= " GROUP BY g.rowid";
  753. $resql = $this->db->query($sql);
  754. if ($resql) {
  755. while ($obj = $this->db->fetch_object($resql)) {
  756. $ret[] = $obj->rowid;
  757. }
  758. $this->db->free($resql);
  759. return $ret;
  760. } else {
  761. $this->error=$this->db->lasterror();
  762. return -1;
  763. }
  764. }
  765. /**
  766. *
  767. * @param unknown $groupid
  768. * @param unknown $template
  769. * @return User[]|number
  770. */
  771. public function getListOfUsersInGroupByTemplate($groupid, $template)
  772. {
  773. $ret=array();
  774. $sql = "SELECT u.rowid, ug.entity as usergroup_entity";
  775. $sql.= " FROM ".MAIN_DB_PREFIX."user as u";
  776. $sql.= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
  777. $sql.= " WHERE ug.fk_user = u.rowid";
  778. $sql.= " AND ug.fk_usergroup = " . (int) $groupid;
  779. $sql.= " AND ug.entity = " . (int) $template;
  780. dol_syslog(get_class($this)."::getListOfUsersInGroupByTemplate groupid=".$groupid." template=".$template, LOG_DEBUG);
  781. $resql = $this->db->query($sql);
  782. if ($resql) {
  783. while ($obj = $this->db->fetch_object($resql)) {
  784. if (!array_key_exists($obj->rowid, $ret)) {
  785. $newuser=new User($this->db);
  786. $newuser->fetch($obj->rowid);
  787. $ret[$obj->rowid]=$newuser;
  788. }
  789. }
  790. $this->db->free($resql);
  791. return $ret;
  792. } else {
  793. $this->error = $this->db->lasterror();
  794. return -1;
  795. }
  796. }
  797. /**
  798. *
  799. * @param string $element Name of element (thirdparty, product, ...)
  800. * @param int $element_id Id of current element for check sharing granularity (if empty, all element sharing records are deleted for once entity)
  801. * @param mixed $entity Array of sharing entities (create/update/delete) or integer of entity (delete entity)
  802. * @return bool
  803. *
  804. */
  805. public function setSharingsByElement($element, $element_id = null, $entity = null)
  806. {
  807. $error = 0;
  808. // For avoid to delete all elements
  809. if (empty($element_id) && !is_int($entity)) {
  810. dol_syslog(get_class($this)."::setSharingsByElement erreur -2 element_id are empty and entity is not an integer", LOG_ERR);
  811. return -2;
  812. }
  813. $this->db->begin();
  814. // Delete before create/update elements
  815. $sql = "DELETE FROM ".MAIN_DB_PREFIX."entity_element_sharing";
  816. $sql.= " WHERE element = '" . $this->db->sanitize($element) . "'";
  817. if (!empty($element_id)) {
  818. $sql.= " AND fk_element = " . (int) $element_id;
  819. } elseif (is_int($entity) && $entity > 0) {
  820. $sql.= " AND entity = " . (int) $entity;
  821. }
  822. dol_syslog(get_class($this)."::setSharingsByElement delete sql=".$sql, LOG_DEBUG);
  823. if (!$this->db->query($sql)) {
  824. $error++;
  825. }
  826. if (empty($error) && !empty($element_id) && is_array($entity) && !empty($entity)) {
  827. foreach($entity as $sharedwithentity) {
  828. dol_syslog(get_class($this)."::setSharingsByElement create element=".$element." fk_element=".$element_id." sharedwithentity=".$sharedwithentity);
  829. $sql = "INSERT INTO ".MAIN_DB_PREFIX."entity_element_sharing (";
  830. $sql.= "entity";
  831. $sql.= ", element";
  832. $sql.= ", fk_element";
  833. $sql.= ") VALUES (";
  834. $sql.= (int) $sharedwithentity;
  835. $sql.= ", '".$this->db->escape($element)."'";
  836. $sql.= ", ". (int) $element_id;
  837. $sql.= ")";
  838. dol_syslog(get_class($this)."::setSharingsByElement create sql=".$sql, LOG_DEBUG);
  839. $resql = $this->db->query($sql);
  840. if (!empty($resql)) {
  841. dol_syslog(get_class($this)."::setSharingsByElement create success id=" . $this->db->last_insert_id(MAIN_DB_PREFIX."entity_element_sharing"));
  842. } else {
  843. $error++;
  844. break;
  845. }
  846. }
  847. }
  848. if (empty($error)) {
  849. dol_syslog(get_class($this)."::setSharingsByElement success");
  850. $this->db->commit();
  851. return 1;
  852. } else {
  853. $this->error.= $this->db->lasterror();
  854. dol_syslog(get_class($this)."::setSharingsByElement echec ".$this->error, LOG_ERR);
  855. $this->db->rollback();
  856. return -1;
  857. }
  858. }
  859. /**
  860. *
  861. * @param string $element Name of element (thirdparty, product, ...)
  862. * @param int $element_id Id of current element for check sharing granularity
  863. * @param int $entity Entity to search
  864. *
  865. */
  866. public function getListOfSharingsByElement($element, $element_id = null, $entity = null)
  867. {
  868. $ret = array();
  869. $searchentity = (!empty($entity) ? (int) $entity : null);
  870. dol_syslog(get_class($this)."::getListOfSharingsByElement element=".$element." fk_element=".$element_id." entity=".$searchentity, LOG_DEBUG);
  871. if (isSharingAllByDefault($element) && !empty($element_id)) {
  872. $notshared = array();
  873. $sql = "SELECT entity";
  874. $sql.= " FROM ".MAIN_DB_PREFIX."entity_element_sharing";
  875. $sql.= " WHERE element = '" . $this->db->sanitize($element) . "'";
  876. $sql.= " AND fk_element = " . (int) $element_id;
  877. $resql = $this->db->query($sql);
  878. if ($resql) {
  879. while ($obj = $this->db->fetch_object($resql)) {
  880. $notshared[] = $obj->entity;
  881. }
  882. $this->db->free($resql);
  883. $onlysharingentities = explode(",", getEntity($element));
  884. if (is_array($onlysharingentities) && !empty($onlysharingentities)) {
  885. if (!empty($notshared)) {
  886. $onlysharingentities = array_diff($onlysharingentities, $notshared);
  887. }
  888. foreach ($onlysharingentities as $fk_entity) {
  889. $ret[$element_id][] = $fk_entity;
  890. }
  891. }
  892. return $ret;
  893. } else {
  894. $this->error = $this->db->lasterror();
  895. return -1;
  896. }
  897. } else {
  898. $sql = "SELECT rowid, entity, element, fk_element";
  899. $sql.= " FROM ".MAIN_DB_PREFIX."entity_element_sharing";
  900. $sql.= " WHERE element = '" . $this->db->sanitize($element) . "'";
  901. if (!empty($searchentity)) {
  902. $sql.= " AND entity = " . (int) $searchentity;
  903. }
  904. if (!empty($element_id)) {
  905. $sql.= " AND fk_element = " . (int) $element_id;
  906. }
  907. }
  908. dol_syslog(get_class($this)."::getListOfSharingsByElement sql=".$sql, LOG_DEBUG);
  909. $resql = $this->db->query($sql);
  910. if ($resql) {
  911. while ($obj = $this->db->fetch_object($resql)) {
  912. $ret[$obj->fk_element][] = $obj->entity;
  913. /*$ret[$obj->fk_element]['element'] = $element;
  914. $ret[$obj->fk_element]['fk_element'] = $obj->fk_element;
  915. $ret[$obj->fk_element]['entity'][] = $obj->entity;*/
  916. }
  917. $this->db->free($resql);
  918. if (empty($ret) && empty($element_id) && !empty($searchentity)) {
  919. $ret[] = 0;
  920. }
  921. return $ret;
  922. } else {
  923. $this->error = $this->db->lasterror();
  924. return -1;
  925. }
  926. }
  927. }