hook.class.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. <?php
  2. /* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. /**
  18. * \file htdocs/zapier/class/hook.class.php
  19. * \ingroup zapier
  20. * \brief This file is a CRUD class file for Zapier Hook record (Create/Read/Update/Delete)
  21. */
  22. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  23. /**
  24. * Class for Hook
  25. */
  26. class Hook extends CommonObject
  27. {
  28. /**
  29. * @var string ID to identify managed object
  30. */
  31. public $element = 'hook';
  32. /**
  33. * @var string Name of table without prefix where object is stored
  34. */
  35. public $table_element = 'zapier_hook';
  36. /**
  37. * @var int Does hook support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
  38. */
  39. public $ismultientitymanaged = 0;
  40. /**
  41. * @var int Does hook support extrafields ? 0=No, 1=Yes
  42. */
  43. public $isextrafieldmanaged = 1;
  44. /**
  45. * @var string String with name of icon for hook. Must be the part after the 'object_' into object_hook.png
  46. */
  47. public $picto = 'hook@zapier';
  48. const STATUS_DRAFT = 0;
  49. const STATUS_VALIDATED = 1;
  50. const STATUS_DISABLED = -1;
  51. /**
  52. * 'type' if the field format ('integer', 'integer:Class:pathtoclass', 'varchar(x)', 'double(24,8)', 'text', 'html', 'datetime', 'timestamp', 'float')
  53. * 'label' the translation key.
  54. * 'enabled' is a condition when the field must be managed.
  55. * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). Using a negative value means field is not shown by default on list but can be selected for viewing)
  56. * 'noteditable' says if field is not editable (1 or 0)
  57. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
  58. * 'default' is a default value for creation (can still be replaced by the global setup of default values)
  59. * 'index' if we want an index in database.
  60. * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...).
  61. * 'position' is the sort order of field.
  62. * 'searchall' is 1 if we want to search in this field when making a search from the quick search button.
  63. * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
  64. * 'css' is the CSS style to use on field. For example: 'maxwidth200'
  65. * 'help' is a string visible as a tooltip on field
  66. * 'comment' is not used. You can store here any text of your choice. It is not used by application.
  67. * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record
  68. * 'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
  69. */
  70. /**
  71. * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
  72. */
  73. public $fields = array(
  74. 'rowid' => array(
  75. 'type' => 'integer',
  76. 'label' => 'TechnicalID',
  77. 'enabled' => 1,
  78. 'visible' => -2,
  79. 'noteditable' => 1,
  80. 'notnull' => 1,
  81. 'index' => 1,
  82. 'position' => 1,
  83. 'comment' => 'Id',
  84. ),
  85. 'entity' => array(
  86. 'type' => 'integer',
  87. 'label' => 'Entity',
  88. 'enabled' => 1,
  89. 'visible' => 0,
  90. 'notnull' => 1,
  91. 'default' => 1,
  92. 'index' => 1,
  93. 'position' => 20,
  94. ),
  95. 'fk_user' => array(
  96. 'type' => 'integer',
  97. 'label' => 'UserOwner',
  98. 'enabled' => 1,
  99. 'visible' => -2,
  100. 'notnull' => 1,
  101. 'position' => 510,
  102. 'foreignkey' => 'llx_user.rowid',
  103. ),
  104. 'url' => array(
  105. 'type' => 'varchar(255)',
  106. 'label' => 'Url',
  107. 'enabled' => 1,
  108. 'visible' => 1,
  109. 'position' => 30,
  110. 'searchall' => 1,
  111. 'css' => 'minwidth200',
  112. 'help' => 'Hook url'
  113. ),
  114. 'module' => array(
  115. 'type' => 'varchar(128)',
  116. 'label' => 'Module',
  117. 'enabled' => 1,
  118. 'visible' => 1,
  119. 'position' => 30,
  120. 'searchall' => 1,
  121. 'css' => 'minwidth200',
  122. 'help' => 'Hook module'
  123. ),
  124. 'action' => array(
  125. 'type' => 'varchar(128)',
  126. 'label' => 'Action',
  127. 'enabled' => 1,
  128. 'visible' => 1,
  129. 'position' => 30,
  130. 'searchall' => 1,
  131. 'css' => 'minwidth200',
  132. 'help' => 'Hook action trigger'
  133. ),
  134. 'event' => array(
  135. 'type' => 'varchar(255)',
  136. 'label' => 'Event',
  137. 'enabled' => 1,
  138. 'visible' => 1,
  139. 'position' => 30,
  140. 'searchall' => 1,
  141. 'css' => 'minwidth200',
  142. 'help' => 'Event',
  143. 'showoncombobox' => 1,
  144. ),
  145. 'date_creation' => array(
  146. 'type' => 'datetime',
  147. 'label' => 'DateCreation',
  148. 'enabled' => 1,
  149. 'visible' => -2,
  150. 'notnull' => 1,
  151. 'position' => 500,
  152. ),
  153. 'import_key' => array(
  154. 'type' => 'varchar(14)',
  155. 'label' => 'ImportId',
  156. 'enabled' => 1,
  157. 'visible' => -2,
  158. 'notnull' => -1,
  159. 'index' => 0,
  160. 'position' => 1000,
  161. ),
  162. 'status' => array(
  163. 'type' => 'integer',
  164. 'label' => 'Status',
  165. 'enabled' => 1,
  166. 'visible' => 1,
  167. 'notnull' => 1,
  168. 'default' => 0,
  169. 'index' => 1,
  170. 'position' => 1000,
  171. 'arrayofkeyval' => array(
  172. 0 => 'Draft',
  173. 1 => 'Active',
  174. -1 => 'Canceled',
  175. ),
  176. ),
  177. );
  178. /**
  179. * @var int ID
  180. */
  181. public $rowid;
  182. /**
  183. * @var string Ref
  184. */
  185. public $ref;
  186. /**
  187. * @var int Entity
  188. */
  189. public $entity;
  190. /**
  191. * @var string label
  192. */
  193. public $label;
  194. /**
  195. * @var string url of webhook
  196. */
  197. public $url;
  198. /**
  199. * @var int ID of user owner webhook
  200. */
  201. public $fk_user;
  202. /**
  203. * @var int Status
  204. */
  205. public $status;
  206. /**
  207. * @var integer|string date_creation
  208. */
  209. public $date_creation;
  210. /**
  211. * @var integer tms
  212. */
  213. public $tms;
  214. /**
  215. * @var int ID
  216. */
  217. public $fk_user_creat;
  218. /**
  219. * @var int ID
  220. */
  221. public $fk_user_modif;
  222. /**
  223. * @var string import_key
  224. */
  225. public $import_key;
  226. /**
  227. * Constructor
  228. *
  229. * @param DoliDb $db Database handler
  230. */
  231. public function __construct(DoliDB $db)
  232. {
  233. global $conf, $langs, $user;
  234. $this->db = $db;
  235. if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) {
  236. $this->fields['rowid']['visible'] = 0;
  237. }
  238. if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
  239. $this->fields['entity']['enabled'] = 0;
  240. }
  241. // Unset fields that are disabled
  242. foreach ($this->fields as $key => $val) {
  243. if (isset($val['enabled']) && empty($val['enabled'])) {
  244. unset($this->fields[$key]);
  245. }
  246. }
  247. // Translate some data of arrayofkeyval
  248. foreach ($this->fields as $key => $val) {
  249. if (is_array($this->fields['status']['arrayofkeyval'])) {
  250. foreach ($this->fields['status']['arrayofkeyval'] as $key2 => $val2) {
  251. $this->fields['status']['arrayofkeyval'][$key2] = $langs->trans($val2);
  252. }
  253. }
  254. }
  255. }
  256. /**
  257. * Create object into database
  258. *
  259. * @param User $user User that creates
  260. * @param bool $notrigger false=launch triggers after, true=disable triggers
  261. * @return int <0 if KO, Id of created object if OK
  262. */
  263. public function create(User $user, $notrigger = false)
  264. {
  265. return $this->createCommon($user, $notrigger);
  266. }
  267. /**
  268. * Clone an object into another one
  269. *
  270. * @param User $user User that creates
  271. * @param int $fromid Id of object to clone
  272. * @return mixed New object created, <0 if KO
  273. */
  274. public function createFromClone(User $user, $fromid)
  275. {
  276. global $langs, $hookmanager, $extrafields;
  277. $error = 0;
  278. dol_syslog(__METHOD__, LOG_DEBUG);
  279. $object = new self($this->db);
  280. $this->db->begin();
  281. // Load source object
  282. $object->fetchCommon($fromid);
  283. // Reset some properties
  284. unset($object->id);
  285. unset($object->fk_user_creat);
  286. unset($object->import_key);
  287. // Clear fields
  288. $object->ref = "copy_of_".$object->ref;
  289. $object->title = $langs->trans("CopyOf")." ".$object->title;
  290. // ...
  291. // Clear extrafields that are unique
  292. if (is_array($object->array_options) && count($object->array_options) > 0) {
  293. $extrafields->fetch_name_optionals_label($this->table_element);
  294. foreach ($object->array_options as $key => $option) {
  295. $shortkey = preg_replace('/options_/', '', $key);
  296. if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
  297. // var_dump($key);
  298. // var_dump($clonedObj->array_options[$key]);
  299. // exit;
  300. unset($object->array_options[$key]);
  301. }
  302. }
  303. }
  304. // Create clone
  305. $object->context['createfromclone'] = 'createfromclone';
  306. $result = $object->createCommon($user);
  307. if ($result < 0) {
  308. $error++;
  309. $this->error = $object->error;
  310. $this->errors = $object->errors;
  311. }
  312. unset($object->context['createfromclone']);
  313. // End
  314. if (!$error) {
  315. $this->db->commit();
  316. return $object;
  317. } else {
  318. $this->db->rollback();
  319. return -1;
  320. }
  321. }
  322. /**
  323. * Load object in memory from the database
  324. *
  325. * @param int $id Id object
  326. * @param string $ref Ref
  327. * @return int <0 if KO, 0 if not found, >0 if OK
  328. */
  329. public function fetch($id, $ref = null)
  330. {
  331. $result = $this->fetchCommon($id, $ref);
  332. if ($result > 0 && !empty($this->table_element_line)) {
  333. //$this->fetchLines();
  334. }
  335. return $result;
  336. }
  337. /**
  338. * Load object lines in memory from the database
  339. *
  340. * @return int <0 if KO, 0 if not found, >0 if OK
  341. */
  342. /*public function fetchLines()
  343. {
  344. $this->lines=array();
  345. // Load lines with object MyObjectLine
  346. return count($this->lines)?1:0;
  347. }*/
  348. /**
  349. * Load list of objects in memory from the database.
  350. *
  351. * @param string $sortorder Sort Order
  352. * @param string $sortfield Sort field
  353. * @param int $limit limit
  354. * @param int $offset Offset
  355. * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
  356. * @param string $filtermode Filter mode (AND or OR)
  357. * @return array|int int <0 if KO, array of pages if OK
  358. */
  359. public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
  360. {
  361. global $conf;
  362. dol_syslog(__METHOD__, LOG_DEBUG);
  363. $records = array();
  364. $sql = 'SELECT';
  365. $sql .= ' t.rowid';
  366. // TODO Get all fields
  367. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  368. $sql .= ' WHERE t.entity = '.((int) $conf->entity);
  369. // Manage filter
  370. $sqlwhere = array();
  371. if (count($filter) > 0) {
  372. foreach ($filter as $key => $value) {
  373. if ($key == 't.rowid') {
  374. $sqlwhere[] = $key." = ".((int) $value);
  375. } elseif (strpos($key, 'date') !== false) {
  376. $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
  377. } elseif ($key == 'customsql') {
  378. $sqlwhere[] = $value;
  379. } else {
  380. $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
  381. }
  382. }
  383. }
  384. if (count($sqlwhere) > 0) {
  385. $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
  386. }
  387. if (!empty($sortfield)) {
  388. $sql .= $this->db->order($sortfield, $sortorder);
  389. }
  390. if (!empty($limit)) {
  391. $sql .= $this->db->plimit($limit, $offset);
  392. }
  393. $resql = $this->db->query($sql);
  394. if ($resql) {
  395. $num = $this->db->num_rows($resql);
  396. while ($obj = $this->db->fetch_object($resql)) {
  397. $record = new self($this->db);
  398. $record->id = $obj->rowid;
  399. // TODO Get other fields
  400. //var_dump($record->id);
  401. $records[$record->id] = $record;
  402. }
  403. $this->db->free($resql);
  404. return $records;
  405. } else {
  406. $this->errors[] = 'Error '.$this->db->lasterror();
  407. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  408. return -1;
  409. }
  410. }
  411. /**
  412. * Update object into database
  413. *
  414. * @param User $user User that modifies
  415. * @param bool $notrigger false=launch triggers after, true=disable triggers
  416. * @return int <0 if KO, >0 if OK
  417. */
  418. public function update(User $user, $notrigger = false)
  419. {
  420. return $this->updateCommon($user, $notrigger);
  421. }
  422. /**
  423. * Delete object in database
  424. *
  425. * @param User $user User that deletes
  426. * @param bool $notrigger false=launch triggers after, true=disable triggers
  427. * @return int <0 if KO, >0 if OK
  428. */
  429. public function delete(User $user, $notrigger = false)
  430. {
  431. return $this->deleteCommon($user, $notrigger);
  432. //return $this->deleteCommon($user, $notrigger, 1);
  433. }
  434. /**
  435. * Return a link to the object card (with optionaly the picto)
  436. *
  437. * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
  438. * @param string $option On what the link point to ('nolink', ...)
  439. * @param int $notooltip 1=Disable tooltip
  440. * @param string $morecss Add more css on link
  441. * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
  442. * @return string String with URL
  443. */
  444. public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
  445. {
  446. global $db, $conf, $langs, $hookmanager, $action;
  447. global $dolibarr_main_authentication, $dolibarr_main_demo;
  448. global $menumanager;
  449. if (!empty($conf->dol_no_mouse_hover)) {
  450. // Force disable tooltips
  451. $notooltip = 1;
  452. }
  453. $result = '';
  454. $label = '<u>'.$langs->trans("Hook").'</u>';
  455. $label .= '<br>';
  456. $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
  457. $url = DOL_URL_ROOT.'/zapier/hook_card.php?id='.$this->id;
  458. if ($option != 'nolink') {
  459. // Add param to save lastsearch_values or not
  460. $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
  461. if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
  462. $add_save_lastsearch_values = 1;
  463. }
  464. if ($add_save_lastsearch_values) {
  465. $url .= '&save_lastsearch_values=1';
  466. }
  467. }
  468. $linkclose = '';
  469. if (empty($notooltip)) {
  470. if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
  471. $label = $langs->trans("ShowMyObject");
  472. $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
  473. }
  474. $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
  475. $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
  476. } else {
  477. $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
  478. }
  479. $linkstart = '<a href="'.$url.'"';
  480. $linkstart .= $linkclose.'>';
  481. $linkend = '</a>';
  482. $result .= $linkstart;
  483. if ($withpicto) {
  484. $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
  485. }
  486. if ($withpicto != 2) {
  487. $result .= $this->ref;
  488. }
  489. $result .= $linkend;
  490. //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
  491. $hookmanager->initHooks(array('hookdao'));
  492. $parameters = array(
  493. 'id' => $this->id,
  494. 'getnomurl' => &$result,
  495. );
  496. // Note that $action and $object may have been modified by some hooks
  497. $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action);
  498. if ($reshook > 0) {
  499. $result = $hookmanager->resPrint;
  500. } else {
  501. $result .= $hookmanager->resPrint;
  502. }
  503. return $result;
  504. }
  505. /**
  506. * Return label of the status
  507. *
  508. * @param int $mode 0 = long label
  509. * 1 = short label
  510. * 2 = Picto + short label
  511. * 3 = Picto, 4=Picto + long label
  512. * 5 = Short label + Picto
  513. * 6 = Long label + Picto
  514. * @return string Label of status
  515. */
  516. public function getLibStatut($mode = 0)
  517. {
  518. return $this->LibStatut($this->status, $mode);
  519. }
  520. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  521. /**
  522. * Return the status
  523. *
  524. * @param int $status Id status
  525. * @param int $mode 0 = long label,
  526. * 1 = short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
  527. * @return string Label of status
  528. */
  529. public function LibStatut($status, $mode = 0)
  530. {
  531. // phpcs:enable
  532. global $langs;
  533. if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
  534. global $langs;
  535. //$langs->load("mymodule");
  536. $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Disabled');
  537. $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
  538. $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Disabled');
  539. $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
  540. }
  541. $statusType = 'status5';
  542. if ($status == self::STATUS_VALIDATED) {
  543. $statusType = 'status4';
  544. }
  545. return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
  546. }
  547. /**
  548. * Load the info information in the object
  549. *
  550. * @param int $id Id of object
  551. * @return void
  552. */
  553. public function info($id)
  554. {
  555. $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
  556. $sql .= ' fk_user_creat, fk_user_modif';
  557. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  558. $sql .= ' WHERE t.rowid = '.((int) $id);
  559. $result = $this->db->query($sql);
  560. if ($result) {
  561. if ($this->db->num_rows($result)) {
  562. $obj = $this->db->fetch_object($result);
  563. $this->id = $obj->rowid;
  564. $this->user_creation_id = $obj->fk_user_creat;
  565. $this->user_modification_id = $obj->fk_user_modif;
  566. $this->date_creation = $this->db->jdate($obj->datec);
  567. $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
  568. }
  569. $this->db->free($result);
  570. } else {
  571. dol_print_error($this->db);
  572. }
  573. }
  574. /**
  575. * Initialise object with example values
  576. * Id must be 0 if object instance is a specimen
  577. *
  578. * @return void
  579. */
  580. public function initAsSpecimen()
  581. {
  582. $this->initAsSpecimenCommon();
  583. }
  584. }