dolibarr 24.0.0-beta
xcal.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.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, see <https://www.gnu.org/licenses/>.
17 */
18
19
36function build_calfile($format, $title, $desc, $events_array, $outputfile)
37{
38 dol_syslog("xcal.lib.php::build_calfile Build cal file ".$outputfile." to format ".$format);
39
40 if (empty($outputfile)) {
41 // -1 = error
42 return -1;
43 }
44
45 $nbevents = 0;
46
47 // Note: A cal file is an UTF8 encoded file
48 $calfileh = fopen($outputfile, "w");
49
50 if ($calfileh) {
51 include_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
52
53 $now = dol_now();
54 $encoding = "";
55
56 if ($format === "vcal") {
57 $encoding = "ENCODING=QUOTED-PRINTABLE:";
58 }
59
60 // Print header
61 fwrite($calfileh, "BEGIN:VCALENDAR\n");
62
63 // version is always "2.0"
64 fwrite($calfileh, "VERSION:2.0\n");
65
66 fwrite($calfileh, "METHOD:PUBLISH\n");
67 fwrite($calfileh, "PRODID:-//DOLIBARR ".DOL_VERSION."\n");
68 fwrite($calfileh, "CALSCALE:GREGORIAN\n");
69 fwrite($calfileh, "X-WR-CALNAME:".$encoding.format_cal($format, $title)."\n");
70 fwrite($calfileh, "X-WR-CALDESC:".$encoding.format_cal($format, $desc)."\n");
71 //fwrite($calfileh,"X-WR-TIMEZONE:Europe/Paris\n");
72
73 if (getDolGlobalString('MAIN_AGENDA_EXPORT_CACHE') && getDolGlobalInt('MAIN_AGENDA_EXPORT_CACHE') > 60) {
74 $hh = convertSecondToTime(getDolGlobalInt('MAIN_AGENDA_EXPORT_CACHE'), "hour");
75 $mm = convertSecondToTime(getDolGlobalInt('MAIN_AGENDA_EXPORT_CACHE'), "min");
76 $ss = convertSecondToTime(getDolGlobalInt('MAIN_AGENDA_EXPORT_CACHE'), "sec");
77
78 fwrite($calfileh, "X-PUBLISHED-TTL: P".$hh."H".$mm."M".$ss."S\n");
79 }
80
81 foreach ($events_array as $key => $event) {
82 // See http://fr.wikipedia.org/wiki/ICalendar for format
83 // See http://www.ietf.org/rfc/rfc2445.txt for RFC
84
85 // TODO: avoid use extra event array, use objects direct thahtwas created before
86
87 $uid = $event["uid"];
88 $type = $event["type"];
89 $startdate = $event["startdate"];
90 $duration = $event["duration"];
91 $enddate = $event["enddate"];
92 $summary = $event["summary"];
93 $category = $event["category"];
94 $priority = $event["priority"];
95 $fulldayevent = $event["fulldayevent"];
96 $location = $event["location"];
97 $email = $event["email"];
98 $url = $event["url"];
99 $transparency = $event["transparency"];
100 $description = dol_string_nohtmltag(preg_replace("/<br[\s\/]?>/i", "\n", $event["desc"]), 0);
101 $created = $event["created"];
102 $modified = $event["modified"];
103 $assignedUsers = $event["assignedUsers"];
104 //print $fulldayevent.' '.dol_print_date($startdate, 'dayhour', 'gmt');
105
106 // Format
107 $summary = format_cal($format, $summary);
108 $description = format_cal($format, $description);
109 $category = format_cal($format, (string) $category);
110 $location = format_cal($format, (string) $location);
111
112 // Output the vCard/iCal VEVENT object
113 /*
114 Example from Google ical export for a 1 hour event:
115 BEGIN:VEVENT
116 DTSTART:20101103T120000Z
117 DTEND:20101103T130000Z
118 DTSTAMP:20101121T144902Z
119 UID:4eilllcsq8r1p87ncg7vc8dbpk@google.com
120 CREATED:20101121T144657Z
121 DESCRIPTION:
122 LAST-MODIFIED:20101121T144707Z
123 LOCATION:
124 SEQUENCE:0
125 STATUS:CONFIRMED
126 SUMMARY:Tâche 1 heure
127 TRANSP:OPAQUE
128 END:VEVENT
129
130 Example from Google ical export for a 1 day event:
131 BEGIN:VEVENT
132 DTSTART;VALUE=DATE:20101102
133 DTEND;VALUE=DATE:20101103
134 DTSTAMP:20101121T144902Z
135 UID:d09t43kcf1qgapu9efsmmo1m6k@google.com
136 CREATED:20101121T144607Z
137 DESCRIPTION:
138 LAST-MODIFIED:20101121T144607Z
139 LOCATION:
140 SEQUENCE:0
141 STATUS:CONFIRMED
142 SUMMARY:Tâche 1 jour
143 TRANSP:TRANSPARENT
144 END:VEVENT
145 */
146
147 if ($type === "event") {
148 $nbevents++;
149
150 fwrite($calfileh, "BEGIN:VEVENT\n");
151 fwrite($calfileh, "UID:".$uid."\n");
152
153 if (!empty($email)) {
154 fwrite($calfileh, "ORGANIZER:MAILTO:".$email."\n");
155 fwrite($calfileh, "CONTACT:MAILTO:".$email."\n");
156 }
157
158 if (!empty($url)) {
159 fwrite($calfileh, "URL:".$url."\n");
160 }
161
162 if (is_array($assignedUsers)) {
163 foreach ($assignedUsers as $assignedUser) {
164 if ($assignedUser->email === $email) {
165 continue;
166 }
167
168 fwrite($calfileh, "ATTENDEE;RSVP=TRUE:mailto:".$assignedUser->email."\n");
169 }
170 }
171
172 if ($created) {
173 fwrite($calfileh, "CREATED:".dol_print_date($created, "dayhourxcard", true)."\n");
174 }
175
176 if ($modified) {
177 fwrite($calfileh, "LAST-MODIFIED:".dol_print_date($modified, "dayhourxcard", true)."\n");
178 }
179
180 fwrite($calfileh, "SUMMARY:".$encoding.$summary."\n");
181 fwrite($calfileh, "DESCRIPTION:".$encoding.$description."\n");
182
183 if (!empty($location)) {
184 fwrite($calfileh, "LOCATION:".$encoding.$location."\n");
185 }
186
187 if ($fulldayevent) {
188 fwrite($calfileh, "X-FUNAMBOL-ALLDAY:1\n");
189 }
190
191 // see https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcical/0f262da6-c5fd-459e-9f18-145eba86b5d2
192 if ($fulldayevent) {
193 fwrite($calfileh, "X-MICROSOFT-CDO-ALLDAYEVENT:TRUE\n");
194 }
195
196 // Date must be GMT dates
197 // Current date
198 fwrite($calfileh, "DTSTAMP:".dol_print_date($now, "dayhourxcard", 'gmt')."\n");
199
200 // Start date
201 $prefix = "";
202 $startdatef = dol_print_date($startdate, "dayhourxcard", 'gmt');
203
204 if ($fulldayevent) {
205 // For fullday event, date was stored with old version by using the user timezone instead of storing the date at UTC+0
206 // in the timezone of server (so for a PHP timezone of -3, we should store '2023-05-31 21:00:00.000'
207 // Using option MAIN_STORE_FULL_EVENT_IN_GMT=1 change the behaviour to store in GMT for full day event. This must become
208 // the default behaviour but there is no way to change keeping old saved date compatible.
209 $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
210 // Local time should be used to prevent users in time zones earlier than GMT from being one day earlier
211 $prefix = ";VALUE=DATE";
212 if ($tzforfullday) {
213 $startdatef = dol_print_date($startdate, "dayxcard", 'gmt');
214 } else {
215 $startdatef = dol_print_date($startdate, "dayxcard", 'tzserver');
216 }
217 }
218
219 fwrite($calfileh, "DTSTART".$prefix.":".$startdatef."\n");
220
221 // End date
222 if ($fulldayevent) {
223 if (empty($enddate)) {
224 // We add 1 day needed for full day event (DTEND must be next day after event).
225 // This is mention in https://datatracker.ietf.org/doc/html/rfc5545:
226 // "The "DTEND" property for a "VEVENT" calendar component specifies the non-inclusive end of the event."
227 $enddate = dol_time_plus_duree($startdate, 1, "d");
228 }
229 } else {
230 if (empty($enddate)) {
231 $enddate = $startdate + $duration;
232 }
233 }
234
235 $prefix = "";
236 $enddatef = dol_print_date($enddate, "dayhourxcard", 'gmt');
237
238 if ($fulldayevent) {
239 $prefix = ";VALUE=DATE";
240 // We add 1 second so we reach the +1 day needed for full day event (DTEND must be next day after event)
241 // This is mention in https://datatracker.ietf.org/doc/html/rfc5545:
242 // "The "DTEND" property for a "VEVENT" calendar component specifies the non-inclusive end of the event."
243 $enddatef = dol_print_date($enddate + 1, "dayxcard", 'tzserver');
244 }
245
246 fwrite($calfileh, "DTEND".$prefix.":".$enddatef."\n");
247 fwrite($calfileh, "STATUS:CONFIRMED\n");
248
249 if (!empty($transparency)) {
250 fwrite($calfileh, "TRANSP:".$transparency."\n");
251 }
252
253 if (!empty($category)) {
254 fwrite($calfileh, "CATEGORIES:".$encoding.$category."\n");
255 }
256
257 fwrite($calfileh, "END:VEVENT\n");
258 }
259
260 // Output the vCard/iCal VJOURNAL object
261 if ($type === "journal") {
262 $nbevents++;
263
264 fwrite($calfileh, "BEGIN:VJOURNAL\n");
265 fwrite($calfileh, "UID:".$uid."\n");
266
267 if (!empty($email)) {
268 fwrite($calfileh, "ORGANIZER:MAILTO:".$email."\n");
269 fwrite($calfileh, "CONTACT:MAILTO:".$email."\n");
270 }
271
272 if (!empty($url)) {
273 fwrite($calfileh, "URL:".$url."\n");
274 }
275
276 if ($created) {
277 fwrite($calfileh, "CREATED:".dol_print_date($created, "dayhourxcard", 'gmt')."\n");
278 }
279
280 if ($modified) {
281 fwrite($calfileh, "LAST-MODIFIED:".dol_print_date($modified, "dayhourxcard", 'gmt')."\n");
282 }
283
284 fwrite($calfileh, "SUMMARY:".$encoding.$summary."\n");
285 fwrite($calfileh, "DESCRIPTION:".$encoding.$description."\n");
286 fwrite($calfileh, "STATUS:CONFIRMED\n");
287 fwrite($calfileh, "CATEGORIES:".$category."\n");
288 fwrite($calfileh, "LOCATION:".$location."\n");
289 fwrite($calfileh, "TRANSP:OPAQUE\n");
290 fwrite($calfileh, "CLASS:CONFIDENTIAL\n");
291 fwrite($calfileh, "DTSTAMP:".dol_print_date($startdate, "dayhourxcard", 'gmt')."\n");
292
293 fwrite($calfileh, "END:VJOURNAL\n");
294 }
295 }
296
297 // Footer
298 fwrite($calfileh, "END:VCALENDAR");
299
300 fclose($calfileh);
301 dolChmod($outputfile);
302 } else {
303 dol_syslog("xcal.lib.php::build_calfile Failed to open file ".$outputfile." for writing");
304 return -2;
305 }
306
307 return $nbevents;
308}
309
325function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter = '', $url = '', $langcode = '', $useurlforguid = false)
326{
327 global $langs, $mysoc;
329
330 dol_syslog("xcal.lib.php::build_rssfile Build rss file ".$outputfile." to format ".$format);
331
332 if (empty($outputfile)) {
333 // -1 = error
334 return -1;
335 }
336
337 $nbevents = 0;
338
339 $fichier = fopen($outputfile, "w");
340
341 if ($fichier) {
342 // Print header
343 fwrite($fichier, '<?xml version="1.0" encoding="'.$langs->charset_output.'"?>'."\n");
344
345 fwrite($fichier, '<rss version="2.0">'."\n");
346
347 fwrite($fichier, "<channel>\n");
348 fwrite($fichier, "<title>".dol_escape_xml($title)."</title>\n");
349 fwrite($fichier, "<description>".dol_escape_xml($title)."</description>\n");
350 if ($langcode) {
351 fwrite($fichier, "<language>".dol_escape_xml($langcode)."</language>\n");
352 }
353
354 // Define $urlwithroot
355 $urlwithouturlroot = preg_replace("/".preg_quote(DOL_URL_ROOT, "/")."$/i", "", trim($dolibarr_main_url_root));
356 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
357 //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
358
359 // Url
360 if (empty($url)) {
361 $url = $urlwithroot."/public/agenda/agendaexport.php?format=rss&exportkey=".urlencode(getDolGlobalString('MAIN_AGENDA_XCAL_EXPORTKEY'));
362 }
363 //fwrite($fichier, "<link><![CDATA[".$url."]]></link>\n");
364 include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
365 fwrite($fichier, "<link>".getRootURLFromURL($url)."</link>\n");
366
367 // Image
368 if (!empty($mysoc->logo_squarred_small)) {
369 $urlimage = $urlwithroot.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_squarred_small);
370 //$urlimage = $GLOBALS['website']->virtualhost
371 if ($urlimage && (empty($GLOBALS['website']) || preg_match('/'.preg_quote($GLOBALS['website']->virtualhost, '/').'/', $urlwithroot))) {
372 fwrite($fichier, "<image><url><![CDATA[".$urlimage."]]></url><title>".htmlspecialchars($title)."</title><link><![CDATA[".$url."]]></link></image>\n");
373 }
374 }
375
376 // Add a tag for some readers (Google / Feed readers) to detect that this is a RSS feed and not a generic XML file
377 fwrite($fichier, '<atom:link href="'.$url.'" rel="self" type="application/rss+xml"/>'."\n");
378
379 foreach ($events_array as $key => $event) {
380 $eventqualified = true;
381
382 if ($filter) {
383 // TODO Add a filter
384
385 $eventqualified = false;
386 }
387
388 if ($eventqualified) {
389 $nbevents++;
390
391 if (is_object($event) && get_class($event) == 'WebsitePage') {
392 // Convert object WebsitePage into an array $event
393 $tmpevent = array();
394 $tmpevent['uid'] = (string) $event->id;
395 $tmpevent['startdate'] = $event->date_creation;
396 $tmpevent['summary'] = $event->title;
397 $tmpevent['url'] = $event->fullpageurl ? $event->fullpageurl : $event->pageurl.'.php';
398 $tmpevent['author'] = $event->author_alias ? $event->author_alias : 'unknown';
399 //$tmpevent['category'] = '';
400 $tmpevent['desc'] = $event->description;
401 if (!empty($event->image)) {
402 $tmpevent['image'] = $GLOBALS['website']->virtualhost.'/medias/'.$event->image;
403 } else {
404 include_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';
405 $tmpimage = getImageFromHtmlContent($event->content);
406 if ($tmpimage) {
407 if (strpos($tmpimage, '/') === 0) { // If $tmpimage is an absolute path
408 $tmpevent['image'] = $GLOBALS['website']->virtualhost.$tmpimage;
409 } elseif (stripos($tmpimage, 'http') === 0) { // If $tmpimage is a full URI
410 $tmpevent['image'] = $tmpimage;
411 } else {
412 $tmpevent['image'] = $GLOBALS['website']->virtualhost.'/medias/'.$tmpimage;
413 } // TODO If $tmpimage is "data:..."
414 }
415 }
416 $tmpevent['content'] = $event->content;
417
418 $event = $tmpevent;
419 }
420 $uid = $event["uid"];
421 $startdate = $event["startdate"];
422 $summary = $event["summary"];
423 $description = $event["desc"];
424 $url = empty($event["url"]) ? '' : $event["url"];
425 $author = $event["author"];
426 $category = empty($event["category"]) ? null : $event["category"];
427 $image = '';
428 if (!empty($event["image"])) {
429 $image = $event["image"];
430 } else {
431 $reg = array();
432 // If we found a link into content like <img alt="..." class="..." src="..."
433 if (!empty($event["content"]) && preg_match('/<img\s*(?:alt="[^"]*"\s*)?(?:class="[^"]*"\s*)?src="([^"]+)"/m', $event["content"], $reg)) {
434 if (!empty($reg[0])) {
435 $image = $reg[1];
436 }
437 // Convert image "/medias/...." and "/viewimage.php?modulepart=medias&file=(.*)"
438 if (!empty($GLOBALS['website']->virtualhost)) {
439 if (preg_match('/^\/medias\//', $image)) {
440 $image = $GLOBALS['website']->virtualhost.$image;
441 } elseif (preg_match('/^\/viewimage\.php\?modulepart=medias&[^"]*file=([^&"]+)/', $image, $reg)) {
442 $image = $GLOBALS['website']->virtualhost.'/medias/'.$reg[1];
443 }
444 }
445 }
446 }
447
448
449 /* No place inside a RSS
450 $priority = $event["priority"];
451 $fulldayevent = $event["fulldayevent"];
452 $location = $event["location"];
453 $email = $event["email"];
454 */
455
456 $description = dol_string_nohtmltag(preg_replace("/<br[\s\/]?>/i", "\n", $event["desc"]), 0);
457
458 fwrite($fichier, "<item>\n");
459 fwrite($fichier, "<title><![CDATA[".$summary."]]></title>\n");
460 //fwrite($fichier, "<link><![CDATA[".$url."]]></link>\n");
461 fwrite($fichier, "<link>".$url."</link>\n");
462
463 //fwrite($fichier, "<author><![CDATA[".$author."]]></author>\n");
464 if (!empty($category)) {
465 fwrite($fichier, "<category><![CDATA[".$category."]]></category>\n");
466 }
467 //fwrite($fichier, "<description><![CDATA[".$summary."]]></description>\n");
468 fwrite($fichier, "<description><![CDATA[");
469 if (!empty($image)) {
470 fwrite($fichier, '<p><img class="center" src="'.$image.'"/></p>');
471 }
472 if ($description) {
473 fwrite($fichier, $description);
474 }
475 fwrite($fichier, "]]></description>\n");
476 // Note: We may also add description into content:encoded tag.
477
478 fwrite($fichier, "<pubDate>".date("r", $startdate)."</pubDate>\n");
479 if ($useurlforguid) {
480 fwrite($fichier, '<guid isPermaLink="true">'.$url.'</guid>'."\n");
481 } else {
482 fwrite($fichier, '<guid isPermaLink="false"><![CDATA['.str_pad($uid, 10, "0", STR_PAD_LEFT).']]></guid>'."\n");
483 }
484 fwrite($fichier, '<source url="'.$url.'"><![CDATA[Dolibarr]]></source>'."\n");
485 fwrite($fichier, "</item>\n");
486 }
487 }
488
489 fwrite($fichier, "</channel>");
490 fwrite($fichier, "\n");
491 fwrite($fichier, "</rss>");
492
493 fclose($fichier);
494 dolChmod($outputfile);
495 }
496
497 return $nbevents;
498}
499
507function format_cal($format, $string)
508{
509 $newstring = $string;
510
511 if ($format === "vcal") {
512 $newstring = quotedPrintEncode($newstring);
513 }
514
515 if ($format === "ical") {
516 // Replace new lines chars by "\n"
517 $newstring = preg_replace("/\r\n/i", "\\n", $newstring);
518 $newstring = preg_replace("/\n\r/i", "\\n", $newstring);
519 $newstring = preg_replace("/\n/i", "\\n", $newstring);
520
521 // Must not exceed 75 char. Cut with "\r\n"+Space
522 $newstring = calEncode($newstring);
523 }
524
525 return $newstring;
526}
527
535function calEncode($line)
536{
537 $out = "";
538 $newpara = "";
539
540 // If mb_ functions exists, it"s better to use them
541 if (function_exists("mb_strlen")) {
542 $strlength = mb_strlen($line, "UTF-8");
543
544 for ($j = 0; $j < $strlength; $j++) {
545 // Take char at position $j
546 $char = dol_substr($line, $j, 1, "UTF-8");
547
548 if ((mb_strlen($newpara, "UTF-8") + mb_strlen($char, "UTF-8")) >= 75) {
549 // CRLF + Space for cal
550 $out .= $newpara."\r\n ";
551
552 $newpara = "";
553 }
554
555 $newpara .= $char;
556 }
557
558 $out .= $newpara;
559 } else {
560 $strlength = dol_strlen($line);
561
562 for ($j = 0; $j < $strlength; $j++) {
563 // Take char at position $j
564 $char = substr($line, $j, 1);
565
566 if ((dol_strlen($newpara) + dol_strlen($char)) >= 75) {
567 // CRLF + Space for cal
568 $out .= $newpara."\r\n ";
569
570 $newpara = "";
571 }
572
573 $newpara .= $char;
574 }
575
576 $out .= $newpara;
577 }
578
579 return trim($out);
580}
581
582
590function quotedPrintEncode($str, $forcal = 0)
591{
592 $lines = preg_split("/\r\n/", $str);
593 $out = "";
594
595 foreach ($lines as $line) {
596 $newpara = "";
597
598 // Do not use dol_strlen here, we need number of bytes
599 $strlength = strlen($line);
600
601 for ($j = 0; $j < $strlength; $j++) {
602 $char = substr($line, $j, 1);
603 $ascii = ord($char);
604
605 if ($ascii < 32 || $ascii === 61 || $ascii > 126) {
606 $char = "=".strtoupper(sprintf("%02X", $ascii));
607 }
608
609 // Do not use dol_strlen here, we need number of bytes
610 if ((strlen($newpara) + strlen($char)) >= 76) {
611 // New line with carray-return (CR) and line-feed (LF)
612 $out .= $newpara."=\r\n";
613
614 // extra space for cal
615 if ($forcal) {
616 $out .= " ";
617 }
618
619 $newpara = "";
620 }
621
622 $newpara .= $char;
623 }
624
625 $out .= $newpara;
626 }
627 return trim($out);
628}
629
636function quotedPrintDecode($str)
637{
638 return trim(quoted_printable_decode(preg_replace("/=\r?\n/", "", $str)));
639}
global $dolibarr_main_url_root
global $mysoc
getImageFromHtmlContent($htmlContent, $imageNumber=1)
Return the URL of an image found into a HTML content.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:248
dol_now($mode='gmt')
Return date for now.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_escape_xml($stringtoescape)
Returns text escaped for inclusion into a XML string.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getRootURLFromURL($url)
Function root url from a long url For example: https://www.abc.mydomain.com/dir/page....
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:487
quotedPrintEncode($str, $forcal=0)
Encode into vcal format.
Definition xcal.lib.php:590
build_calfile($format, $title, $desc, $events_array, $outputfile)
Build a file from an array of events All input params and data must be encoded in $conf->charset_outp...
Definition xcal.lib.php:36
build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter='', $url='', $langcode='', $useurlforguid=false)
Build a file from an array of events.
Definition xcal.lib.php:325
format_cal($format, $string)
Encode for cal export.
Definition xcal.lib.php:507
calEncode($line)
Cut string after 75 chars.
Definition xcal.lib.php:535
quotedPrintDecode($str)
Decode vcal format.
Definition xcal.lib.php:636