dav.class.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. /* Copyright (C) 2018 Destailleur Laurent <eldy@users.sourceforge.net>
  3. *
  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/dav/dav.class.php
  19. * \ingroup dav
  20. * \brief Server DAV
  21. */
  22. /**
  23. * Define Common function to access calendar items and format it in vCalendar
  24. */
  25. class CdavLib
  26. {
  27. private $db;
  28. private $user;
  29. private $langs;
  30. /**
  31. * Constructor
  32. *
  33. * @param User $user user
  34. * @param DoliDB $db Database handler
  35. * @param Translate $langs translation
  36. */
  37. public function __construct($user, $db, $langs)
  38. {
  39. $this->user = $user;
  40. $this->db = $db;
  41. $this->langs = $langs;
  42. }
  43. /**
  44. * Base sql request for calendar events
  45. *
  46. * @param int $calid Calendard id
  47. * @param int|boolean $oid Oid
  48. * @param int|boolean $ouri Ouri
  49. * @return string
  50. */
  51. public function getSqlCalEvents($calid, $oid = false, $ouri = false)
  52. {
  53. // TODO : replace GROUP_CONCAT by
  54. $sql = 'SELECT
  55. a.tms AS lastupd,
  56. a.*,
  57. sp.firstname,
  58. sp.lastname,
  59. sp.address,
  60. sp.zip,
  61. sp.town,
  62. co.label country_label,
  63. sp.phone,
  64. sp.phone_perso,
  65. sp.phone_mobile,
  66. s.nom AS soc_nom,
  67. s.address soc_address,
  68. s.zip soc_zip,
  69. s.town soc_town,
  70. cos.label soc_country_label,
  71. s.phone soc_phone,
  72. ac.sourceuid,
  73. (SELECT GROUP_CONCAT(u.login) FROM '.MAIN_DB_PREFIX.'actioncomm_resources ar
  74. LEFT OUTER JOIN '.MAIN_DB_PREFIX.'user AS u ON (u.rowid=fk_element)
  75. WHERE ar.element_type=\'user\' AND fk_actioncomm=a.id) AS other_users
  76. FROM '.MAIN_DB_PREFIX.'actioncomm AS a';
  77. if (!$this->user->rights->societe->client->voir) { //FIXME si 'voir' on voit plus de chose ?
  78. $sql .= ' LEFT OUTER JOIN '.MAIN_DB_PREFIX.'societe_commerciaux AS sc ON (a.fk_soc = sc.fk_soc AND sc.fk_user='.((int) $this->user->id).')
  79. LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON (s.rowid = sc.fk_soc)
  80. LEFT JOIN '.MAIN_DB_PREFIX.'socpeople AS sp ON (sp.fk_soc = sc.fk_soc AND sp.rowid = a.fk_contact)
  81. LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_cdav AS ac ON (a.id = ac.fk_object)';
  82. } else {
  83. $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON (s.rowid = a.fk_soc)
  84. LEFT JOIN '.MAIN_DB_PREFIX.'socpeople AS sp ON (sp.rowid = a.fk_contact)
  85. LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_cdav AS ac ON (a.id = ac.fk_object)';
  86. }
  87. $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as co ON co.rowid = sp.fk_pays
  88. LEFT JOIN '.MAIN_DB_PREFIX.'c_country as cos ON cos.rowid = s.fk_pays
  89. WHERE a.id IN (SELECT ar.fk_actioncomm FROM '.MAIN_DB_PREFIX.'actioncomm_resources ar WHERE ar.element_type=\'user\' AND ar.fk_element='.((int) $calid).')
  90. AND a.code IN (SELECT cac.code FROM '.MAIN_DB_PREFIX.'c_actioncomm cac WHERE cac.type<>\'systemauto\')
  91. AND a.entity IN ('.getEntity('societe', 1).')';
  92. if ($oid !== false) {
  93. if ($ouri === false) {
  94. $sql .= ' AND a.id = '.intval($oid);
  95. } else {
  96. $sql .= ' AND (a.id = '.intval($oid).' OR ac.uuidext = \''.$this->db->escape($ouri).'\')';
  97. }
  98. }
  99. return $sql;
  100. }
  101. /**
  102. * Convert calendar row to VCalendar string
  103. *
  104. * @param int $calid Calendar id
  105. * @param Object $obj Object id
  106. * @return string
  107. */
  108. public function toVCalendar($calid, $obj)
  109. {
  110. /*$categ = array();
  111. if($obj->soc_client)
  112. {
  113. $nick[] = $obj->soc_code_client;
  114. $categ[] = $this->langs->transnoentitiesnoconv('Customer');
  115. }*/
  116. $location = $obj->location;
  117. // contact address
  118. if (empty($location) && !empty($obj->address)) {
  119. $location = trim(str_replace(array("\r", "\t", "\n"), ' ', $obj->address));
  120. $location = trim($location.', '.$obj->zip);
  121. $location = trim($location.' '.$obj->town);
  122. $location = trim($location.', '.$obj->country_label);
  123. }
  124. // contact address
  125. if (empty($location) && !empty($obj->soc_address)) {
  126. $location = trim(str_replace(array("\r", "\t", "\n"), ' ', $obj->soc_address));
  127. $location = trim($location.', '.$obj->soc_zip);
  128. $location = trim($location.' '.$obj->soc_town);
  129. $location = trim($location.', '.$obj->soc_country_label);
  130. }
  131. $address = explode("\n", $obj->address, 2);
  132. foreach ($address as $kAddr => $vAddr) {
  133. $address[$kAddr] = trim(str_replace(array("\r", "\t"), ' ', str_replace("\n", ' | ', trim($vAddr))));
  134. }
  135. $address[] = '';
  136. $address[] = '';
  137. if ($obj->percent == -1 && trim($obj->datep) != '') {
  138. $type = 'VEVENT';
  139. } else {
  140. $type = 'VTODO';
  141. }
  142. $timezone = date_default_timezone_get();
  143. $caldata = "BEGIN:VCALENDAR\n";
  144. $caldata .= "VERSION:2.0\n";
  145. $caldata .= "METHOD:PUBLISH\n";
  146. $caldata .= "PRODID:-//Dolibarr CDav//FR\n";
  147. $caldata .= "BEGIN:".$type."\n";
  148. $caldata .= "CREATED:".gmdate('Ymd\THis', strtotime($obj->datec))."Z\n";
  149. $caldata .= "LAST-MODIFIED:".gmdate('Ymd\THis', strtotime($obj->lastupd))."Z\n";
  150. $caldata .= "DTSTAMP:".gmdate('Ymd\THis', strtotime($obj->lastupd))."Z\n";
  151. if ($obj->sourceuid == '') {
  152. $caldata .= "UID:".$obj->id.'-ev-'.$calid.'-cal-'.constant('CDAV_URI_KEY')."\n";
  153. } else {
  154. $caldata .= "UID:".$obj->sourceuid."\n";
  155. }
  156. $caldata .= "SUMMARY:".$obj->label."\n";
  157. $caldata .= "LOCATION:".$location."\n";
  158. $caldata .= "PRIORITY:".$obj->priority."\n";
  159. if ($obj->fulldayevent) {
  160. $caldata .= "DTSTART;VALUE=DATE:".date('Ymd', strtotime($obj->datep))."\n";
  161. if ($type == 'VEVENT') {
  162. if (trim($obj->datep2) != '') {
  163. $caldata .= "DTEND;VALUE=DATE:".date('Ymd', strtotime($obj->datep2) + 1)."\n";
  164. } else {
  165. $caldata .= "DTEND;VALUE=DATE:".date('Ymd', strtotime($obj->datep) + (25 * 3600))."\n";
  166. }
  167. } elseif (trim($obj->datep2) != '') {
  168. $caldata .= "DUE;VALUE=DATE:".date('Ymd', strtotime($obj->datep2) + 1)."\n";
  169. }
  170. } else {
  171. $caldata .= "DTSTART;TZID=".$timezone.":".strtr($obj->datep, array(" "=>"T", ":"=>"", "-"=>""))."\n";
  172. if ($type == 'VEVENT') {
  173. if (trim($obj->datep2) != '') {
  174. $caldata .= "DTEND;TZID=".$timezone.":".strtr($obj->datep2, array(" "=>"T", ":"=>"", "-"=>""))."\n";
  175. } else {
  176. $caldata .= "DTEND;TZID=".$timezone.":".strtr($obj->datep, array(" "=>"T", ":"=>"", "-"=>""))."\n";
  177. }
  178. } elseif (trim($obj->datep2) != '') {
  179. $caldata .= "DUE;TZID=".$timezone.":".strtr($obj->datep2, array(" "=>"T", ":"=>"", "-"=>""))."\n";
  180. }
  181. }
  182. $caldata .= "CLASS:PUBLIC\n";
  183. if ($obj->transparency == 1) {
  184. $caldata .= "TRANSP:TRANSPARENT\n";
  185. } else {
  186. $caldata .= "TRANSP:OPAQUE\n";
  187. }
  188. if ($type == 'VEVENT') {
  189. $caldata .= "STATUS:CONFIRMED\n";
  190. } elseif ($obj->percent == 0) {
  191. $caldata .= "STATUS:NEEDS-ACTION\n";
  192. } elseif ($obj->percent == 100) {
  193. $caldata .= "STATUS:COMPLETED\n";
  194. } else {
  195. $caldata .= "STATUS:IN-PROCESS\n";
  196. $caldata .= "PERCENT-COMPLETE:".$obj->percent."\n";
  197. }
  198. $caldata .= "DESCRIPTION:";
  199. $caldata .= strtr($obj->note, array("\n"=>"\\n", "\r"=>""));
  200. if (!empty($obj->soc_nom)) {
  201. $caldata .= "\\n*DOLIBARR-SOC: ".$obj->soc_nom;
  202. }
  203. if (!empty($obj->soc_phone)) {
  204. $caldata .= "\\n*DOLIBARR-SOC-TEL: ".$obj->soc_phone;
  205. }
  206. if (!empty($obj->firstname) || !empty($obj->lastname)) {
  207. $caldata .= "\\n*DOLIBARR-CTC: ".trim($obj->firstname.' '.$obj->lastname);
  208. }
  209. if (!empty($obj->phone) || !empty($obj->phone_perso) || !empty($obj->phone_mobile)) {
  210. $caldata .= "\\n*DOLIBARR-CTC-TEL: ".trim($obj->phone.' '.$obj->phone_perso.' '.$obj->phone_mobile);
  211. }
  212. if (strpos($obj->other_users, ',')) { // several
  213. $caldata .= "\\n*DOLIBARR-USR: ".$obj->other_users;
  214. }
  215. $caldata .= "\n";
  216. $caldata .= "END:".$type."\n";
  217. $caldata .= "END:VCALENDAR\n";
  218. return $caldata;
  219. }
  220. /**
  221. * getFullCalendarObjects
  222. *
  223. * @param int $calendarId Calendar id
  224. * @param int $bCalendarData Add calendar data
  225. * @return array|string[][]
  226. */
  227. public function getFullCalendarObjects($calendarId, $bCalendarData)
  228. {
  229. $calid = ($calendarId * 1);
  230. $calevents = array();
  231. if (!$this->user->rights->agenda->myactions->read) {
  232. return $calevents;
  233. }
  234. if ($calid != $this->user->id && (!isset($this->user->rights->agenda->allactions->read) || !$this->user->rights->agenda->allactions->read)) {
  235. return $calevents;
  236. }
  237. $sql = $this->getSqlCalEvents($calid);
  238. $result = $this->db->query($sql);
  239. if ($result) {
  240. while ($obj = $this->db->fetch_object($result)) {
  241. $calendardata = $this->toVCalendar($calid, $obj);
  242. if ($bCalendarData) {
  243. $calevents[] = array(
  244. 'calendardata' => $calendardata,
  245. 'uri' => $obj->id.'-ev-'.constant('CDAV_URI_KEY'),
  246. 'lastmodified' => strtotime($obj->lastupd),
  247. 'etag' => '"'.md5($calendardata).'"',
  248. 'calendarid' => $calendarId,
  249. 'size' => strlen($calendardata),
  250. 'component' => strpos($calendardata, 'BEGIN:VEVENT') > 0 ? 'vevent' : 'vtodo',
  251. );
  252. } else {
  253. $calevents[] = array(
  254. // 'calendardata' => $calendardata, not necessary because etag+size are present
  255. 'uri' => $obj->id.'-ev-'.constant('CDAV_URI_KEY'),
  256. 'lastmodified' => strtotime($obj->lastupd),
  257. 'etag' => '"'.md5($calendardata).'"',
  258. 'calendarid' => $calendarId,
  259. 'size' => strlen($calendardata),
  260. 'component' => strpos($calendardata, 'BEGIN:VEVENT') > 0 ? 'vevent' : 'vtodo',
  261. );
  262. }
  263. }
  264. }
  265. return $calevents;
  266. }
  267. }